diff --git a/CLOBBER b/CLOBBER index f2468ed04799..80b881c90591 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Recent Android build system changes from bug 961339 and bug 946083 seem to be needs-clobbery. +Skia update from Bug 910754 needs a CLOBBER build diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index 001cdd64f211..2ea7d01ba848 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -13,6 +13,7 @@ #include "MacIOSurface.h" #include "FilterNodeSoftware.h" #include "mozilla/Assertions.h" +#include "mozilla/FloatingPoint.h" using namespace std; @@ -413,6 +414,8 @@ UpdateLinearParametersToIncludePoint(double *min_t, double *max_t, double dx, double dy, double x, double y) { + MOZ_ASSERT(IsFinite(x) && IsFinite(y)); + /** * Compute a parameter t such that a line perpendicular to the (dx,dy) * vector, passing through (start->x + dx*t, start->y + dy*t), also @@ -609,6 +612,10 @@ DrawRadialRepeatingGradient(CGContextRef cg, const RadialGradientPattern &aPatte static void DrawGradient(CGContextRef cg, const Pattern &aPattern, const CGRect &aExtents) { + if (CGRectIsEmpty(aExtents)) { + return; + } + if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) { const LinearGradientPattern& pat = static_cast(aPattern); GradientStopsCG *stops = static_cast(pat.mStops.get()); diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 433c2f205050..4ab6a14ccc2d 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -7,7 +7,8 @@ #include "SourceSurfaceSkia.h" #include "ScaledFontBase.h" #include "ScaledFontCairo.h" -#include "skia/SkDevice.h" +#include "skia/SkGpuDevice.h" +#include "skia/SkBitmapDevice.h" #include "FilterNodeSoftware.h" #ifdef USE_SKIA_GPU @@ -747,9 +748,9 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface, bool DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat) { - SkAutoTUnref device(new SkDevice(GfxFormatToSkiaConfig(aFormat), - aSize.width, aSize.height, - aFormat == SurfaceFormat::B8G8R8X8)); + SkAutoTUnref device(new SkBitmapDevice(GfxFormatToSkiaConfig(aFormat), + aSize.width, aSize.height, + aFormat == SurfaceFormat::B8G8R8X8)); SkBitmap bitmap = device->accessBitmap(true); if (!bitmap.allocPixels()) { @@ -794,7 +795,7 @@ DrawTargetSkia::InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLCont targetDescriptor.fRenderTargetHandle = 0; // GLContext always exposes the right framebuffer as id 0 SkAutoTUnref target(mGrContext->wrapBackendRenderTarget(targetDescriptor)); - SkAutoTUnref device(new SkGpuDevice(mGrContext.get(), target.get())); + SkAutoTUnref device(new SkGpuDevice(mGrContext.get(), target.get())); SkAutoTUnref canvas(new SkCanvas(device.get())); mCanvas = canvas.get(); @@ -812,18 +813,17 @@ DrawTargetSkia::SetCacheLimits(int aCount, int aSizeInBytes) void DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { - bool isOpaque = false; + SkAlphaType alphaType = kPremul_SkAlphaType; if (aFormat == SurfaceFormat::B8G8R8X8) { // We have to manually set the A channel to be 255 as Skia doesn't understand BGRX ConvertBGRXToBGRA(aData, aSize, aStride); - isOpaque = true; + alphaType = kOpaque_SkAlphaType; } SkBitmap bitmap; - bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride); + bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride, alphaType); bitmap.setPixels(aData); - bitmap.setIsOpaque(isOpaque); - SkAutoTUnref canvas(new SkCanvas(new SkDevice(bitmap))); + SkAutoTUnref canvas(new SkCanvas(new SkBitmapDevice(bitmap))); mSize = aSize; mCanvas = canvas.get(); diff --git a/gfx/2d/Scale.cpp b/gfx/2d/Scale.cpp index bb784253007f..0b5a26fadba7 100644 --- a/gfx/2d/Scale.cpp +++ b/gfx/2d/Scale.cpp @@ -18,19 +18,18 @@ bool Scale(uint8_t* srcData, int32_t srcWidth, int32_t srcHeight, int32_t srcStr SurfaceFormat format) { #ifdef USE_SKIA - bool opaque; + SkAlphaType alphaType; if (format == SurfaceFormat::B8G8R8A8) { - opaque = false; + alphaType = kPremul_SkAlphaType; } else { - opaque = true; + alphaType = kOpaque_SkAlphaType; } SkBitmap::Config config = GfxFormatToSkiaConfig(format); SkBitmap imgSrc; - imgSrc.setConfig(config, srcWidth, srcHeight, srcStride); + imgSrc.setConfig(config, srcWidth, srcHeight, srcStride, alphaType); imgSrc.setPixels(srcData); - imgSrc.setIsOpaque(opaque); // Rescaler is compatible with 32 bpp only. Convert to RGB32 if needed. if (config != SkBitmap::kARGB_8888_Config) { diff --git a/gfx/2d/SourceSurfaceSkia.cpp b/gfx/2d/SourceSurfaceSkia.cpp index a58c3aed7559..1fb99a04c2cd 100644 --- a/gfx/2d/SourceSurfaceSkia.cpp +++ b/gfx/2d/SourceSurfaceSkia.cpp @@ -78,7 +78,7 @@ SourceSurfaceSkia::InitFromData(unsigned char* aData, ConvertBGRXToBGRA(reinterpret_cast(mBitmap.getPixels()), aSize, mBitmap.rowBytes()); mBitmap.unlockPixels(); mBitmap.notifyPixelsChanged(); - mBitmap.setIsOpaque(true); + mBitmap.setAlphaType(kOpaque_SkAlphaType); } mSize = aSize; diff --git a/gfx/2d/image_operations.cpp b/gfx/2d/image_operations.cpp index a12272b9ee4d..577633d8c897 100644 --- a/gfx/2d/image_operations.cpp +++ b/gfx/2d/image_operations.cpp @@ -470,7 +470,7 @@ SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source, src_row += h * row_words; dst_row += result.rowBytes() / 4; } - result.setIsOpaque(img.isOpaque()); + result.setAlphaType(img.alphaType()); return result; #else return SkBitmap(); @@ -534,7 +534,7 @@ SkBitmap ImageOperations::ResizeBasic(const SkBitmap& source, /* sse = */ false); // Preserve the "opaque" flag for use as an optimization later. - result.setIsOpaque(source.isOpaque()); + result.setAlphaType(source.alphaType()); return result; } diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index b54f64ba5cad..77d2cd5d4405 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -499,6 +499,19 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } }, { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } }, { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } }, + // These functions are only used by Skia/GL in desktop mode. + // Other parts of Gecko should avoid using these + { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } }, { nullptr, { nullptr } }, }; diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index a483a5180a73..c1c5c59adae5 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -862,6 +862,12 @@ public: AFTER_GL_CALL; } + void fClientActiveTexture(GLenum texture) { + BEFORE_GL_CALL; + mSymbols.fClientActiveTexture(texture); + AFTER_GL_CALL; + } + void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha) { BEFORE_GL_CALL; mSymbols.fColorMask(red, green, blue, alpha); @@ -954,6 +960,12 @@ public: AFTER_GL_CALL; } + void fDisableClientState(GLenum capability) { + BEFORE_GL_CALL; + mSymbols.fDisableClientState(capability); + AFTER_GL_CALL; + } + void fDisableVertexAttribArray(GLuint index) { BEFORE_GL_CALL; mSymbols.fDisableVertexAttribArray(index); @@ -998,6 +1010,12 @@ public: AFTER_GL_CALL; } + void fEnableClientState(GLenum capability) { + BEFORE_GL_CALL; + mSymbols.fEnableClientState(capability); + AFTER_GL_CALL; + } + void fEnableVertexAttribArray(GLuint index) { BEFORE_GL_CALL; mSymbols.fEnableVertexAttribArray(index); @@ -1343,6 +1361,24 @@ public: AFTER_GL_CALL; } + void fLoadIdentity() { + BEFORE_GL_CALL; + mSymbols.fLoadIdentity(); + AFTER_GL_CALL; + } + + void fLoadMatrixf(const GLfloat *matrix) { + BEFORE_GL_CALL; + mSymbols.fLoadMatrixf(matrix); + AFTER_GL_CALL; + } + + void fMatrixMode(GLenum mode) { + BEFORE_GL_CALL; + mSymbols.fMatrixMode(mode); + AFTER_GL_CALL; + } + void fPixelStorei(GLenum pname, GLint param) { BEFORE_GL_CALL; mSymbols.fPixelStorei(pname, param); @@ -1470,6 +1506,24 @@ public: AFTER_GL_CALL; } + void fTexGeni(GLenum coord, GLenum pname, GLint param) { + BEFORE_GL_CALL; + mSymbols.fTexGeni(coord, pname, param); + AFTER_GL_CALL; + } + + void fTexGenf(GLenum coord, GLenum pname, GLfloat param) { + BEFORE_GL_CALL; + mSymbols.fTexGenf(coord, pname, param); + AFTER_GL_CALL; + } + + void fTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) { + BEFORE_GL_CALL; + mSymbols.fTexGenfv(coord, pname, params); + AFTER_GL_CALL; + } + private: void raw_fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { BEFORE_GL_CALL; @@ -1676,6 +1730,12 @@ public: AFTER_GL_CALL; } + void fVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) { + BEFORE_GL_CALL; + mSymbols.fVertexPointer(size, type, stride, pointer); + AFTER_GL_CALL; + } + void fCompileShader(GLuint shader) { BEFORE_GL_CALL; mSymbols.fCompileShader(shader); diff --git a/gfx/gl/GLContextSkia.cpp b/gfx/gl/GLContextSkia.cpp index 54c4d9f0cd93..9c46f86e6541 100644 --- a/gfx/gl/GLContextSkia.cpp +++ b/gfx/gl/GLContextSkia.cpp @@ -125,6 +125,12 @@ GrGLvoid glCompileShader_mozilla(GrGLuint shader) return sGLContext.get()->fCompileShader(shader); } +GrGLvoid glCopyTexSubImage2D_mozilla(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, + GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) +{ + return sGLContext.get()->fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + GrGLuint glCreateProgram_mozilla(void) { return sGLContext.get()->fCreateProgram(); @@ -250,6 +256,11 @@ GrGLvoid glGenTextures_mozilla(GrGLsizei n, GrGLuint* textures) return sGLContext.get()->fGenTextures(n, textures); } +GrGLvoid glGenerateMipmap_mozilla(GrGLenum target) +{ + return sGLContext.get()->fGenerateMipmap(target); +} + GrGLvoid glGetBufferParameteriv_mozilla(GrGLenum target, GrGLenum pname, GrGLint* params) { return sGLContext.get()->fGetBufferParameteriv(target, pname, params); @@ -710,6 +721,57 @@ GrGLvoid glGenVertexArrays_mozilla(GrGLsizei n, GrGLuint *arrays) { return sGLContext.get()->fGenVertexArrays(n, arrays); } +// Additional functions required for desktop GL < version 3.2 + +GrGLvoid glClientActiveTexture_mozilla(GrGLenum texture) +{ + return sGLContext.get()->fClientActiveTexture(texture); +} + +GrGLvoid glDisableClientState_mozilla(GrGLenum capability) +{ + return sGLContext.get()->fDisableClientState(capability); +} + +GrGLvoid glEnableClientState_mozilla(GrGLenum capability) +{ + return sGLContext.get()->fEnableClientState(capability); +} + +GrGLvoid glLoadMatrixf_mozilla(const GLfloat* matrix) +{ + return sGLContext.get()->fLoadMatrixf(matrix); +} + +GrGLvoid glLoadIdentity_mozilla() +{ + return sGLContext.get()->fLoadIdentity(); +} + +GrGLvoid glMatrixMode_mozilla(GrGLenum mode) +{ + return sGLContext.get()->fMatrixMode(mode); +} + +GrGLvoid glTexGeni_mozilla(GrGLenum coord, GrGLenum pname, GrGLint param) +{ + return sGLContext.get()->fTexGeni(coord, pname, param); +} + +GrGLvoid glTexGenf_mozilla(GrGLenum coord, GrGLenum pname, GrGLfloat param) +{ + return sGLContext.get()->fTexGenf(coord, pname, param); +} + +GrGLvoid glTexGenfv_mozilla(GrGLenum coord, GrGLenum pname, const GrGLfloat* param) +{ + return sGLContext.get()->fTexGenfv(coord, pname, param); +} + +GrGLvoid glVertexPointer_mozilla(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer) +{ + return sGLContext.get()->fVertexPointer(size, type, stride, pointer); +} } // extern "C" @@ -737,6 +799,7 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) i->fClearStencil = glClearStencil_mozilla; i->fColorMask = glColorMask_mozilla; i->fCompileShader = glCompileShader_mozilla; + i->fCopyTexSubImage2D = glCopyTexSubImage2D_mozilla; i->fCreateProgram = glCreateProgram_mozilla; i->fCreateShader = glCreateShader_mozilla; i->fCullFace = glCullFace_mozilla; @@ -763,6 +826,7 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) i->fGenRenderbuffers = glGenRenderbuffers_mozilla; i->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv_mozilla; i->fGenTextures = glGenTextures_mozilla; + i->fGenerateMipmap = glGenerateMipmap_mozilla; i->fGetBufferParameteriv = glGetBufferParameteriv_mozilla; i->fGetError = glGetError_mozilla; i->fGetIntegerv = glGetIntegerv_mozilla; @@ -849,6 +913,18 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) // Desktop OpenGL > 2.0 i->fDrawBuffers = glDrawBuffers_mozilla; + // Desktop OpenGL < 3.2 (which we pretend to be) + i->fClientActiveTexture = glClientActiveTexture_mozilla; + i->fDisableClientState = glDisableClientState_mozilla; + i->fEnableClientState = glEnableClientState_mozilla; + i->fLoadIdentity = glLoadIdentity_mozilla; + i->fLoadMatrixf = glLoadMatrixf_mozilla; + i->fMatrixMode = glMatrixMode_mozilla; + i->fTexGenf = glTexGenf_mozilla; + i->fTexGenfv = glTexGenfv_mozilla; + i->fTexGeni = glTexGeni_mozilla; + i->fVertexPointer = glVertexPointer_mozilla; + // We support both desktop GL and GLES2 if (context->IsGLES2()) { i->fBindingsExported = kES2_GrGLBinding; diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h index 1b5a4f8e5a0e..73c96f4c7bfc 100644 --- a/gfx/gl/GLContextSymbols.h +++ b/gfx/gl/GLContextSymbols.h @@ -313,6 +313,31 @@ struct GLContextSymbols typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage; + // These functions are only used by Skia/GL in desktop mode. + // Other parts of Gecko should avoid using these + typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTURE) (GLenum texture); + PFNGLCLIENTACTIVETEXTURE fClientActiveTexture; + typedef void (GLAPIENTRY * PFNDISABLECLIENTSTATE) (GLenum capability); + PFNDISABLECLIENTSTATE fDisableClientState; + typedef void (GLAPIENTRY * PFNENABLECLIENTSTATE) (GLenum capability); + PFNENABLECLIENTSTATE fEnableClientState; + typedef void (GLAPIENTRY * PFNLOADIDENTITY) (void); + PFNLOADIDENTITY fLoadIdentity; + typedef void (GLAPIENTRY * PFNLOADMATRIXD) (const GLdouble* matrix); + PFNLOADMATRIXD fLoadMatrixd; + typedef void (GLAPIENTRY * PFNLOADMATRIXF) (const GLfloat* matrix); + PFNLOADMATRIXF fLoadMatrixf; + typedef void (GLAPIENTRY * PFNMATRIXMODE) (GLenum mode); + PFNMATRIXMODE fMatrixMode; + typedef void (GLAPIENTRY * PFNTEXGENI) (GLenum coord, GLenum pname, GLint param); + PFNTEXGENI fTexGeni; + typedef void (GLAPIENTRY * PFNTEXGENF) (GLenum coord, GLenum pname, GLfloat param); + PFNTEXGENF fTexGenf; + typedef void (GLAPIENTRY * PFNTEXGENFV) (GLenum coord, GLenum pname, const GLfloat* param); + PFNTEXGENFV fTexGenfv; + typedef void (GLAPIENTRY * PFNVERTEXPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); + PFNVERTEXPOINTER fVertexPointer; + typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFER) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); PFNGLBLITFRAMEBUFFER fBlitFramebuffer; typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLE) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height); diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 239053b707c1..e93d04df0182 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -813,9 +813,13 @@ ContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter) } if (prev) { prev->SetNextSibling(next); + } else { + mFirstChild = next; } if (next) { next->SetPrevSibling(prev); + } else { + mLastChild = prev; } if (!aAfter) { aChild->SetPrevSibling(nullptr); diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in index 50e7ee842c70..07a77a3e9cb2 100644 --- a/gfx/skia/Makefile.in +++ b/gfx/skia/Makefile.in @@ -19,10 +19,13 @@ include $(topsrcdir)/config/rules.mk ifneq (,$(INTEL_ARCHITECTURE)) ifdef GNU_CC +SkBitmapFilter_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 SkBitmapProcState_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 SkBitmapProcState_opts_SSSE3.$(OBJ_SUFFIX): CXXFLAGS+=-mssse3 -SkBlitRow_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 SkBlitRect_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 +SkBlitRow_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 +SkBlurImage_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 +SkMorphology_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 SkUtils_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2 endif endif diff --git a/gfx/skia/README_MOZILLA b/gfx/skia/README_MOZILLA index 775321fb14f9..ef95ac716e78 100644 --- a/gfx/skia/README_MOZILLA +++ b/gfx/skia/README_MOZILLA @@ -2,4 +2,14 @@ The source from this directory was copied from the skia subversion trunk using the update.sh script. The changes made were those applied by update.sh, the addition/update of Makefile.in files for the Mozilla build system. -The subversion revision used was r8495. +The subversion revision used was r13424. + +To update to a new version of Skia: + +- Copy the entire trunk/ directory from a Skia clone to mozilla-central/gfx/skia +- cd gfx/skia && ./gyp_mozbuild + +Once that's done, use git status to view the files that have changed. Keep an eye on GrUserConfig.h +and SkUserConfig.h as those probably don't want to be overwritten by upstream versions. + +This process will be made more automatic in the future. diff --git a/gfx/skia/dump_mozbuild.py b/gfx/skia/dump_mozbuild.py new file mode 100644 index 000000000000..b5d40a65dcc7 --- /dev/null +++ b/gfx/skia/dump_mozbuild.py @@ -0,0 +1,92 @@ +# Copyright (c) 2012 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections +import os +import gyp +import gyp.common +import gyp.msvs_emulation +import json +import sys + +generator_supports_multiple_toolsets = True + +generator_wants_static_library_dependencies_adjusted = False + +generator_default_variables = { +} +for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', + 'LIB_DIR', 'SHARED_LIB_DIR']: + # Some gyp steps fail if these are empty(!). + generator_default_variables[dirname] = 'dir' +for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', + 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', + 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', + 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', + 'CONFIGURATION_NAME']: + generator_default_variables[unused] = '' + + +def CalculateVariables(default_variables, params): + generator_flags = params.get('generator_flags', {}) + for key, val in generator_flags.items(): + default_variables.setdefault(key, val) + default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + + flavor = gyp.common.GetFlavor(params) + if flavor =='win': + # Copy additional generator configuration data from VS, which is shared + # by the Windows Ninja generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + + +def CalculateGeneratorInputInfo(params): + """Calculate the generator specific info that gets fed to input (called by + gyp).""" + generator_flags = params.get('generator_flags', {}) + if generator_flags.get('adjust_static_libraries', False): + global generator_wants_static_library_dependencies_adjusted + generator_wants_static_library_dependencies_adjusted = True + +def GetOS(params): + for d in params['defines']: + pass + +def GenerateOutput(target_list, target_dicts, data, params): + # Map of target -> list of targets it depends on. + edges = {} + + # Queue of targets to visit. + targets_to_visit = target_list[:] + + sources = []; + + while len(targets_to_visit) > 0: + target = targets_to_visit.pop() + if target in edges: + continue + edges[target] = [] + + target_sources = target_dicts[target].get('sources') + if target_sources: + for source in target_sources: + if source.endswith('.cpp'): + sources.append(source) + + for dep in target_dicts[target].get('dependencies', []): + edges[target].append(dep) + targets_to_visit.append(dep) + + skia_os = data['gyp/core.gyp']['variables']['skia_os%'] + + f = open('sources.json', 'w') + json.dump(sources, f) + f.close() \ No newline at end of file diff --git a/gfx/skia/generate_mozbuild.py b/gfx/skia/generate_mozbuild.py new file mode 100755 index 000000000000..be32cc1c18ed --- /dev/null +++ b/gfx/skia/generate_mozbuild.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python + +import os + +import locale +locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + +footer = """ + +# left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with +if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: + SOURCES += [ + 'trunk/src/opts/memset.arm.S', + ] + +MSVC_ENABLE_PGO = True + +FINAL_LIBRARY = 'gkmedias' +LOCAL_INCLUDES += [ + 'trunk/include/config', + 'trunk/include/core', + 'trunk/include/effects', + 'trunk/include/gpu', + 'trunk/include/images', + 'trunk/include/lazy', + 'trunk/include/pathops', + 'trunk/include/pipe', + 'trunk/include/ports', + 'trunk/include/utils', + 'trunk/include/utils/mac', + 'trunk/include/utils/win', + 'trunk/include/views', + 'trunk/src/core', + 'trunk/src/gpu', + 'trunk/src/gpu/effects', + 'trunk/src/gpu/gl', + 'trunk/src/image', + 'trunk/src/lazy', + 'trunk/src/opts', + 'trunk/src/sfnt', + 'trunk/src/utils', + 'trunk/src/utils/android', + 'trunk/src/utils/mac', + 'trunk/src/utils/win', +] + +DEFINES['SK_A32_SHIFT'] = 24 +DEFINES['SK_R32_SHIFT'] = 16 +DEFINES['SK_G32_SHIFT'] = 8 +DEFINES['SK_B32_SHIFT'] = 0 + +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'cocoa'): + DEFINES['SK_USE_POSIX_THREADS'] = 1 + +if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']: + DEFINES['SK_BUILD_SSSE3'] = 1 + +if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or \ + (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or \ + CONFIG['MOZ_WIDGET_GTK']: + DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1 + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + DEFINES['SKIA_DLL'] = 1 + +DEFINES['SKIA_IMPLEMENTATION'] = 1 +DEFINES['GR_IMPLEMENTATION'] = 1 +""" + +import json + +platforms = ['linux', 'mac', 'android', 'win'] + +custom_includes = { + 'trunk/src/ports/SkAtomics_android.h': True, + 'trunk/src/ports/SkAtomics_sync.h': True, + 'trunk/src/ports/SkAtomics_win.h': True, + 'trunk/src/ports/SkMutex_pthread.h': True, + 'trunk/src/ports/SkMutex_win.h': True +} + +def generate_includes(): + includes = {} + for root, dirs, files in os.walk('trunk/include'): + for name in files: + if name.endswith('.h'): + includes[os.path.join(root, name)] = True + + return dict(includes.items() + custom_includes.items()) + +def generate_opt_sources(): + opt_sources = {'opts': {''}} + for root, dirs, files in os.walk('trunk/src/opts'): + for name in files: + if name.endswith('.cpp'): + opt_sources['opts'].add(os.path.join(root, name)) + + return opt_sources + +def generate_platform_sources(): + sources = {} + + for plat in platforms: + if os.system("cd trunk && GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=%s gyp/skia_lib.gyp" % plat) != 0: + print 'Failed to generate sources for ' + plat + continue + + + f = open('trunk/sources.json'); + sources[plat] = set(json.load(f)); + f.close() + + return dict(sources.items() + generate_opt_sources().items()) + + +def generate_separated_sources(platform_sources): + blacklist = [ + 'ChromeUtils', + 'SkImageDecoder_', + '_gif', + 'SkFontConfigParser_android', + 'SkJpeg', + 'SkXML', + 'SkCity', + 'GrGLCreateNativeInterface', + 'fontconfig', + '_neon', + 'SkImage_Codec', + 'SkBitmapChecksummer', + 'SkNativeGLContext', + 'SkFontConfig', + 'SkFontHost_win_dw', + 'SkForceLinking', + 'SkMovie', + 'SkImageDecoder', + 'SkImageEncoder', + 'SkBitmapHasher', + 'SkWGL', + 'SkImages', + 'SkDiscardableMemory_ashmem' + ] + + def isblacklisted(value): + for item in blacklist: + if value.find(item) >= 0: + return True + + return False + + separated = { + 'common': { + #'trunk/src/effects/gradients/SkGradientTileProc.cpp', + 'trunk/src/gpu/gl/GrGLCreateNativeInterface_none.cpp', + 'trunk/src/ports/SkDiscardableMemory_none.cpp', + 'trunk/src/ports/SkImageDecoder_empty.cpp', + # 'trunk/src/images/SkImages.cpp', + # 'trunk/src/images/SkImageRef.cpp', + # 'trunk/src/images/SkImageRef_GlobalPool.cpp', + # 'trunk/src/images/SkImageRefPool.cpp', + # 'trunk/src/images/SkImageDecoder.cpp', + # 'trunk/src/images/SkImageDecoder_Factory.cpp', + }, + 'android': { + # 'trunk/src/ports/SkDebug_android.cpp', + 'trunk/src/ports/SkFontHost_cairo.cpp', + # 'trunk/src/ports/SkFontHost_FreeType.cpp', + # 'trunk/src/ports/SkFontHost_FreeType_common.cpp', + # 'trunk/src/ports/SkThread_pthread.cpp', + # 'trunk/src/ports/SkPurgeableMemoryBlock_android.cpp', + # 'trunk/src/ports/SkTime_Unix.cpp', + # 'trunk/src/utils/SkThreadUtils_pthread.cpp', + # 'trunk/src/utils/SkThreadUtils_pthread_other.cpp', + # 'trunk/src/images/SkImageRef_ashmem.cpp', + # 'trunk/src/utils/android/ashmem.cpp', + }, + 'linux': { + 'trunk/src/ports/SkFontHost_cairo.cpp', + }, + 'intel': { + 'trunk/src/opts/SkXfermode_opts_none.cpp', + }, + 'arm': { + 'trunk/src/opts/SkUtils_opts_arm.cpp', + }, + 'none': { + 'trunk/src/opts/SkUtils_opts_none.cpp', + } + } + + for plat in platform_sources.keys(): + if not separated.has_key(plat): + separated[plat] = set() + + for value in platform_sources[plat]: + if isblacklisted(value): + continue + + if value.find('_SSE') > 0 or value.find('_SSSE') > 0: #lol + separated['intel'].add(value) + continue + + if value.find('_arm') > 0 or value.find('_neon') > 0: + separated['arm'].add(value) + continue + + if value.find('_none') > 0: + separated['none'].add(value) + continue + + found = True + for other in platforms: + if other == plat or not platform_sources.has_key(other): + continue + + if not value in platform_sources[other]: + found = False + break; + + if found: + separated['common'].add(value) + else: + separated[plat].add(value) + + return separated + +def uniq(seq): + seen = set() + seen_add = seen.add + return [ x for x in seq if x not in seen and not seen_add(x)] + +def write_list(f, name, values, indent): + def write_indent(indent): + for _ in range(indent): + f.write(' ') + + val_list = uniq(sorted(map(lambda val: val.replace('../', 'trunk/'), values), key=lambda x: x.lower())) + + if len(val_list) == 0: + return + + write_indent(indent) + f.write(name + ' += [\n') + for val in val_list: + write_indent(indent + 4) + f.write('\'' + val + '\',\n') + + write_indent(4) + f.write(']\n') + +def write_mozbuild(includes, sources): + filename = 'moz.build' + f = open(filename, 'w') + + + write_list(f, 'EXPORTS.skia', includes, 0) + + write_list(f, 'SOURCES', sources['common'], 0) + + f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):\n") + write_list(f, 'SOURCES', sources['android'], 4) + + f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':\n") + write_list(f, 'SOURCES', sources['mac'], 4) + + f.write("if CONFIG['MOZ_WIDGET_GTK']:\n") + write_list(f, 'SOURCES', sources['linux'], 4) + + f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n") + write_list(f, 'SOURCES', sources['win'], 4) + + f.write("\n\n") + f.write("if CONFIG['INTEL_ARCHITECTURE']:\n") + write_list(f, 'SOURCES', sources['intel'], 4) + + f.write("elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:\n") + write_list(f, 'SOURCES', sources['arm'], 4) + + f.write("else:\n") + write_list(f, 'SOURCES', sources['none'], 4) + + f.write(footer) + + f.close() + + print 'Wrote ' + filename + +def main(): + includes = generate_includes() + platform_sources = generate_platform_sources() + separated_sources = generate_separated_sources(platform_sources) + write_mozbuild(includes, separated_sources) + + +if __name__ == '__main__': + main() diff --git a/gfx/skia/gyp_mozbuild b/gfx/skia/gyp_mozbuild new file mode 100755 index 000000000000..c5e53b69e87c --- /dev/null +++ b/gfx/skia/gyp_mozbuild @@ -0,0 +1,13 @@ +#!/bin/bash + +# Install our generator +cp dump_mozbuild.py trunk/third_party/externals/gyp/pylib/gyp/generator + +# pushd trunk +# for OS in win linux mac; do +# GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=$OS -D arm_neon=0 gyp/effects.gyp +# done +# popd + +./generate_mozbuild.py + diff --git a/gfx/skia/include/config/sk_stdint.h b/gfx/skia/include/config/sk_stdint.h deleted file mode 100644 index 360755e75b6f..000000000000 --- a/gfx/skia/include/config/sk_stdint.h +++ /dev/null @@ -1,23 +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 sk_stdint_DEFINED -#define sk_stdint_DEFINED - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned uint32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; - -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - -#endif diff --git a/gfx/skia/include/core/SkColorTable.h b/gfx/skia/include/core/SkColorTable.h deleted file mode 100644 index f8d1ccf07b7a..000000000000 --- a/gfx/skia/include/core/SkColorTable.h +++ /dev/null @@ -1,112 +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 SkColorTable_DEFINED -#define SkColorTable_DEFINED - -#include "SkColor.h" -#include "SkFlattenable.h" - -/** \class SkColorTable - - SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by - 8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable. -*/ -class SkColorTable : public SkFlattenable { -public: - SK_DECLARE_INST_COUNT(SkColorTable) - - /** Makes a deep copy of colors. - */ - SkColorTable(const SkColorTable& src); - /** Preallocates the colortable to have 'count' colors, which - * are initially set to 0. - */ - explicit SkColorTable(int count); - SkColorTable(const SkPMColor colors[], int count); - virtual ~SkColorTable(); - - enum Flags { - kColorsAreOpaque_Flag = 0x01 //!< if set, all of the colors in the table are opaque (alpha==0xFF) - }; - /** Returns the flag bits for the color table. These can be changed with setFlags(). - */ - unsigned getFlags() const { return fFlags; } - /** Set the flags for the color table. See the Flags enum for possible values. - */ - void setFlags(unsigned flags); - - bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; } - void setIsOpaque(bool isOpaque); - - /** Returns the number of colors in the table. - */ - int count() const { return fCount; } - - /** Returns the specified color from the table. In the debug build, this asserts that - the index is in range (0 <= index < count). - */ - SkPMColor operator[](int index) const { - SkASSERT(fColors != NULL && (unsigned)index < fCount); - return fColors[index]; - } - - /** Specify the number of colors in the color table. This does not initialize the colors - to any value, just allocates memory for them. To initialize the values, either call - setColors(array, count), or follow setCount(count) with a call to - lockColors()/{set the values}/unlockColors(true). - */ -// void setColors(int count) { this->setColors(NULL, count); } -// void setColors(const SkPMColor[], int count); - - /** Return the array of colors for reading and/or writing. This must be - balanced by a call to unlockColors(changed?), telling the colortable if - the colors were changed during the lock. - */ - SkPMColor* lockColors() { - SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);) - return fColors; - } - /** Balancing call to lockColors(). If the colors have been changed, pass true. - */ - void unlockColors(bool changed); - - /** Similar to lockColors(), lock16BitCache() returns the array of - RGB16 colors that mirror the 32bit colors. However, this function - will return null if kColorsAreOpaque_Flag is not set. - Also, unlike lockColors(), the returned array here cannot be modified. - */ - const uint16_t* lock16BitCache(); - /** Balancing call to lock16BitCache(). - */ - void unlock16BitCache() { - SkASSERT(f16BitCacheLockCount > 0); - SkDEBUGCODE(f16BitCacheLockCount -= 1); - } - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorTable) - -protected: - explicit SkColorTable(SkFlattenableReadBuffer&); - void flatten(SkFlattenableWriteBuffer&) const; - -private: - SkPMColor* fColors; - uint16_t* f16BitCache; - uint16_t fCount; - uint8_t fFlags; - SkDEBUGCODE(int fColorLockCount;) - SkDEBUGCODE(int f16BitCacheLockCount;) - - void inval16BitCache(); - - typedef SkFlattenable INHERITED; -}; - -#endif diff --git a/gfx/skia/include/core/SkDataSet.h b/gfx/skia/include/core/SkDataSet.h deleted file mode 100644 index 2e5d96e68ab2..000000000000 --- a/gfx/skia/include/core/SkDataSet.h +++ /dev/null @@ -1,88 +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 SkDataSet_DEFINED -#define SkDataSet_DEFINED - -#include "SkData.h" -#include "SkFlattenable.h" - -class SkStream; -class SkWStream; - -class SkDataSet : public SkFlattenable { -public: - /** - * Returns a new empty dataset. Note: since SkDataSet is immutable, this - * "new" set may be the same one that was returned before, but each - * returned object must have its reference-count balanced regardless. - * - * SkDataSet* empty = SkDataSet::NewEmpty(); - * ... - * empty->unref(); - */ - static SkDataSet* NewEmpty(); - - struct Pair { - const char* fKey; - SkData* fValue; - }; - - SkDataSet(const char key[], SkData* value); - SkDataSet(const Pair[], int count); - virtual ~SkDataSet(); - - bool isEmpty() const { return 0 == fCount; } - int count() const { return fCount; } - SkData* find(const char name[]) const; - - class Iter { - public: - Iter(const SkDataSet& ds) { - fPair = ds.fPairs; - fStop = ds.fPairs + ds.fCount; - } - - const char* key() const { - SkASSERT(!this->done()); - return fPair->fKey; - } - - SkData* value() const { - SkASSERT(!this->done()); - return fPair->fValue; - } - - bool done() const { return fPair >= fStop; } - void next() { - SkASSERT(!this->done()); - fPair += 1; - } - - private: - const SkDataSet::Pair* fPair; - const SkDataSet::Pair* fStop; - }; - - explicit SkDataSet(SkStream*); - void writeToStream(SkWStream*) const; - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataSet) - -protected: - SkDataSet(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - -private: - int32_t fCount; - uint32_t fKeySize; - Pair* fPairs; - - typedef SkFlattenable INHERITED; -}; - -#endif diff --git a/gfx/skia/include/core/SkFlattenableBuffers.h b/gfx/skia/include/core/SkFlattenableBuffers.h deleted file mode 100644 index f5b853c5ac47..000000000000 --- a/gfx/skia/include/core/SkFlattenableBuffers.h +++ /dev/null @@ -1,175 +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 SkFlattenableBuffers_DEFINED -#define SkFlattenableBuffers_DEFINED - -#include "SkColor.h" -#include "SkPaint.h" -#include "SkPoint.h" - -class SkBitmap; -class SkFlattenable; -struct SkIRect; -class SkMatrix; -class SkOrderedReadBuffer; -class SkOrderedWriteBuffer; -class SkPath; -class SkPixelRef; -struct SkRect; -class SkRefCnt; -class SkRegion; -class SkStream; -class SkString; -class SkTypeface; -class SkWStream; - -class SkFlattenableReadBuffer { -public: - SkFlattenableReadBuffer(); - virtual ~SkFlattenableReadBuffer(); - - bool isOrderedBinaryBuffer() { return NULL != getOrderedBinaryBuffer(); } - virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() { return NULL; } - - enum Flags { - kCrossProcess_Flag = 1 << 0, - kScalarIsFloat_Flag = 1 << 1, - kPtrIs64Bit_Flag = 1 << 2, - }; - - void setFlags(uint32_t flags) { fFlags = flags; } - uint32_t getFlags() const { return fFlags; } - - bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); } - bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); } - bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); } - - // primitives - virtual bool readBool() = 0; - virtual SkColor readColor() = 0; - virtual SkFixed readFixed() = 0; - virtual int32_t readInt() = 0; - virtual SkScalar readScalar() = 0; - virtual uint32_t readUInt() = 0; - virtual int32_t read32() = 0; - - // strings -- the caller is responsible for freeing the string contents - virtual char* readString() = 0; - virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) = 0; - - // common data structures - virtual SkFlattenable* readFlattenable() = 0; - virtual void readPoint(SkPoint* point) = 0; - virtual void readMatrix(SkMatrix* matrix) = 0; - virtual void readIRect(SkIRect* rect) = 0; - virtual void readRect(SkRect* rect) = 0; - virtual void readRegion(SkRegion* region) = 0; - virtual void readPath(SkPath* path) = 0; - - // binary data and arrays - virtual uint32_t readByteArray(void* value) = 0; - virtual uint32_t readColorArray(SkColor* colors) = 0; - virtual uint32_t readIntArray(int32_t* values) = 0; - virtual uint32_t readPointArray(SkPoint* points) = 0; - virtual uint32_t readScalarArray(SkScalar* values) = 0; - - /** This helper peeks into the buffer and reports back the length of the next array in - * the buffer but does not change the state of the buffer. - */ - virtual uint32_t getArrayCount() = 0; - - // helper functions - virtual void* readFunctionPtr(); - virtual void readPaint(SkPaint* paint); - - virtual void readBitmap(SkBitmap* bitmap) = 0; - virtual SkTypeface* readTypeface() = 0; - - // helper function for classes with const SkPoint members - SkPoint readPoint() { - SkPoint point; - this->readPoint(&point); - return point; - } - - template T* readFlattenableT() { - return static_cast(this->readFlattenable()); - } - -private: - uint32_t fFlags; -}; - -/////////////////////////////////////////////////////////////////////////////// - -class SkFlattenableWriteBuffer { -public: - SkFlattenableWriteBuffer(); - virtual ~SkFlattenableWriteBuffer(); - - virtual bool isOrderedBinaryBuffer() { return false; } - virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() { sk_throw(); return NULL; } - - // primitives - virtual void writeByteArray(const void* data, size_t size) = 0; - virtual void writeBool(bool value) = 0; - virtual void writeFixed(SkFixed value) = 0; - virtual void writeScalar(SkScalar value) = 0; - virtual void writeScalarArray(const SkScalar* value, uint32_t count) = 0; - virtual void writeInt(int32_t value) = 0; - virtual void writeIntArray(const int32_t* value, uint32_t count) = 0; - virtual void writeUInt(uint32_t value) = 0; - virtual void write32(int32_t value) = 0; // printf in hex - virtual void writeString(const char* value) = 0; - virtual void writeEncodedString(const void* value, size_t byteLength, - SkPaint::TextEncoding encoding) = 0; - - // common data structures - virtual void writeFlattenable(SkFlattenable* flattenable) = 0; - virtual void writeColor(const SkColor& color) = 0; - virtual void writeColorArray(const SkColor* color, uint32_t count) = 0; - virtual void writePoint(const SkPoint& point) = 0; - virtual void writePointArray(const SkPoint* points, uint32_t count) = 0; - virtual void writeMatrix(const SkMatrix& matrix) = 0; - virtual void writeIRect(const SkIRect& rect) = 0; - virtual void writeRect(const SkRect& rect) = 0; - virtual void writeRegion(const SkRegion& region) = 0; - virtual void writePath(const SkPath& path) = 0; - virtual size_t writeStream(SkStream* stream, size_t length) = 0; - - // helper functions - virtual void writeFunctionPtr(void* ptr); - virtual void writePaint(const SkPaint& paint); - - virtual void writeBitmap(const SkBitmap& bitmap) = 0; - virtual void writeTypeface(SkTypeface* typeface) = 0; - - virtual bool writeToStream(SkWStream*) = 0; - - enum Flags { - kCrossProcess_Flag = 0x01, - }; - - uint32_t getFlags() const { return fFlags; } - void setFlags(uint32_t flags) { fFlags = flags; } - - bool isCrossProcess() const { - return SkToBool(fFlags & kCrossProcess_Flag); - } - - bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; } - -protected: - // A helper function so that each subclass does not have to be a friend of SkFlattenable - void flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer); - - uint32_t fFlags; -}; - -#endif diff --git a/gfx/skia/include/core/SkImage.h b/gfx/skia/include/core/SkImage.h deleted file mode 100644 index b8ebc3aca57f..000000000000 --- a/gfx/skia/include/core/SkImage.h +++ /dev/null @@ -1,100 +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 SkImage_DEFINED -#define SkImage_DEFINED - -#include "SkRefCnt.h" -#include "SkScalar.h" - -class SkData; -class SkCanvas; -class SkPaint; -class SkShader; -class GrContext; -class GrTexture; - -// need for TileMode -#include "SkShader.h" - -////// EXPERIMENTAL - -/** - * SkImage is an abstraction for drawing a rectagle of pixels, though the - * particular type of image could be actually storing its data on the GPU, or - * as drawing commands (picture or PDF or otherwise), ready to be played back - * into another canvas. - * - * The content of SkImage is always immutable, though the actual storage may - * change, if for example that image can be re-created via encoded data or - * other means. - */ -class SkImage : public SkRefCnt { -public: - SK_DECLARE_INST_COUNT(SkImage) - - enum ColorType { - kAlpha_8_ColorType, - kRGB_565_ColorType, - kRGBA_8888_ColorType, - kBGRA_8888_ColorType, - kPMColor_ColorType, - - kLastEnum_ColorType = kPMColor_ColorType - }; - - enum AlphaType { - kIgnore_AlphaType, - kOpaque_AlphaType, - kPremul_AlphaType, - kUnpremul_AlphaType, - - kLastEnum_AlphaType = kUnpremul_AlphaType - }; - - struct Info { - int fWidth; - int fHeight; - ColorType fColorType; - AlphaType fAlphaType; - }; - - static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes); - static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes); - static SkImage* NewEncodedData(SkData*); - static SkImage* NewTexture(GrTexture*); - - int width() const { return fWidth; } - int height() const { return fHeight; } - uint32_t uniqueID() const { return fUniqueID; } - - SkShader* newShaderClamp() const; - SkShader* newShader(SkShader::TileMode, SkShader::TileMode) const; - - void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); - -protected: - SkImage(int width, int height) : - fWidth(width), - fHeight(height), - fUniqueID(NextUniqueID()) { - - SkASSERT(width >= 0); - SkASSERT(height >= 0); - } - -private: - const int fWidth; - const int fHeight; - const uint32_t fUniqueID; - - static uint32_t NextUniqueID(); - - typedef SkRefCnt INHERITED; -}; - -#endif diff --git a/gfx/skia/include/core/SkImageFilter.h b/gfx/skia/include/core/SkImageFilter.h deleted file mode 100644 index 6cc53c0de0ad..000000000000 --- a/gfx/skia/include/core/SkImageFilter.h +++ /dev/null @@ -1,171 +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 SkImageFilter_DEFINED -#define SkImageFilter_DEFINED - -#include "SkFlattenable.h" - -class SkBitmap; -class SkColorFilter; -class SkDevice; -class SkMatrix; -struct SkIPoint; -struct SkIRect; -class SkShader; -class GrEffectRef; -class GrTexture; - -/** - * Experimental. - * - * Base class for image filters. If one is installed in the paint, then - * all drawing occurs as usual, but it is as if the drawing happened into an - * offscreen (before the xfermode is applied). This offscreen bitmap will - * then be handed to the imagefilter, who in turn creates a new bitmap which - * is what will finally be drawn to the device (using the original xfermode). - * - * THIS SIGNATURE IS TEMPORARY - * - * There are several weaknesses in this function signature: - * 1. Does not expose the destination/target device, so filters that can draw - * directly to it are unable to take advantage of that optimization. - * 2. Does not expose a way to create a "compabitible" image (i.e. gpu -> gpu) - * 3. As with #1, the filter is unable to "read" the dest (which would be slow) - * - * Therefore, we should not create any real dependencies on this API yet -- it - * is being checked in as a check-point so we can explore these and other - * considerations. - */ -class SK_API SkImageFilter : public SkFlattenable { -public: - SK_DECLARE_INST_COUNT(SkImageFilter) - - class Proxy { - public: - virtual ~Proxy() {}; - - virtual SkDevice* createDevice(int width, int height) = 0; - // returns true if the proxy can handle this filter natively - virtual bool canHandleImageFilter(SkImageFilter*) = 0; - // returns true if the proxy handled the filter itself. if this returns - // false then the filter's code will be called. - virtual bool filterImage(SkImageFilter*, const SkBitmap& src, - const SkMatrix& ctm, - SkBitmap* result, SkIPoint* offset) = 0; - }; - - /** - * Request a new (result) image to be created from the src image. - * If the src has no pixels (isNull()) then the request just wants to - * receive the config and width/height of the result. - * - * The matrix is the current matrix on the canvas. - * - * Offset is the amount to translate the resulting image relative to the - * src when it is drawn. - * - * If the result image cannot be created, return false, in which case both - * the result and offset parameters will be ignored by the caller. - */ - bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm, - SkBitmap* result, SkIPoint* offset); - - /** - * Given the src bounds of an image, this returns the bounds of the result - * image after the filter has been applied. - */ - bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst); - - /** - * Returns true if the filter can be expressed a single-pass - * GrEffect, used to process this filter on the GPU, or false if - * not. - * - * If effect is non-NULL, a new GrEffect instance is stored - * in it. The caller assumes ownership of the stage, and it is up to the - * caller to unref it. - * - * The effect can assume its vertexCoords space maps 1-to-1 with texels - * in the texture. - */ - virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const; - - /** - * Returns true if the filter can be processed on the GPU. This is most - * often used for multi-pass effects, where intermediate results must be - * rendered to textures. For single-pass effects, use asNewEffect(). - * The default implementation returns false. - */ - virtual bool canFilterImageGPU() const; - - /** - * Process this image filter on the GPU. src is the source image for - * processing, as a texture-backed bitmap. result is the destination - * bitmap, which should contain a texture-backed pixelref on success. - * The default implementation returns returns false and ignores the - * result parameter. - */ - virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result); - - /** - * Returns whether this image filter is a color filter and puts the color filter into the - * "filterPtr" parameter if it can. Does nothing otherwise. - * If this returns false, then the filterPtr is unchanged. - * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler - * (i.e. it may not be set to NULL). - */ - virtual bool asColorFilter(SkColorFilter** filterPtr) const; - - /** - * Returns the number of inputs this filter will accept (some inputs can - * be NULL). - */ - int countInputs() const { return fInputCount; } - - /** - * Returns the input filter at a given index, or NULL if no input is - * connected. The indices used are filter-specific. - */ - SkImageFilter* getInput(int i) const { - SkASSERT(i < fInputCount); - return fInputs[i]; - } - -protected: - SkImageFilter(int inputCount, SkImageFilter** inputs); - - // Convenience constructor for 1-input filters. - explicit SkImageFilter(SkImageFilter* input); - - // Convenience constructor for 2-input filters. - SkImageFilter(SkImageFilter* input1, SkImageFilter* input2); - - virtual ~SkImageFilter(); - - explicit SkImageFilter(SkFlattenableReadBuffer& rb); - - virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE; - - // Default impl returns false - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset); - // Default impl copies src into dst and returns true - virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*); - - // Return the result of processing the given input, or the source bitmap - // if we have no connected input at that index. - SkBitmap getInputResult(int index, Proxy*, const SkBitmap& src, const SkMatrix&, - SkIPoint*); - -private: - typedef SkFlattenable INHERITED; - int fInputCount; - SkImageFilter** fInputs; -}; - -#endif diff --git a/gfx/skia/include/core/SkImageTypes.h b/gfx/skia/include/core/SkImageTypes.h deleted file mode 100644 index 541c3884a512..000000000000 --- a/gfx/skia/include/core/SkImageTypes.h +++ /dev/null @@ -1,39 +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 SkImageTypes_DEFINED -#define SkImageTypes_DEFINED - -#include "SkTypes.h" - -enum SkColorType { - kAlpha_8_SkColorType, - kRGB_565_SkColorType, -// kRGBA_8888_SkColorType, -// kBGRA_8888_SkColorType, - kPMColor_SkColorType, - - kLastEnum_SkColorType = kPMColor_SkColorType -}; - -enum SkAlphaType { -// kIgnore_SkAlphaType, - kOpaque_SkAlphaType, -// kUnpremul_SkAlphaType, - kPremul_SkAlphaType, - - kLastEnum_SkAlphaType = kPremul_SkAlphaType -}; - -struct SkImageInfo { - int fWidth; - int fHeight; - SkColorType fColorType; - SkAlphaType fAlphaType; -}; - -#endif diff --git a/gfx/skia/include/core/SkMallocPixelRef.h b/gfx/skia/include/core/SkMallocPixelRef.h deleted file mode 100644 index 2241a513e7ea..000000000000 --- a/gfx/skia/include/core/SkMallocPixelRef.h +++ /dev/null @@ -1,51 +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 SkMallocPixelRef_DEFINED -#define SkMallocPixelRef_DEFINED - -#include "SkPixelRef.h" - -/** We explicitly use the same allocator for our pixels that SkMask does, - so that we can freely assign memory allocated by one class to the other. -*/ -class SkMallocPixelRef : public SkPixelRef { -public: - /** Allocate the specified buffer for pixels. The memory is freed when the - last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw() - is called to allocate it. - */ - SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable, bool ownPixels = true); - virtual ~SkMallocPixelRef(); - - //! Return the allocation size for the pixels - size_t getSize() const { return fSize; } - void* getAddr() const { return fStorage; } - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef) - -protected: - // overrides from SkPixelRef - virtual void* onLockPixels(SkColorTable**); - virtual void onUnlockPixels(); - - SkMallocPixelRef(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - -private: - void* fStorage; - size_t fSize; - SkColorTable* fCTable; - bool fOwnPixels; - - typedef SkPixelRef INHERITED; -}; - - -#endif diff --git a/gfx/skia/include/core/SkPostConfig.h b/gfx/skia/include/core/SkPostConfig.h deleted file mode 100644 index 23f1aff0203e..000000000000 --- a/gfx/skia/include/core/SkPostConfig.h +++ /dev/null @@ -1,363 +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 SkPostConfig_DEFINED -#define SkPostConfig_DEFINED - -#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE) - #define SK_BUILD_FOR_WIN -#endif - -#if defined(SK_DEBUG) && defined(SK_RELEASE) - #error "cannot define both SK_DEBUG and SK_RELEASE" -#elif !defined(SK_DEBUG) && !defined(SK_RELEASE) - #error "must define either SK_DEBUG or SK_RELEASE" -#endif - -#if defined SK_SUPPORT_UNITTEST && !defined(SK_DEBUG) - #error "can't have unittests without debug" -#endif - -#if defined(SK_SCALAR_IS_FIXED) && defined(SK_SCALAR_IS_FLOAT) - #error "cannot define both SK_SCALAR_IS_FIXED and SK_SCALAR_IS_FLOAT" -#elif !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT) - #define SK_SCALAR_IS_FLOAT -#endif - -#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT) - #error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT" -#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT) - // default is double, as that is faster given our impl uses doubles - // for intermediate calculations. - #define SK_MSCALAR_IS_DOUBLE -#endif - -#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) - #error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN" -#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) - #error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN" -#endif - -// ensure the port has defined all of these, or none of them -#ifdef SK_A32_SHIFT - #if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT) - #error "all or none of the 32bit SHIFT amounts must be defined" - #endif -#else - #if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT) - #error "all or none of the 32bit SHIFT amounts must be defined" - #endif -#endif - -#if !defined(SK_HAS_COMPILER_FEATURE) - #if defined(__has_feature) - #define SK_HAS_COMPILER_FEATURE(x) __has_feature(x) - #else - #define SK_HAS_COMPILER_FEATURE(x) 0 - #endif -#endif - -#if !defined(SK_SUPPORT_GPU) - #define SK_SUPPORT_GPU 1 -#endif - -/** - * The clang static analyzer likes to know that when the program is not - * expected to continue (crash, assertion failure, etc). It will notice that - * some combination of parameters lead to a function call that does not return. - * It can then make appropriate assumptions about the parameters in code - * executed only if the non-returning function was *not* called. - */ -#if !defined(SkNO_RETURN_HINT) - #if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn) - static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn)); - static inline void SkNO_RETURN_HINT() {} - #else - #define SkNO_RETURN_HINT() do {} while (false) - #endif -#endif - -#if defined(SK_ZLIB_INCLUDE) && defined(SK_SYSTEM_ZLIB) - #error "cannot define both SK_ZLIB_INCLUDE and SK_SYSTEM_ZLIB" -#elif defined(SK_ZLIB_INCLUDE) || defined(SK_SYSTEM_ZLIB) - #define SK_HAS_ZLIB -#endif - -/////////////////////////////////////////////////////////////////////////////// - -#ifndef SkNEW - #define SkNEW(type_name) (new type_name) - #define SkNEW_ARGS(type_name, args) (new type_name args) - #define SkNEW_ARRAY(type_name, count) (new type_name[(count)]) - #define SkNEW_PLACEMENT(buf, type_name) (new (buf) type_name) - #define SkNEW_PLACEMENT_ARGS(buf, type_name, args) \ - (new (buf) type_name args) - #define SkDELETE(obj) (delete (obj)) - #define SkDELETE_ARRAY(array) (delete[] (array)) -#endif - -#ifndef SK_CRASH -#if 1 // set to 0 for infinite loop, which can help connecting gdb - #define SK_CRASH() do { SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0; } while (false) -#else - #define SK_CRASH() do { SkNO_RETURN_HINT(); } while (true) -#endif -#endif - -/////////////////////////////////////////////////////////////////////////////// - -// SK_ENABLE_INST_COUNT defaults to 1 in DEBUG and 0 in RELEASE -#ifndef SK_ENABLE_INST_COUNT - #ifdef SK_DEBUG - #define SK_ENABLE_INST_COUNT 1 - #else - #define SK_ENABLE_INST_COUNT 0 - #endif -#endif - -/////////////////////////////////////////////////////////////////////////////// - -#if defined(SK_SOFTWARE_FLOAT) && defined(SK_SCALAR_IS_FLOAT) - // if this is defined, we convert floats to 2scompliment ints for compares - #ifndef SK_SCALAR_SLOW_COMPARES - #define SK_SCALAR_SLOW_COMPARES - #endif - #ifndef SK_USE_FLOATBITS - #define SK_USE_FLOATBITS - #endif -#endif - -#ifdef SK_BUILD_FOR_WIN - // we want lean_and_mean when we include windows.h - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED - #endif - - #include - - #ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED - #undef WIN32_LEAN_AND_MEAN - #endif - - #ifndef SK_DEBUGBREAK - #define SK_DEBUGBREAK(cond) do { if (!(cond)) { SkNO_RETURN_HINT(); __debugbreak(); }} while (false) - #endif - - #ifndef SK_A32_SHIFT - #define SK_A32_SHIFT 24 - #define SK_R32_SHIFT 16 - #define SK_G32_SHIFT 8 - #define SK_B32_SHIFT 0 - #endif - -#else - #ifdef SK_DEBUG - #include - #ifndef SK_DEBUGBREAK - #define SK_DEBUGBREAK(cond) do { if (cond) break; \ - SkDebugf("%s:%d: failed assertion \"%s\"\n", \ - __FILE__, __LINE__, #cond); SK_CRASH(); } while (false) - #endif - #endif -#endif - -/* - * We check to see if the SHIFT value has already been defined. - * if not, we define it ourself to some default values. We default to OpenGL - * order (in memory: r,g,b,a) - */ -#ifndef SK_A32_SHIFT - #ifdef SK_CPU_BENDIAN - #define SK_R32_SHIFT 24 - #define SK_G32_SHIFT 16 - #define SK_B32_SHIFT 8 - #define SK_A32_SHIFT 0 - #else - #define SK_R32_SHIFT 0 - #define SK_G32_SHIFT 8 - #define SK_B32_SHIFT 16 - #define SK_A32_SHIFT 24 - #endif -#endif - -/** - * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The - * relationship between the byte order and shift values depends on machine endianness. If the shift - * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little - * endian machine and the A channel on a big endian machine. Thus, given those shifts values, - * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and - * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine. - */ -#ifdef SK_CPU_BENDIAN - #define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \ - (SK_ ## C3 ## 32_SHIFT == 0 && \ - SK_ ## C2 ## 32_SHIFT == 8 && \ - SK_ ## C1 ## 32_SHIFT == 16 && \ - SK_ ## C0 ## 32_SHIFT == 24) -#else - #define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \ - (SK_ ## C0 ## 32_SHIFT == 0 && \ - SK_ ## C1 ## 32_SHIFT == 8 && \ - SK_ ## C2 ## 32_SHIFT == 16 && \ - SK_ ## C3 ## 32_SHIFT == 24) -#endif - -// stdlib macros - -#if 0 -#if !defined(strlen) && defined(SK_DEBUG) - extern size_t sk_strlen(const char*); - #define strlen(s) sk_strlen(s) -#endif -#ifndef sk_strcpy - #define sk_strcpy(dst, src) strcpy(dst, src) -#endif -#ifndef sk_strchr - #define sk_strchr(s, c) strchr(s, c) -#endif -#ifndef sk_strrchr - #define sk_strrchr(s, c) strrchr(s, c) -#endif -#ifndef sk_strcmp - #define sk_strcmp(s, t) strcmp(s, t) -#endif -#ifndef sk_strncmp - #define sk_strncmp(s, t, n) strncmp(s, t, n) -#endif -#ifndef sk_memcpy - #define sk_memcpy(dst, src, n) memcpy(dst, src, n) -#endif -#ifndef memmove - #define memmove(dst, src, n) memmove(dst, src, n) -#endif -#ifndef sk_memset - #define sk_memset(dst, val, n) memset(dst, val, n) -#endif -#ifndef sk_memcmp - #define sk_memcmp(s, t, n) memcmp(s, t, n) -#endif - -#define sk_strequal(s, t) (!sk_strcmp(s, t)) -#define sk_strnequal(s, t, n) (!sk_strncmp(s, t, n)) -#endif - -////////////////////////////////////////////////////////////////////// - -#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) - #ifndef SkLONGLONG - #ifdef SK_BUILD_FOR_WIN32 - #define SkLONGLONG __int64 - #else - #define SkLONGLONG long long - #endif - #endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////// -#ifndef SK_BUILD_FOR_WINCE -#include -#include -#else -#define _CMNINTRIN_DECLARE_ONLY -#include "cmnintrin.h" -#endif - -#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32 -//#define _CRTDBG_MAP_ALLOC -#ifdef free -#undef free -#endif -#include -#undef free - -#ifdef SK_DEBUGx -#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus) - void * operator new( - size_t cb, - int nBlockUse, - const char * szFileName, - int nLine, - int foo - ); - void * operator new[]( - size_t cb, - int nBlockUse, - const char * szFileName, - int nLine, - int foo - ); - void operator delete( - void *pUserData, - int, const char*, int, int - ); - void operator delete( - void *pUserData - ); - void operator delete[]( void * p ); - #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__, 0) -#else - #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) -#endif - #define new DEBUG_CLIENTBLOCK -#else -#define DEBUG_CLIENTBLOCK -#endif // _DEBUG - - -#endif - -#endif - -////////////////////////////////////////////////////////////////////// - -#ifndef SK_OVERRIDE - #if defined(_MSC_VER) - #define SK_OVERRIDE override - #elif defined(__clang__) && !defined(SK_BUILD_FOR_IOS) - #if __has_feature(cxx_override_control) - // Some documentation suggests we should be using __attribute__((override)), - // but it doesn't work. - #define SK_OVERRIDE override - #elif defined(__has_extension) - #if __has_extension(cxx_override_control) - #define SK_OVERRIDE override - #endif - #endif - #endif - #ifndef SK_OVERRIDE - #define SK_OVERRIDE - #endif -#endif - -////////////////////////////////////////////////////////////////////// - -#ifndef SK_PRINTF_LIKE -#if defined(__clang__) || defined(__GNUC__) -#define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B)))) -#else -#define SK_PRINTF_LIKE(A, B) -#endif -#endif - -////////////////////////////////////////////////////////////////////// - -#ifndef SK_SIZE_T_SPECIFIER -#if defined(_MSC_VER) -#define SK_SIZE_T_SPECIFIER "%Iu" -#else -#define SK_SIZE_T_SPECIFIER "%zu" -#endif -#endif - -////////////////////////////////////////////////////////////////////// - -#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS -#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1 -#endif diff --git a/gfx/skia/include/core/SkScalar.h b/gfx/skia/include/core/SkScalar.h deleted file mode 100644 index a699fe9a99ab..000000000000 --- a/gfx/skia/include/core/SkScalar.h +++ /dev/null @@ -1,379 +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 SkScalar_DEFINED -#define SkScalar_DEFINED - -#include "SkFixed.h" -#include "SkFloatingPoint.h" - -/** \file SkScalar.h - - Types and macros for the data type SkScalar. This is the fractional numeric type - that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented - either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written - to allow the calling code to manipulate SkScalar values without knowing which representation - is in effect. -*/ - -#ifdef SK_SCALAR_IS_FLOAT - - /** SkScalar is our type for fractional values and coordinates. Depending on - compile configurations, it is either represented as an IEEE float, or - as a 16.16 fixed point integer. - */ - typedef float SkScalar; - - /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar - */ - #define SK_Scalar1 (1.0f) - /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar - */ - #define SK_ScalarHalf (0.5f) - /** SK_ScalarInfinity is defined to be infinity as an SkScalar - */ - #define SK_ScalarInfinity SK_FloatInfinity - /** SK_ScalarNegativeInfinity is defined to be negative infinity as an SkScalar - */ - #define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity - /** SK_ScalarMax is defined to be the largest value representable as an SkScalar - */ - #define SK_ScalarMax (3.402823466e+38f) - /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar - */ - #define SK_ScalarMin (-SK_ScalarMax) - /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar - */ - #define SK_ScalarNaN SK_FloatNaN - /** SkScalarIsNaN(n) returns true if argument is not a number - */ - static inline bool SkScalarIsNaN(float x) { return x != x; } - - /** Returns true if x is not NaN and not infinite */ - static inline bool SkScalarIsFinite(float x) { - // We rely on the following behavior of infinities and nans - // 0 * finite --> 0 - // 0 * infinity --> NaN - // 0 * NaN --> NaN - float prod = x * 0; - // At this point, prod will either be NaN or 0 - // Therefore we can return (prod == prod) or (0 == prod). - return prod == prod; - } - -#ifdef SK_DEBUG - /** SkIntToScalar(n) returns its integer argument as an SkScalar - * - * If we're compiling in DEBUG mode, and can thus afford some extra runtime - * cycles, check to make sure that the parameter passed in has not already - * been converted to SkScalar. (A double conversion like this is harmless - * for SK_SCALAR_IS_FLOAT, but for SK_SCALAR_IS_FIXED this causes trouble.) - * - * Note that we need all of these method signatures to properly handle the - * various types that we pass into SkIntToScalar() to date: - * int, size_t, U8CPU, etc., even though what we really mean is "anything - * but a float". - */ - static inline float SkIntToScalar(signed int param) { - return (float)param; - } - static inline float SkIntToScalar(unsigned int param) { - return (float)param; - } - static inline float SkIntToScalar(signed long param) { - return (float)param; - } - static inline float SkIntToScalar(unsigned long param) { - return (float)param; - } - static inline float SkIntToScalar(float /* param */) { - /* If the parameter passed into SkIntToScalar is a float, - * one of two things has happened: - * 1. the parameter was an SkScalar (which is typedef'd to float) - * 2. the parameter was a float instead of an int - * - * Either way, it's not good. - */ - SkDEBUGFAIL("looks like you passed an SkScalar into SkIntToScalar"); - return (float)0; - } -#else // not SK_DEBUG - /** SkIntToScalar(n) returns its integer argument as an SkScalar - */ - #define SkIntToScalar(n) ((float)(n)) -#endif // not SK_DEBUG - /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar - */ - #define SkFixedToScalar(x) SkFixedToFloat(x) - /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed - */ - #define SkScalarToFixed(x) SkFloatToFixed(x) - - #define SkScalarToFloat(n) (n) - #define SkFloatToScalar(n) (n) - - #define SkScalarToDouble(n) (double)(n) - #define SkDoubleToScalar(n) (float)(n) - - /** SkScalarFraction(x) returns the signed fractional part of the argument - */ - #define SkScalarFraction(x) sk_float_mod(x, 1.0f) - - #define SkScalarFloorToScalar(x) sk_float_floor(x) - #define SkScalarCeilToScalar(x) sk_float_ceil(x) - #define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f) - - #define SkScalarFloorToInt(x) sk_float_floor2int(x) - #define SkScalarCeilToInt(x) sk_float_ceil2int(x) - #define SkScalarRoundToInt(x) sk_float_round2int(x) - #define SkScalarTruncToInt(x) static_cast(x) - - /** Returns the absolute value of the specified SkScalar - */ - #define SkScalarAbs(x) sk_float_abs(x) - /** Return x with the sign of y - */ - #define SkScalarCopySign(x, y) sk_float_copysign(x, y) - /** Returns the value pinned between 0 and max inclusive - */ - inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) { - return x < 0 ? 0 : x > max ? max : x; - } - /** Returns the value pinned between min and max inclusive - */ - inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) { - return x < min ? min : x > max ? max : x; - } - /** Returns the specified SkScalar squared (x*x) - */ - inline SkScalar SkScalarSquare(SkScalar x) { return x * x; } - /** Returns the product of two SkScalars - */ - #define SkScalarMul(a, b) ((float)(a) * (b)) - /** Returns the product of two SkScalars plus a third SkScalar - */ - #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c)) - /** Returns the product of a SkScalar and an int rounded to the nearest integer value - */ - #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b)) - /** Returns the product of a SkScalar and an int promoted to the next larger int - */ - #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b)) - /** Returns the product of a SkScalar and an int truncated to the next smaller int - */ - #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b)) - /** Returns the quotient of two SkScalars (a/b) - */ - #define SkScalarDiv(a, b) ((float)(a) / (b)) - /** Returns the mod of two SkScalars (a mod b) - */ - #define SkScalarMod(x,y) sk_float_mod(x,y) - /** Returns the product of the first two arguments, divided by the third argument - */ - #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c)) - /** Returns the multiplicative inverse of the SkScalar (1/x) - */ - #define SkScalarInvert(x) (SK_Scalar1 / (x)) - #define SkScalarFastInvert(x) (SK_Scalar1 / (x)) - /** Returns the square root of the SkScalar - */ - #define SkScalarSqrt(x) sk_float_sqrt(x) - /** Returns b to the e - */ - #define SkScalarPow(b, e) sk_float_pow(b, e) - /** Returns the average of two SkScalars (a+b)/2 - */ - #define SkScalarAve(a, b) (((a) + (b)) * 0.5f) - /** Returns the geometric mean of two SkScalars - */ - #define SkScalarMean(a, b) sk_float_sqrt((float)(a) * (b)) - /** Returns one half of the specified SkScalar - */ - #define SkScalarHalf(a) ((a) * 0.5f) - - #define SK_ScalarSqrt2 1.41421356f - #define SK_ScalarPI 3.14159265f - #define SK_ScalarTanPIOver8 0.414213562f - #define SK_ScalarRoot2Over2 0.707106781f - - #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180)) - float SkScalarSinCos(SkScalar radians, SkScalar* cosValue); - #define SkScalarSin(radians) (float)sk_float_sin(radians) - #define SkScalarCos(radians) (float)sk_float_cos(radians) - #define SkScalarTan(radians) (float)sk_float_tan(radians) - #define SkScalarASin(val) (float)sk_float_asin(val) - #define SkScalarACos(val) (float)sk_float_acos(val) - #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x) - #define SkScalarExp(x) (float)sk_float_exp(x) - #define SkScalarLog(x) (float)sk_float_log(x) - - inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; } - inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; } - - static inline bool SkScalarIsInt(SkScalar x) { - return x == (float)(int)x; - } -#else - typedef SkFixed SkScalar; - - #define SK_Scalar1 SK_Fixed1 - #define SK_ScalarHalf SK_FixedHalf - #define SK_ScalarInfinity SK_FixedMax - #define SK_ScalarNegativeInfinity SK_FixedMin - #define SK_ScalarMax SK_FixedMax - #define SK_ScalarMin SK_FixedMin - #define SK_ScalarNaN SK_FixedNaN - #define SkScalarIsNaN(x) ((x) == SK_FixedNaN) - #define SkScalarIsFinite(x) ((x) != SK_FixedNaN) - - #define SkIntToScalar(n) SkIntToFixed(n) - #define SkFixedToScalar(x) (x) - #define SkScalarToFixed(x) (x) - #define SkScalarToFloat(n) SkFixedToFloat(n) - #define SkFloatToScalar(n) SkFloatToFixed(n) - - #define SkScalarToDouble(n) SkFixedToDouble(n) - #define SkDoubleToScalar(n) SkDoubleToFixed(n) - #define SkScalarFraction(x) SkFixedFraction(x) - - #define SkScalarFloorToScalar(x) SkFixedFloorToFixed(x) - #define SkScalarCeilToScalar(x) SkFixedCeilToFixed(x) - #define SkScalarRoundToScalar(x) SkFixedRoundToFixed(x) - - #define SkScalarFloorToInt(x) SkFixedFloorToInt(x) - #define SkScalarCeilToInt(x) SkFixedCeilToInt(x) - #define SkScalarRoundToInt(x) SkFixedRoundToInt(x) - #define SkScalarTruncToInt(x) (((x) < 0) ? SkScalarCeilToInt(x) : SkScalarFloorToInt(x)) - - #define SkScalarAbs(x) SkFixedAbs(x) - #define SkScalarCopySign(x, y) SkCopySign32(x, y) - #define SkScalarClampMax(x, max) SkClampMax(x, max) - #define SkScalarPin(x, min, max) SkPin32(x, min, max) - #define SkScalarSquare(x) SkFixedSquare(x) - #define SkScalarMul(a, b) SkFixedMul(a, b) - #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c) - #define SkScalarMulRound(a, b) SkFixedMulCommon(a, b, SK_FixedHalf) - #define SkScalarMulCeil(a, b) SkFixedMulCommon(a, b, SK_Fixed1 - 1) - #define SkScalarMulFloor(a, b) SkFixedMulCommon(a, b, 0) - #define SkScalarDiv(a, b) SkFixedDiv(a, b) - #define SkScalarMod(a, b) SkFixedMod(a, b) - #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c) - #define SkScalarInvert(x) SkFixedInvert(x) - #define SkScalarFastInvert(x) SkFixedFastInvert(x) - #define SkScalarSqrt(x) SkFixedSqrt(x) - #define SkScalarAve(a, b) SkFixedAve(a, b) - #define SkScalarMean(a, b) SkFixedMean(a, b) - #define SkScalarHalf(a) ((a) >> 1) - - #define SK_ScalarSqrt2 SK_FixedSqrt2 - #define SK_ScalarPI SK_FixedPI - #define SK_ScalarTanPIOver8 SK_FixedTanPIOver8 - #define SK_ScalarRoot2Over2 SK_FixedRoot2Over2 - - #define SkDegreesToRadians(degrees) SkFractMul(degrees, SK_FractPIOver180) - #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr) - #define SkScalarSin(radians) SkFixedSin(radians) - #define SkScalarCos(radians) SkFixedCos(radians) - #define SkScalarTan(val) SkFixedTan(val) - #define SkScalarASin(val) SkFixedASin(val) - #define SkScalarACos(val) SkFixedACos(val) - #define SkScalarATan2(y, x) SkFixedATan2(y,x) - #define SkScalarExp(x) SkFixedExp(x) - #define SkScalarLog(x) SkFixedLog(x) - - #define SkMaxScalar(a, b) SkMax32(a, b) - #define SkMinScalar(a, b) SkMin32(a, b) - - static inline bool SkScalarIsInt(SkFixed x) { - return 0 == (x & 0xffff); - } -#endif - -// DEPRECATED : use ToInt or ToScalar variant -#define SkScalarFloor(x) SkScalarFloorToInt(x) -#define SkScalarCeil(x) SkScalarCeilToInt(x) -#define SkScalarRound(x) SkScalarRoundToInt(x) - -/** - * Returns -1 || 0 || 1 depending on the sign of value: - * -1 if x < 0 - * 0 if x == 0 - * 1 if x > 0 - */ -static inline int SkScalarSignAsInt(SkScalar x) { - return x < 0 ? -1 : (x > 0); -} - -// Scalar result version of above -static inline SkScalar SkScalarSignAsScalar(SkScalar x) { - return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0); -} - -#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12)) - -static inline bool SkScalarNearlyZero(SkScalar x, - SkScalar tolerance = SK_ScalarNearlyZero) { - SkASSERT(tolerance >= 0); - return SkScalarAbs(x) <= tolerance; -} - -static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y, - SkScalar tolerance = SK_ScalarNearlyZero) { - SkASSERT(tolerance >= 0); - return SkScalarAbs(x-y) <= tolerance; -} - -/** Linearly interpolate between A and B, based on t. - If t is 0, return A - If t is 1, return B - else interpolate. - t must be [0..SK_Scalar1] -*/ -static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) { - SkASSERT(t >= 0 && t <= SK_Scalar1); - return A + SkScalarMul(B - A, t); -} - -static inline SkScalar SkScalarLog2(SkScalar x) { - static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2)); - - return SkScalarMul(SkScalarLog(x), log2_conversion_factor); -} - -/** Interpolate along the function described by (keys[length], values[length]) - for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length] - clamp to the min or max value. This function was inspired by a desire - to change the multiplier for thickness in fakeBold; therefore it assumes - the number of pairs (length) will be small, and a linear search is used. - Repeated keys are allowed for discontinuous functions (so long as keys is - monotonically increasing), and if key is the value of a repeated scalar in - keys, the first one will be used. However, that may change if a binary - search is used. -*/ -SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[], - const SkScalar values[], int length); - -/* - * Helper to compare an array of scalars. - */ -static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) { -#ifdef SK_SCALAR_IS_FLOAT - SkASSERT(n >= 0); - for (int i = 0; i < n; ++i) { - if (a[i] != b[i]) { - return false; - } - } - return true; -#else - return 0 == memcmp(a, b, n * sizeof(SkScalar)); -#endif -} - -#endif diff --git a/gfx/skia/include/core/SkStream.h b/gfx/skia/include/core/SkStream.h deleted file mode 100644 index 30855b35f4e2..000000000000 --- a/gfx/skia/include/core/SkStream.h +++ /dev/null @@ -1,397 +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 SkStream_DEFINED -#define SkStream_DEFINED - -#include "SkRefCnt.h" -#include "SkScalar.h" - -class SkData; - -class SK_API SkStream : public SkRefCnt { -public: - /** - * Attempts to open the specified file, and return a stream to it (using - * mmap if available). On success, the caller must call unref() on the - * returned object. On failure, returns NULL. - */ - static SkStream* NewFromFile(const char path[]); - - SK_DECLARE_INST_COUNT(SkStream) - - /** Called to rewind to the beginning of the stream. If this cannot be - done, return false. - */ - virtual bool rewind() = 0; - /** If this stream represents a file, this method returns the file's name. - If it does not, it returns NULL (the default behavior). - */ - virtual const char* getFileName(); - /** Called to read or skip size number of bytes. - If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped. - If buffer is NULL and size == 0, return the total length of the stream. - If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied. - @param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer - @param size The number of bytes to skip or copy - @return bytes read on success - */ - virtual size_t read(void* buffer, size_t size) = 0; - - /** Return the total length of the stream. - */ - size_t getLength() { return this->read(NULL, 0); } - - /** Skip the specified number of bytes, returning the actual number - of bytes that could be skipped. - */ - size_t skip(size_t bytes); - - /** If the stream is backed by RAM, this method returns the starting - address for the data. If not (i.e. it is backed by a file or other - structure), this method returns NULL. - The default implementation returns NULL. - */ - virtual const void* getMemoryBase(); - - int8_t readS8(); - int16_t readS16(); - int32_t readS32(); - - uint8_t readU8() { return (uint8_t)this->readS8(); } - uint16_t readU16() { return (uint16_t)this->readS16(); } - uint32_t readU32() { return (uint32_t)this->readS32(); } - - bool readBool() { return this->readU8() != 0; } - SkScalar readScalar(); - size_t readPackedUInt(); - - /** - * Reconstitute an SkData object that was written to the stream - * using SkWStream::writeData(). - */ - SkData* readData(); - -private: - typedef SkRefCnt INHERITED; -}; - -class SK_API SkWStream : SkNoncopyable { -public: - SK_DECLARE_INST_COUNT_ROOT(SkWStream) - - virtual ~SkWStream(); - - /** Called to write bytes to a SkWStream. Returns true on success - @param buffer the address of at least size bytes to be written to the stream - @param size The number of bytes in buffer to write to the stream - @return true on success - */ - virtual bool write(const void* buffer, size_t size) = 0; - virtual void newline(); - virtual void flush(); - - // helpers - - bool write8(U8CPU); - bool write16(U16CPU); - bool write32(uint32_t); - - bool writeText(const char text[]); - bool writeDecAsText(int32_t); - bool writeBigDecAsText(int64_t, int minDigits = 0); - bool writeHexAsText(uint32_t, int minDigits = 0); - bool writeScalarAsText(SkScalar); - - bool writeBool(bool v) { return this->write8(v); } - bool writeScalar(SkScalar); - bool writePackedUInt(size_t); - - bool writeStream(SkStream* input, size_t length); - - /** - * Append an SkData object to the stream, such that it can be read - * out of the stream using SkStream::readData(). - * - * Note that the encoding method used to write the SkData object - * to the stream may change over time. This method DOES NOT - * just write the raw content of the SkData object to the stream. - */ - bool writeData(const SkData*); -}; - -//////////////////////////////////////////////////////////////////////////////////////// - -#include "SkString.h" - -struct SkFILE; - -/** A stream that reads from a FILE*, which is opened in the constructor and - closed in the destructor - */ -class SK_API SkFILEStream : public SkStream { -public: - SK_DECLARE_INST_COUNT(SkFILEStream) - - /** Initialize the stream by calling fopen on the specified path. Will be - closed in the destructor. - */ - explicit SkFILEStream(const char path[] = NULL); - virtual ~SkFILEStream(); - - /** Returns true if the current path could be opened. - */ - bool isValid() const { return fFILE != NULL; } - /** Close the current file, and open a new file with the specified - path. If path is NULL, just close the current file. - */ - void setPath(const char path[]); - - virtual bool rewind() SK_OVERRIDE; - virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; - virtual const char* getFileName() SK_OVERRIDE; - -private: - SkFILE* fFILE; - SkString fName; - - typedef SkStream INHERITED; -}; - -/** A stream that reads from a file descriptor - */ -class SK_API SkFDStream : public SkStream { -public: - SK_DECLARE_INST_COUNT(SkFDStream) - - /** Initialize the stream with a dup() of the specified file descriptor. - If closeWhenDone is true, then the descriptor will be closed in the - destructor. - */ - SkFDStream(int fileDesc, bool closeWhenDone); - virtual ~SkFDStream(); - - /** Returns true if the current path could be opened. - */ - bool isValid() const { return fFD >= 0; } - - virtual bool rewind() SK_OVERRIDE; - virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; - virtual const char* getFileName() SK_OVERRIDE { return NULL; } - -private: - int fFD; - bool fCloseWhenDone; - - typedef SkStream INHERITED; -}; - -class SK_API SkMemoryStream : public SkStream { -public: - SK_DECLARE_INST_COUNT(SkMemoryStream) - - SkMemoryStream(); - /** We allocate (and free) the memory. Write to it via getMemoryBase() - */ - SkMemoryStream(size_t length); - /** if copyData is true, the stream makes a private copy of the data - */ - SkMemoryStream(const void* data, size_t length, bool copyData = false); - - /** - * Use the specified data as the memory for this stream. The stream will - * call ref() on the data (assuming it is not null). - */ - SkMemoryStream(SkData*); - - virtual ~SkMemoryStream(); - - /** Resets the stream to the specified data and length, - just like the constructor. - if copyData is true, the stream makes a private copy of the data - */ - virtual void setMemory(const void* data, size_t length, - bool copyData = false); - /** Replace any memory buffer with the specified buffer. The caller - must have allocated data with sk_malloc or sk_realloc, since it - will be freed with sk_free. - */ - void setMemoryOwned(const void* data, size_t length); - - /** - * Return the stream's data in a SkData. The caller must call unref() when - * it is finished using the data. - */ - SkData* copyToData() const; - - /** - * Use the specified data as the memory for this stream. The stream will - * call ref() on the data (assuming it is not null). The function returns - * the data parameter as a convenience. - */ - SkData* setData(SkData*); - - void skipToAlign4(); - virtual bool rewind() SK_OVERRIDE; - virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; - virtual const void* getMemoryBase() SK_OVERRIDE; - const void* getAtPos(); - size_t seek(size_t offset); - size_t peek() const { return fOffset; } - -private: - SkData* fData; - size_t fOffset; - - typedef SkStream INHERITED; -}; - -/** \class SkBufferStream - This is a wrapper class that adds buffering to another stream. - The caller can provide the buffer, or ask SkBufferStream to allocated/free - it automatically. -*/ -class SK_API SkBufferStream : public SkStream { -public: - SK_DECLARE_INST_COUNT(SkBufferStream) - - /** Provide the stream to be buffered (proxy), and the size of the buffer that - should be used. This will be allocated and freed automatically. If bufferSize is 0, - a default buffer size will be used. - The proxy stream is referenced, and will be unreferenced in when the - bufferstream is destroyed. - */ - SkBufferStream(SkStream* proxy, size_t bufferSize = 0); - /** Provide the stream to be buffered (proxy), and a buffer and size to be used. - This buffer is owned by the caller, and must be at least bufferSize bytes big. - Passing NULL for buffer will cause the buffer to be allocated/freed automatically. - If buffer is not NULL, it is an error for bufferSize to be 0. - The proxy stream is referenced, and will be unreferenced in when the - bufferstream is destroyed. - */ - SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize); - virtual ~SkBufferStream(); - - virtual bool rewind() SK_OVERRIDE; - virtual const char* getFileName() SK_OVERRIDE; - virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; - virtual const void* getMemoryBase() SK_OVERRIDE; - -private: - enum { - kDefaultBufferSize = 128 - }; - // illegal - SkBufferStream(const SkBufferStream&); - SkBufferStream& operator=(const SkBufferStream&); - - SkStream* fProxy; - char* fBuffer; - size_t fOrigBufferSize, fBufferSize, fBufferOffset; - bool fWeOwnTheBuffer; - - void init(void*, size_t); - - typedef SkStream INHERITED; -}; - -///////////////////////////////////////////////////////////////////////////////////////////// - -class SK_API SkFILEWStream : public SkWStream { -public: - SK_DECLARE_INST_COUNT(SkFILEWStream) - - SkFILEWStream(const char path[]); - virtual ~SkFILEWStream(); - - /** Returns true if the current path could be opened. - */ - bool isValid() const { return fFILE != NULL; } - - virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; - virtual void flush() SK_OVERRIDE; - -private: - SkFILE* fFILE; - - typedef SkWStream INHERITED; -}; - -class SkMemoryWStream : public SkWStream { -public: - SK_DECLARE_INST_COUNT(SkMemoryWStream) - - SkMemoryWStream(void* buffer, size_t size); - virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; - size_t bytesWritten() const { return fBytesWritten; } - -private: - char* fBuffer; - size_t fMaxLength; - size_t fBytesWritten; - - typedef SkWStream INHERITED; -}; - -class SK_API SkDynamicMemoryWStream : public SkWStream { -public: - SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream) - - SkDynamicMemoryWStream(); - virtual ~SkDynamicMemoryWStream(); - - virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; - // random access write - // modifies stream and returns true if offset + size is less than or equal to getOffset() - bool write(const void* buffer, size_t offset, size_t size); - bool read(void* buffer, size_t offset, size_t size); - size_t getOffset() const { return fBytesWritten; } - size_t bytesWritten() const { return fBytesWritten; } - - // copy what has been written to the stream into dst - void copyTo(void* dst) const; - - /** - * Return a copy of the data written so far. This call is responsible for - * calling unref() when they are finished with the data. - */ - SkData* copyToData() const; - - // reset the stream to its original state - void reset(); - void padToAlign4(); -private: - struct Block; - Block* fHead; - Block* fTail; - size_t fBytesWritten; - mutable SkData* fCopy; // is invalidated if we write after it is created - - void invalidateCopy(); - - typedef SkWStream INHERITED; -}; - - -class SK_API SkDebugWStream : public SkWStream { -public: - SK_DECLARE_INST_COUNT(SkDebugWStream) - - // overrides - virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; - virtual void newline() SK_OVERRIDE; - -private: - typedef SkWStream INHERITED; -}; - -// for now -typedef SkFILEStream SkURLStream; - -#endif diff --git a/gfx/skia/include/core/SkTScopedPtr.h b/gfx/skia/include/core/SkTScopedPtr.h deleted file mode 100644 index 580d72f1f80b..000000000000 --- a/gfx/skia/include/core/SkTScopedPtr.h +++ /dev/null @@ -1,76 +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 SkTScopedPtr_DEFINED -#define SkTScopedPtr_DEFINED - -#include "SkTypes.h" - -/** \class SkTScopedPtr - A SkTScopedPtr is like a T*, except that the destructor of SkTScopedPtr - automatically deletes the pointer it holds (if any). That is, SkTScopedPtr - owns the T object that it points to. Like a T*, a SkTScopedPtr may hold - either NULL or a pointer to a T object. Also like T*, SkTScopedPtr is - thread-compatible, and once you dereference it, you get the threadsafety - guarantees of T. - - The size of a SkTScopedPtr is small: sizeof(SkTScopedPtr) == sizeof(T*) -*/ -template class SkTScopedPtr : SkNoncopyable { -public: - explicit SkTScopedPtr(T* o = NULL) : fObj(o) {} - ~SkTScopedPtr() { - enum { kTypeMustBeComplete = sizeof(T) }; - delete fObj; - } - - /** Delete the current object, if any. Then take ownership of the - passed object. - */ - void reset(T* o = NULL) { - if (o != fObj) { - enum { kTypeMustBeComplete = sizeof(T) }; - delete fObj; - fObj = o; - } - } - - /** Without deleting the current object, return it and forget about it. - Similar to calling get() and reset(), but the object is not deleted. - */ - T* release() { - T* retVal = fObj; - fObj = NULL; - return retVal; - } - - T& operator*() const { - SkASSERT(fObj != NULL); - return *fObj; - } - T* operator->() const { - SkASSERT(fObj != NULL); - return fObj; - } - T* get() const { return fObj; } - - bool operator==(T* o) const { return fObj == o; } - bool operator!=(T* o) const { return fObj != o; } - -private: - T* fObj; - - // Forbid comparison of SkTScopedPtr types. If T2 != T, it doesn't make - // sense, and if T2 == T, it still doesn't make sense because the same - // object can't be owned by two different scoped_ptrs. - template bool operator==(SkTScopedPtr const& o2) const; - template bool operator!=(SkTScopedPtr const& o2) const; -}; - -#endif diff --git a/gfx/skia/include/core/SkTSearch.h b/gfx/skia/include/core/SkTSearch.h deleted file mode 100644 index eaf5ee593494..000000000000 --- a/gfx/skia/include/core/SkTSearch.h +++ /dev/null @@ -1,239 +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 SkTSearch_DEFINED -#define SkTSearch_DEFINED - -#include "SkTypes.h" - -/** - * All of the SkTSearch variants want to return the index (0...N-1) of the - * found element, or the bit-not of where to insert the element. - * - * At a simple level, if the return value is negative, it was not found. - * - * For clients that want to insert the new element if it was not found, use - * the following logic: - * - * int index = SkTSearch(...); - * if (index >= 0) { - * // found at index - * } else { - * index = ~index; // now we are positive - * // insert at index - * } - */ - -template -int SkTSearch(const T* base, int count, const T& target, size_t elemSize) -{ - SkASSERT(count >= 0); - if (count <= 0) - return ~0; - - SkASSERT(base != NULL); // base may be NULL if count is zero - - int lo = 0; - int hi = count - 1; - - while (lo < hi) - { - int mid = (hi + lo) >> 1; - const T* elem = (const T*)((const char*)base + mid * elemSize); - - if (*elem < target) - lo = mid + 1; - else - hi = mid; - } - - const T* elem = (const T*)((const char*)base + hi * elemSize); - if (*elem != target) - { - if (*elem < target) - hi += 1; - hi = ~hi; - } - return hi; -} - -template -int SkTSearch(const T* base, int count, const T& target, size_t elemSize) -{ - SkASSERT(count >= 0); - if (count <= 0) { - return ~0; - } - - SkASSERT(base != NULL); // base may be NULL if count is zero - - int lo = 0; - int hi = count - 1; - - while (lo < hi) { - int mid = (hi + lo) >> 1; - const T* elem = (const T*)((const char*)base + mid * elemSize); - - if (COMPARE(elem, &target) < 0) - lo = mid + 1; - else - hi = mid; - } - - const T* elem = (const T*)((const char*)base + hi * elemSize); - int pred = COMPARE(elem, &target); - if (pred != 0) { - if (pred < 0) - hi += 1; - hi = ~hi; - } - return hi; -} - -template -int SkTSearch(const T* base, int count, const T& target, size_t elemSize, - int (*compare)(const T*, const T*)) -{ - SkASSERT(count >= 0); - if (count <= 0) { - return ~0; - } - - SkASSERT(base != NULL); // base may be NULL if count is zero - - int lo = 0; - int hi = count - 1; - - while (lo < hi) { - int mid = (hi + lo) >> 1; - const T* elem = (const T*)((const char*)base + mid * elemSize); - - if ((*compare)(elem, &target) < 0) - lo = mid + 1; - else - hi = mid; - } - - const T* elem = (const T*)((const char*)base + hi * elemSize); - int pred = (*compare)(elem, &target); - if (pred != 0) { - if (pred < 0) - hi += 1; - hi = ~hi; - } - return hi; -} - -template -int SkTSearch(const T** base, int count, const T* target, size_t elemSize, - int (*compare)(const T*, const T*)) -{ - SkASSERT(count >= 0); - if (count <= 0) - return ~0; - - SkASSERT(base != NULL); // base may be NULL if count is zero - - int lo = 0; - int hi = count - 1; - - while (lo < hi) - { - int mid = (hi + lo) >> 1; - const T* elem = *(const T**)((const char*)base + mid * elemSize); - - if ((*compare)(elem, target) < 0) - lo = mid + 1; - else - hi = mid; - } - - const T* elem = *(const T**)((const char*)base + hi * elemSize); - int pred = (*compare)(elem, target); - if (pred != 0) - { - if (pred < 0) - hi += 1; - hi = ~hi; - } - return hi; -} - -template -int SkTSearch(const T** base, int count, const T* target, size_t elemSize) -{ - SkASSERT(count >= 0); - if (count <= 0) - return ~0; - - SkASSERT(base != NULL); // base may be NULL if count is zero - - int lo = 0; - int hi = count - 1; - - while (lo < hi) - { - int mid = (hi + lo) >> 1; - const T* elem = *(const T**)((const char*)base + mid * elemSize); - - if (COMPARE(elem, target) < 0) - lo = mid + 1; - else - hi = mid; - } - - const T* elem = *(const T**)((const char*)base + hi * elemSize); - int pred = COMPARE(elem, target); - if (pred != 0) - { - if (pred < 0) - hi += 1; - hi = ~hi; - } - return hi; -} -int SkStrSearch(const char*const* base, int count, const char target[], - size_t target_len, size_t elemSize); -int SkStrSearch(const char*const* base, int count, const char target[], - size_t elemSize); - -/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that - base points to a table of lower-case strings. -*/ -int SkStrLCSearch(const char*const* base, int count, const char target[], - size_t target_len, size_t elemSize); -int SkStrLCSearch(const char*const* base, int count, const char target[], - size_t elemSize); - -/** Helper class to convert a string to lower-case, but only modifying the ascii - characters. This makes the routine very fast and never changes the string - length, but it is not suitable for linguistic purposes. Normally this is - used for buiding and searching string tables. -*/ -class SkAutoAsciiToLC { -public: - SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1); - ~SkAutoAsciiToLC(); - - const char* lc() const { return fLC; } - size_t length() const { return fLength; } - -private: - char* fLC; // points to either the heap or fStorage - size_t fLength; - enum { - STORAGE = 64 - }; - char fStorage[STORAGE+1]; -}; - -// Helper when calling qsort with a compare proc that has typed its arguments -#define SkCastForQSort(compare) reinterpret_cast(compare) - -#endif diff --git a/gfx/skia/include/core/SkThread.h b/gfx/skia/include/core/SkThread.h deleted file mode 100644 index 4a2499a203db..000000000000 --- a/gfx/skia/include/core/SkThread.h +++ /dev/null @@ -1,68 +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 SkThread_DEFINED -#define SkThread_DEFINED - -#include "SkTypes.h" -#include "SkThread_platform.h" - -/****** SkThread_platform needs to define the following... - -int32_t sk_atomic_inc(int32_t*); -int32_t sk_atomic_add(int32_t*, int32_t); -int32_t sk_atomic_dec(int32_t*); -int32_t sk_atomic_conditional_inc(int32_t*); - -class SkMutex { -public: - SkMutex(); - ~SkMutex(); - - void acquire(); - void release(); -}; - -****************/ - -class SkAutoMutexAcquire : SkNoncopyable { -public: - explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) { - SkASSERT(fMutex != NULL); - mutex.acquire(); - } - - SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) { - if (mutex) { - mutex->acquire(); - } - } - - /** If the mutex has not been release, release it now. - */ - ~SkAutoMutexAcquire() { - if (fMutex) { - fMutex->release(); - } - } - - /** If the mutex has not been release, release it now. - */ - void release() { - if (fMutex) { - fMutex->release(); - fMutex = NULL; - } - } - -private: - SkBaseMutex* fMutex; -}; - -#endif diff --git a/gfx/skia/include/core/SkWriter32.h b/gfx/skia/include/core/SkWriter32.h deleted file mode 100644 index 51044ab00ea0..000000000000 --- a/gfx/skia/include/core/SkWriter32.h +++ /dev/null @@ -1,294 +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 SkWriter32_DEFINED -#define SkWriter32_DEFINED - -#include "SkTypes.h" - -#include "SkScalar.h" -#include "SkPath.h" -#include "SkPoint.h" -#include "SkRect.h" -#include "SkRRect.h" -#include "SkMatrix.h" -#include "SkRegion.h" - -class SkStream; -class SkWStream; - -class SkWriter32 : SkNoncopyable { - struct BlockHeader; -public: - /** - * The caller can specify an initial block of storage, which the caller manages. - * SkWriter32 will not attempt to free this in its destructor. It is up to the - * implementation to decide if, and how much, of the storage to utilize, and it - * is possible that it may be ignored entirely. - */ - SkWriter32(size_t minSize, void* initialStorage, size_t storageSize); - - SkWriter32(size_t minSize) - : fHead(NULL) - , fTail(NULL) - , fMinSize(minSize) - , fSize(0) - , fWrittenBeforeLastBlock(0) - {} - - ~SkWriter32(); - - // return the current offset (will always be a multiple of 4) - uint32_t bytesWritten() const { return fSize; } - // DEPRECATED: use byetsWritten instead - uint32_t size() const { return this->bytesWritten(); } - - void reset(); - - // size MUST be multiple of 4 - uint32_t* reserve(size_t size) { - SkASSERT(SkAlign4(size) == size); - - Block* block = fTail; - if (NULL == block || block->available() < size) { - block = this->doReserve(size); - } - fSize += size; - return block->alloc(size); - } - - void reset(void* storage, size_t size); - - bool writeBool(bool value) { - this->writeInt(value); - return value; - } - - void writeInt(int32_t value) { - *(int32_t*)this->reserve(sizeof(value)) = value; - } - - void write8(int32_t value) { - *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; - } - - void write16(int32_t value) { - *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; - } - - void write32(int32_t value) { - *(int32_t*)this->reserve(sizeof(value)) = value; - } - - void writePtr(void* ptr) { - // Since we "know" that we're always 4-byte aligned, we can tell the - // compiler that here, by assigning to an int32 ptr. - int32_t* addr = (int32_t*)this->reserve(sizeof(void*)); - if (4 == sizeof(void*)) { - *(void**)addr = ptr; - } else { - memcpy(addr, &ptr, sizeof(void*)); - } - } - - void writeScalar(SkScalar value) { - *(SkScalar*)this->reserve(sizeof(value)) = value; - } - - void writePoint(const SkPoint& pt) { - *(SkPoint*)this->reserve(sizeof(pt)) = pt; - } - - void writeRect(const SkRect& rect) { - *(SkRect*)this->reserve(sizeof(rect)) = rect; - } - - void writeRRect(const SkRRect& rrect) { - rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); - } - - void writePath(const SkPath& path) { - size_t size = path.writeToMemory(NULL); - SkASSERT(SkAlign4(size) == size); - path.writeToMemory(this->reserve(size)); - } - - void writeMatrix(const SkMatrix& matrix) { - size_t size = matrix.writeToMemory(NULL); - SkASSERT(SkAlign4(size) == size); - matrix.writeToMemory(this->reserve(size)); - } - - void writeRegion(const SkRegion& rgn) { - size_t size = rgn.writeToMemory(NULL); - SkASSERT(SkAlign4(size) == size); - rgn.writeToMemory(this->reserve(size)); - } - - // write count bytes (must be a multiple of 4) - void writeMul4(const void* values, size_t size) { - this->write(values, size); - } - - /** - * Write size bytes from values. size must be a multiple of 4, though - * values need not be 4-byte aligned. - */ - void write(const void* values, size_t size) { - SkASSERT(SkAlign4(size) == size); - // if we could query how much is avail in the current block, we might - // copy that much, and then alloc the rest. That would reduce the waste - // in the current block - memcpy(this->reserve(size), values, size); - } - - /** - * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be - * filled in with zeroes. - */ - uint32_t* reservePad(size_t size); - - /** - * Write size bytes from src, and pad to 4 byte alignment with zeroes. - */ - void writePad(const void* src, size_t size); - - /** - * Writes a string to the writer, which can be retrieved with - * SkReader32::readString(). - * The length can be specified, or if -1 is passed, it will be computed by - * calling strlen(). The length must be < 0xFFFF - */ - void writeString(const char* str, size_t len = (size_t)-1); - - /** - * Computes the size (aligned to multiple of 4) need to write the string - * in a call to writeString(). If the length is not specified, it will be - * computed by calling strlen(). - */ - static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); - - // return the address of the 4byte int at the specified offset (which must - // be a multiple of 4. This does not allocate any new space, so the returned - // address is only valid for 1 int. - uint32_t* peek32(size_t offset); - - /** - * Move the cursor back to offset bytes from the beginning. - * This has the same restrictions as peek32: offset must be <= size() and - * offset must be a multiple of 4. - */ - void rewindToOffset(size_t offset); - - // copy into a single buffer (allocated by caller). Must be at least size() - void flatten(void* dst) const; - - // read from the stream, and write up to length bytes. Return the actual - // number of bytes written. - size_t readFromStream(SkStream*, size_t length); - - bool writeToStream(SkWStream*); - -private: - struct Block { - Block* fNext; - char* fBasePtr; - size_t fSizeOfBlock; // total space allocated (after this) - size_t fAllocatedSoFar; // space used so far - - size_t available() const { return fSizeOfBlock - fAllocatedSoFar; } - char* base() { return fBasePtr; } - const char* base() const { return fBasePtr; } - - uint32_t* alloc(size_t size) { - SkASSERT(SkAlign4(size) == size); - SkASSERT(this->available() >= size); - void* ptr = this->base() + fAllocatedSoFar; - fAllocatedSoFar += size; - SkASSERT(fAllocatedSoFar <= fSizeOfBlock); - return (uint32_t*)ptr; - } - - uint32_t* peek32(size_t offset) { - SkASSERT(offset <= fAllocatedSoFar + 4); - void* ptr = this->base() + offset; - return (uint32_t*)ptr; - } - - void rewind() { - fNext = NULL; - fAllocatedSoFar = 0; - // keep fSizeOfBlock as is - } - - static Block* Create(size_t size) { - SkASSERT(SkIsAlign4(size)); - Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); - block->fNext = NULL; - block->fBasePtr = (char*)(block + 1); - block->fSizeOfBlock = size; - block->fAllocatedSoFar = 0; - return block; - } - - Block* initFromStorage(void* storage, size_t size) { - SkASSERT(SkIsAlign4((intptr_t)storage)); - SkASSERT(SkIsAlign4(size)); - Block* block = this; - block->fNext = NULL; - block->fBasePtr = (char*)storage; - block->fSizeOfBlock = size; - block->fAllocatedSoFar = 0; - return block; - } - }; - - enum { - MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t) - }; - - Block fExternalBlock; - Block* fHead; - Block* fTail; - size_t fMinSize; - uint32_t fSize; - // sum of bytes written in all blocks *before* fTail - uint32_t fWrittenBeforeLastBlock; - - bool isHeadExternallyAllocated() const { - return fHead == &fExternalBlock; - } - - Block* newBlock(size_t bytes); - - // only call from reserve() - Block* doReserve(size_t bytes); - - SkDEBUGCODE(void validate() const;) -}; - -/** - * Helper class to allocated SIZE bytes as part of the writer, and to provide - * that storage to the constructor as its initial storage buffer. - * - * This wrapper ensures proper alignment rules are met for the storage. - */ -template class SkSWriter32 : public SkWriter32 { -public: - SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {} - -private: - union { - void* fPtrAlignment; - double fDoubleAlignment; - char fStorage[SIZE]; - } fData; -}; - -#endif diff --git a/gfx/skia/include/effects/SkBlendImageFilter.h b/gfx/skia/include/effects/SkBlendImageFilter.h deleted file mode 100644 index a2dc84749427..000000000000 --- a/gfx/skia/include/effects/SkBlendImageFilter.h +++ /dev/null @@ -1,50 +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 SkBlendImageFilter_DEFINED -#define SkBlendImageFilter_DEFINED - -#include "SkImageFilter.h" -#include "SkBitmap.h" - -class SK_API SkBlendImageFilter : public SkImageFilter { -public: - enum Mode { - kNormal_Mode, - kMultiply_Mode, - kScreen_Mode, - kDarken_Mode, - kLighten_Mode, - }; - SkBlendImageFilter(Mode mode, SkImageFilter* background, SkImageFilter* foreground = NULL); - - ~SkBlendImageFilter(); - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlendImageFilter) - - virtual bool onFilterImage(Proxy* proxy, - const SkBitmap& src, - const SkMatrix& ctm, - SkBitmap* dst, - SkIPoint* offset) SK_OVERRIDE; -#if SK_SUPPORT_GPU - virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; } - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; -#endif - -protected: - explicit SkBlendImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - -private: - Mode fMode; - typedef SkImageFilter INHERITED; - SkImageFilter* getBackgroundInput() { return getInput(0); } - SkImageFilter* getForegroundInput() { return getInput(1); } -}; - -#endif diff --git a/gfx/skia/include/effects/SkMorphologyImageFilter.h b/gfx/skia/include/effects/SkMorphologyImageFilter.h deleted file mode 100644 index a189c757de1e..000000000000 --- a/gfx/skia/include/effects/SkMorphologyImageFilter.h +++ /dev/null @@ -1,73 +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 SkMorphologyImageFilter_DEFINED -#define SkMorphologyImageFilter_DEFINED - -#include "SkImageFilter.h" -#include "SkSize.h" - -class SK_API SkMorphologyImageFilter : public SkImageFilter { -public: - SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input); - -protected: - SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; -#if SK_SUPPORT_GPU - virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; } -#endif - - SkISize radius() const { return fRadius; } - -private: - SkISize fRadius; - typedef SkImageFilter INHERITED; -}; - -class SK_API SkDilateImageFilter : public SkMorphologyImageFilter { -public: - SkDilateImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL) - : INHERITED(radiusX, radiusY, input) {} - - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; -#if SK_SUPPORT_GPU - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; -#endif - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter) - -protected: - SkDilateImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} - -private: - typedef SkMorphologyImageFilter INHERITED; -}; - -class SK_API SkErodeImageFilter : public SkMorphologyImageFilter { -public: - SkErodeImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL) - : INHERITED(radiusX, radiusY, input) {} - - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; -#if SK_SUPPORT_GPU - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; -#endif - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter) - -protected: - SkErodeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} - -private: - typedef SkMorphologyImageFilter INHERITED; -}; - -#endif diff --git a/gfx/skia/include/effects/SkRectShaderImageFilter.h b/gfx/skia/include/effects/SkRectShaderImageFilter.h deleted file mode 100644 index a71ee42742b9..000000000000 --- a/gfx/skia/include/effects/SkRectShaderImageFilter.h +++ /dev/null @@ -1,43 +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 SkRectShaderImageFilter_DEFINED -#define SkRectShaderImageFilter_DEFINED - -#include "SkImageFilter.h" -#include "SkRect.h" - -class SkShader; - -class SK_API SkRectShaderImageFilter : public SkImageFilter { -public: - /** - * The SkShader object will have its refcnt increased as it becomes a member of the - * SkRectShaderImageFilter object returned by this function. It cannot be NULL. - * The region parameter is used to specify on which region the shader is applied. - */ - static SkRectShaderImageFilter* Create(SkShader* s, const SkRect& rect); - virtual ~SkRectShaderImageFilter(); - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter) - -protected: - SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - -private: - SkRectShaderImageFilter(SkShader* s, const SkRect& rect); - SkShader* fShader; - SkRect fRect; - - typedef SkImageFilter INHERITED; -}; - -#endif diff --git a/gfx/skia/include/effects/SkTestImageFilters.h b/gfx/skia/include/effects/SkTestImageFilters.h deleted file mode 100755 index c38c03793b39..000000000000 --- a/gfx/skia/include/effects/SkTestImageFilters.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _SkTestImageFilters_h -#define _SkTestImageFilters_h - -#include "SkImageFilter.h" -#include "SkPoint.h" - -class SK_API SkComposeImageFilter : public SkImageFilter { -public: - SkComposeImageFilter(SkImageFilter* outer, SkImageFilter* inner) : INHERITED(outer, inner) {} - virtual ~SkComposeImageFilter(); - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeImageFilter) - -protected: - SkComposeImageFilter(SkFlattenableReadBuffer& buffer); - - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE; - -private: - typedef SkImageFilter INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -// Fun mode that scales down (only) and then scales back up to look pixelated -class SK_API SkDownSampleImageFilter : public SkImageFilter { -public: - SkDownSampleImageFilter(SkScalar scale) : INHERITED(0), fScale(scale) {} - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDownSampleImageFilter) - -protected: - SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - - virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - -private: - SkScalar fScale; - - typedef SkImageFilter INHERITED; -}; - -#endif diff --git a/gfx/skia/include/gpu/GrAARectRenderer.h b/gfx/skia/include/gpu/GrAARectRenderer.h deleted file mode 100644 index 0cf7faac05ea..000000000000 --- a/gfx/skia/include/gpu/GrAARectRenderer.h +++ /dev/null @@ -1,65 +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 GrAARectRenderer_DEFINED -#define GrAARectRenderer_DEFINED - -#include "GrRect.h" -#include "GrRefCnt.h" - -class GrGpu; -class GrDrawTarget; -class GrIndexBuffer; - -/* - * This class wraps helper functions that draw AA rects (filled & stroked) - */ -class GrAARectRenderer : public GrRefCnt { -public: - SK_DECLARE_INST_COUNT(GrAARectRenderer) - - GrAARectRenderer() - : fAAFillRectIndexBuffer(NULL) - , fAAStrokeRectIndexBuffer(NULL) { - } - - void reset(); - - ~GrAARectRenderer() { - this->reset(); - } - - // TODO: potentialy fuse the fill & stroke methods and differentiate - // btween them by passing in strokeWidth (<0 means fill). - - // TODO: Remove the useVertexCoverage boolean. Just use it all the time - // since we now have a coverage vertex attribute - void fillAARect(GrGpu* gpu, - GrDrawTarget* target, - const GrRect& devRect, - bool useVertexCoverage); - - void strokeAARect(GrGpu* gpu, - GrDrawTarget* target, - const GrRect& devRect, - const GrVec& devStrokeSize, - bool useVertexCoverage); - -private: - GrIndexBuffer* fAAFillRectIndexBuffer; - GrIndexBuffer* fAAStrokeRectIndexBuffer; - - GrIndexBuffer* aaFillRectIndexBuffer(GrGpu* gpu); - - static int aaStrokeRectIndexCount(); - GrIndexBuffer* aaStrokeRectIndexBuffer(GrGpu* gpu); - - typedef GrRefCnt INHERITED; -}; - -#endif // GrAARectRenderer_DEFINED diff --git a/gfx/skia/include/gpu/GrEffectStage.h b/gfx/skia/include/gpu/GrEffectStage.h deleted file mode 100644 index 94ff779a185e..000000000000 --- a/gfx/skia/include/gpu/GrEffectStage.h +++ /dev/null @@ -1,211 +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. - */ - - - -#ifndef GrEffectStage_DEFINED -#define GrEffectStage_DEFINED - -#include "GrBackendEffectFactory.h" -#include "GrEffect.h" -#include "SkMatrix.h" -#include "GrTypes.h" - -#include "SkShader.h" - -class GrEffectStage { -public: - GrEffectStage() - : fEffectRef (NULL) { - GR_DEBUGCODE(fSavedCoordChangeCnt = 0;) - } - - ~GrEffectStage() { - GrSafeUnref(fEffectRef); - GrAssert(0 == fSavedCoordChangeCnt); - } - - bool operator ==(const GrEffectStage& other) const { - // first handle cases where one or the other has no effect - if (NULL == fEffectRef) { - return NULL == other.fEffectRef; - } else if (NULL == other.fEffectRef) { - return false; - } - - if (!(*this->getEffect())->isEqual(*other.getEffect())) { - return false; - } - - return fCoordChangeMatrix == other.fCoordChangeMatrix; - } - - bool operator !=(const GrEffectStage& s) const { return !(*this == s); } - - GrEffectStage& operator =(const GrEffectStage& other) { - GrSafeAssign(fEffectRef, other.fEffectRef); - if (NULL != fEffectRef) { - fCoordChangeMatrix = other.fCoordChangeMatrix; - } - return *this; - } - - /** - * This is called when the coordinate system in which the geometry is specified will change. - * - * @param matrix The transformation from the old coord system in which geometry is specified - * to the new one from which it will actually be drawn. - */ - void localCoordChange(const SkMatrix& matrix) { fCoordChangeMatrix.preConcat(matrix); } - - class SavedCoordChange { - private: - SkMatrix fCoordChangeMatrix; - GR_DEBUGCODE(mutable SkAutoTUnref fEffectRef;) - - friend class GrEffectStage; - }; - - /** - * This gets the current coordinate system change. It is the accumulation of - * localCoordChange calls since the effect was installed. It is used when then caller - * wants to temporarily change the source geometry coord system, draw something, and then - * restore the previous coord system (e.g. temporarily draw in device coords). - */ - void saveCoordChange(SavedCoordChange* savedCoordChange) const { - savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix; - GrAssert(NULL == savedCoordChange->fEffectRef.get()); - GR_DEBUGCODE(GrSafeRef(fEffectRef);) - GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef);) - GR_DEBUGCODE(++fSavedCoordChangeCnt); - } - - /** - * This balances the saveCoordChange call. - */ - void restoreCoordChange(const SavedCoordChange& savedCoordChange) { - fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix; - GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef); - GR_DEBUGCODE(--fSavedCoordChangeCnt); - GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);) - } - - /** - * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its - * GrEffect to be recycled through the cache. - */ - class DeferredStage { - public: - DeferredStage() : fEffect(NULL) { - SkDEBUGCODE(fInitialized = false;) - } - - ~DeferredStage() { - if (NULL != fEffect) { - fEffect->decDeferredRefCounts(); - } - } - - void saveFrom(const GrEffectStage& stage) { - GrAssert(!fInitialized); - if (NULL != stage.fEffectRef) { - stage.fEffectRef->get()->incDeferredRefCounts(); - fEffect = stage.fEffectRef->get(); - fCoordChangeMatrix = stage.fCoordChangeMatrix; - fVertexAttribIndices[0] = stage.fVertexAttribIndices[0]; - fVertexAttribIndices[1] = stage.fVertexAttribIndices[1]; - } - SkDEBUGCODE(fInitialized = true;) - } - - void restoreTo(GrEffectStage* stage) { - GrAssert(fInitialized); - const GrEffectRef* oldEffectRef = stage->fEffectRef; - if (NULL != fEffect) { - stage->fEffectRef = GrEffect::CreateEffectRef(fEffect); - stage->fCoordChangeMatrix = fCoordChangeMatrix; - stage->fVertexAttribIndices[0] = fVertexAttribIndices[0]; - stage->fVertexAttribIndices[1] = fVertexAttribIndices[1]; - } else { - stage->fEffectRef = NULL; - } - SkSafeUnref(oldEffectRef); - } - - bool isEqual(const GrEffectStage& stage) const { - if (NULL == stage.fEffectRef) { - return NULL == fEffect; - } else if (NULL == fEffect) { - return false; - } - - if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0] - || fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) { - return false; - } - - if (!(*stage.getEffect())->isEqual(*fEffect)) { - return false; - } - - return fCoordChangeMatrix == stage.fCoordChangeMatrix; - } - - private: - const GrEffect* fEffect; - SkMatrix fCoordChangeMatrix; - int fVertexAttribIndices[2]; - SkDEBUGCODE(bool fInitialized;) - }; - - /** - * Gets the matrix representing all changes of coordinate system since the GrEffect was - * installed in the stage. - */ - const SkMatrix& getCoordChangeMatrix() const { return fCoordChangeMatrix; } - - void reset() { - GrSafeSetNull(fEffectRef); - } - - const GrEffectRef* setEffect(const GrEffectRef* EffectRef) { - GrAssert(0 == fSavedCoordChangeCnt); - GrSafeAssign(fEffectRef, EffectRef); - fCoordChangeMatrix.reset(); - - fVertexAttribIndices[0] = -1; - fVertexAttribIndices[1] = -1; - - return EffectRef; - } - - const GrEffectRef* setEffect(const GrEffectRef* EffectRef, int attr0, int attr1 = -1) { - GrAssert(0 == fSavedCoordChangeCnt); - GrSafeAssign(fEffectRef, EffectRef); - fCoordChangeMatrix.reset(); - - fVertexAttribIndices[0] = attr0; - fVertexAttribIndices[1] = attr1; - - return EffectRef; - } - - const GrEffectRef* getEffect() const { return fEffectRef; } - - const int* getVertexAttribIndices() const { return fVertexAttribIndices; } - int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); } - -private: - SkMatrix fCoordChangeMatrix; - const GrEffectRef* fEffectRef; - int fVertexAttribIndices[2]; - - GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;) -}; - -#endif diff --git a/gfx/skia/include/gpu/GrNoncopyable.h b/gfx/skia/include/gpu/GrNoncopyable.h deleted file mode 100644 index 3d471709119c..000000000000 --- a/gfx/skia/include/gpu/GrNoncopyable.h +++ /dev/null @@ -1,30 +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. - */ - - - -#ifndef GrNoncopyable_DEFINED -#define GrNoncopyable_DEFINED - -#include "GrTypes.h" - -/** - * Base for classes that want to disallow copying themselves. It makes its - * copy-constructor and assignment operators private (and unimplemented). - */ -class GR_API GrNoncopyable { -public: - GrNoncopyable() {} - -private: - // illegal - GrNoncopyable(const GrNoncopyable&); - GrNoncopyable& operator=(const GrNoncopyable&); -}; - -#endif diff --git a/gfx/skia/include/gpu/GrOvalRenderer.h b/gfx/skia/include/gpu/GrOvalRenderer.h deleted file mode 100644 index 88dd0a4b99cb..000000000000 --- a/gfx/skia/include/gpu/GrOvalRenderer.h +++ /dev/null @@ -1,46 +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 GrOvalRenderer_DEFINED -#define GrOvalRenderer_DEFINED - -#include "GrContext.h" -#include "GrPaint.h" -#include "GrRefCnt.h" -#include "GrRect.h" - -class GrContext; -class GrDrawTarget; -class GrPaint; -class SkStrokeRec; - -/* - * This class wraps helper functions that draw ovals (filled & stroked) - */ -class GrOvalRenderer : public GrRefCnt { -public: - SK_DECLARE_INST_COUNT(GrOvalRenderer) - - GrOvalRenderer() {} - - ~GrOvalRenderer() {} - - bool drawOval(GrDrawTarget* target, const GrContext* context, const GrPaint& paint, - const GrRect& oval, const SkStrokeRec& stroke); -private: - void drawEllipse(GrDrawTarget* target, const GrPaint& paint, - const GrRect& ellipse, - const SkStrokeRec& stroke); - void drawCircle(GrDrawTarget* target, const GrPaint& paint, - const GrRect& circle, - const SkStrokeRec& stroke); - - typedef GrRefCnt INHERITED; -}; - -#endif // GrOvalRenderer_DEFINED diff --git a/gfx/skia/include/gpu/GrRefCnt.h b/gfx/skia/include/gpu/GrRefCnt.h deleted file mode 100644 index 31aa80dacdb1..000000000000 --- a/gfx/skia/include/gpu/GrRefCnt.h +++ /dev/null @@ -1,33 +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. - */ - - - -#ifndef GrRefCnt_DEFINED -#define GrRefCnt_DEFINED - -#include "GrTypes.h" -#include "SkRefCnt.h" - -typedef SkRefCnt GrRefCnt; -typedef SkAutoRef GrAutoRef; -typedef SkAutoUnref GrAutoUnref; - -#define GrSafeRef SkSafeRef -#define GrSafeUnref SkSafeUnref -#define GrSafeAssign(a, b) SkRefCnt_SafeAssign(a, b) - -template -static inline void GrSafeSetNull(T*& obj) { - if (NULL != obj) { - obj->unref(); - obj = NULL; - } -} - -#endif diff --git a/gfx/skia/include/gpu/GrTextContext.h b/gfx/skia/include/gpu/GrTextContext.h deleted file mode 100644 index 348f3abb45c3..000000000000 --- a/gfx/skia/include/gpu/GrTextContext.h +++ /dev/null @@ -1,60 +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. - */ - - - -#ifndef GrTextContext_DEFINED -#define GrTextContext_DEFINED - -#include "GrContext.h" -#include "GrGlyph.h" -#include "GrPaint.h" - -class GrContext; -class GrTextStrike; -class GrFontScaler; -class GrDrawTarget; - -class GrTextContext { -public: - GrTextContext(GrContext*, const GrPaint&); - ~GrTextContext(); - - void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, - GrFontScaler*); - - void flush(); // optional; automatically called by destructor - -private: - GrPaint fPaint; - GrContext* fContext; - GrDrawTarget* fDrawTarget; - - GrFontScaler* fScaler; - GrTextStrike* fStrike; - - inline void flushGlyphs(); - void setupDrawTarget(); - - enum { - kMinRequestedGlyphs = 1, - kDefaultRequestedGlyphs = 64, - kMinRequestedVerts = kMinRequestedGlyphs * 4, - kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, - }; - - SkPoint* fVertices; - int32_t fMaxVertices; - GrTexture* fCurrTexture; - int fCurrVertex; - - GrIRect fClipRect; - GrContext::AutoMatrix fAutoMatrix; -}; - -#endif diff --git a/gfx/skia/include/gpu/gl/GrGLInterface.h b/gfx/skia/include/gpu/gl/GrGLInterface.h deleted file mode 100644 index 58e3814d75d6..000000000000 --- a/gfx/skia/include/gpu/gl/GrGLInterface.h +++ /dev/null @@ -1,326 +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 GrGLInterface_DEFINED -#define GrGLInterface_DEFINED - -#include "GrGLFunctions.h" -#include "GrRefCnt.h" - -//////////////////////////////////////////////////////////////////////////////// - -/** - * Classifies GL contexts (currently as Desktop vs. ES2). This is a bitfield. - * A GrGLInterface (defined below) may support multiple bindings. - */ -enum GrGLBinding { - kNone_GrGLBinding = 0x0, - - kDesktop_GrGLBinding = 0x01, - kES2_GrGLBinding = 0x02, - - // for iteration of GrGLBindings - kFirstGrGLBinding = kDesktop_GrGLBinding, - kLastGrGLBinding = kES2_GrGLBinding -}; - -//////////////////////////////////////////////////////////////////////////////// - -/** - * Rather than depend on platform-specific GL headers and libraries, we require - * the client to provide a struct of GL function pointers. This struct can be - * specified per-GrContext as a parameter to GrContext::Create. If NULL is - * passed to Create then the "default" GL interface is used. If the default is - * also NULL GrContext creation will fail. - * - * The default interface is returned by GrGLDefaultInterface. This function's - * implementation is platform-specific. Several have been provided, along with - * an implementation that simply returns NULL. It is implementation-specific - * whether the same GrGLInterface is returned or whether a new one is created - * at each call. Some platforms may not be able to use a single GrGLInterface - * because extension function ptrs vary across contexts. Note that GrGLInterface - * is ref-counted. So if the same object is returned by multiple calls to - * GrGLDefaultInterface, each should bump the ref count. - * - * By defining GR_GL_PER_GL_CALL_IFACE_CALLBACK to 1 the client can specify a - * callback function that will be called prior to each GL function call. See - * comments in GrGLConfig.h - */ - -struct GrGLInterface; - -const GrGLInterface* GrGLDefaultInterface(); - -/** - * Creates a GrGLInterface for a "native" GL context (e.g. WGL on windows, - * GLX on linux, AGL on Mac). On platforms that have context-specific function - * pointers for GL extensions (e.g. windows) the returned interface is only - * valid for the context that was current at creation. - */ -const GrGLInterface* GrGLCreateNativeInterface(); - -#if SK_MESA -/** - * Creates a GrGLInterface for an OSMesa context. - */ -const GrGLInterface* GrGLCreateMesaInterface(); -#endif - -#if SK_ANGLE -/** - * Creates a GrGLInterface for an ANGLE context. - */ -const GrGLInterface* GrGLCreateANGLEInterface(); -#endif - -/** - * Creates a null GrGLInterface that doesn't draw anything. Used for measuring - * CPU overhead. - */ -const GrGLInterface* GrGLCreateNullInterface(); - -/** - * Creates a debugging GrGLInterface that doesn't draw anything. Used for - * finding memory leaks and invalid memory accesses. - */ -const GrGLInterface* GrGLCreateDebugInterface(); - -#if GR_GL_PER_GL_FUNC_CALLBACK -typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*); -typedef intptr_t GrGLInterfaceCallbackData; -#endif - -/* - * GrContext uses the following interface to make all calls into OpenGL. When a - * GrContext is created it is given a GrGLInterface. The interface's function - * pointers must be valid for the OpenGL context associated with the GrContext. - * On some platforms, such as Windows, function pointers for OpenGL extensions - * may vary between OpenGL contexts. So the caller must be careful to use a - * GrGLInterface initialized for the correct context. All functions that should - * be available based on the OpenGL's version and extension string must be - * non-NULL or GrContext creation will fail. This can be tested with the - * validate() method when the OpenGL context has been made current. - */ -struct GR_API GrGLInterface : public GrRefCnt { -private: - // simple wrapper class that exists only to initialize a pointer to NULL - template class GLPtr { - public: - GLPtr() : fPtr(NULL) {} - GLPtr operator =(FNPTR_TYPE ptr) { fPtr = ptr; return *this; } - operator FNPTR_TYPE() const { return fPtr; } - private: - FNPTR_TYPE fPtr; - }; - - typedef GrRefCnt INHERITED; - -public: - SK_DECLARE_INST_COUNT(GrGLInterface) - - GrGLInterface(); - - // Validates that the GrGLInterface supports a binding. This means that - // the GrGLinterface advertises the binding in fBindingsExported and all - // the necessary function pointers have been initialized. The interface is - // validated for the current OpenGL context. - bool validate(GrGLBinding binding) const; - - // Indicator variable specifying the type of GL implementation - // exported: GLES2 and/or Desktop. - GrGLBinding fBindingsExported; - - GLPtr fActiveTexture; - GLPtr fAttachShader; - GLPtr fBeginQuery; - GLPtr fBindAttribLocation; - GLPtr fBindBuffer; - GLPtr fBindFragDataLocation; - GLPtr fBindFragDataLocationIndexed; - GLPtr fBindFramebuffer; - GLPtr fBindRenderbuffer; - GLPtr fBindTexture; - GLPtr fBindVertexArray; - GLPtr fBlendColor; - GLPtr fBlendFunc; - GLPtr fBlitFramebuffer; - GLPtr fBufferData; - GLPtr fBufferSubData; - GLPtr fCheckFramebufferStatus; - GLPtr fClear; - GLPtr fClearColor; - GLPtr fClearStencil; - GLPtr fColorMask; - GLPtr fCompileShader; - GLPtr fCompressedTexImage2D; - GLPtr fCreateProgram; - GLPtr fCreateShader; - GLPtr fCullFace; - GLPtr fDeleteBuffers; - GLPtr fDeleteFramebuffers; - GLPtr fDeleteProgram; - GLPtr fDeleteQueries; - GLPtr fDeleteRenderbuffers; - GLPtr fDeleteShader; - GLPtr fDeleteTextures; - GLPtr fDeleteVertexArrays; - GLPtr fDepthMask; - GLPtr fDisable; - GLPtr fDisableVertexAttribArray; - GLPtr fDrawArrays; - GLPtr fDrawBuffer; - GLPtr fDrawBuffers; - GLPtr fDrawElements; - GLPtr fEnable; - GLPtr fEnableVertexAttribArray; - GLPtr fEndQuery; - GLPtr fFinish; - GLPtr fFlush; - GLPtr fFramebufferRenderbuffer; - GLPtr fFramebufferTexture2D; - GLPtr fFramebufferTexture2DMultisample; - GLPtr fFrontFace; - GLPtr fGenBuffers; - GLPtr fGenFramebuffers; - GLPtr fGenQueries; - GLPtr fGenRenderbuffers; - GLPtr fGenTextures; - GLPtr fGenVertexArrays; - GLPtr fGetBufferParameteriv; - GLPtr fGetError; - GLPtr fGetFramebufferAttachmentParameteriv; - GLPtr fGetIntegerv; - GLPtr fGetQueryObjecti64v; - GLPtr fGetQueryObjectiv; - GLPtr fGetQueryObjectui64v; - GLPtr fGetQueryObjectuiv; - GLPtr fGetQueryiv; - GLPtr fGetProgramInfoLog; - GLPtr fGetProgramiv; - GLPtr fGetRenderbufferParameteriv; - GLPtr fGetShaderInfoLog; - GLPtr fGetShaderiv; - GLPtr fGetString; - GLPtr fGetStringi; - GLPtr fGetTexLevelParameteriv; - GLPtr fGetUniformLocation; - GLPtr fLineWidth; - GLPtr fLinkProgram; - GLPtr fMapBuffer; - GLPtr fPixelStorei; - GLPtr fQueryCounter; - GLPtr fReadBuffer; - GLPtr fReadPixels; - GLPtr fRenderbufferStorage; - GLPtr fRenderbufferStorageMultisample; - GLPtr fRenderbufferStorageMultisampleCoverage; - GLPtr fResolveMultisampleFramebuffer; - GLPtr fScissor; - GLPtr fShaderSource; - GLPtr fStencilFunc; - GLPtr fStencilFuncSeparate; - GLPtr fStencilMask; - GLPtr fStencilMaskSeparate; - GLPtr fStencilOp; - GLPtr fStencilOpSeparate; - GLPtr fTexImage2D; - GLPtr fTexParameteri; - GLPtr fTexParameteriv; - GLPtr fTexSubImage2D; - GLPtr fTexStorage2D; - GLPtr fUniform1f; - GLPtr fUniform1i; - GLPtr fUniform1fv; - GLPtr fUniform1iv; - GLPtr fUniform2f; - GLPtr fUniform2i; - GLPtr fUniform2fv; - GLPtr fUniform2iv; - GLPtr fUniform3f; - GLPtr fUniform3i; - GLPtr fUniform3fv; - GLPtr fUniform3iv; - GLPtr fUniform4f; - GLPtr fUniform4i; - GLPtr fUniform4fv; - GLPtr fUniform4iv; - GLPtr fUniformMatrix2fv; - GLPtr fUniformMatrix3fv; - GLPtr fUniformMatrix4fv; - GLPtr fUnmapBuffer; - GLPtr fUseProgram; - GLPtr fVertexAttrib4fv; - GLPtr fVertexAttribPointer; - GLPtr fViewport; - - // Experimental: Functions for GL_NV_path_rendering. These will be - // alphabetized with the above functions once this is fully supported - // (and functions we are unlikely to use will possibly be omitted). - GLPtr fMatrixMode; - GLPtr fLoadIdentity; - GLPtr fLoadMatrixf; - GLPtr fPathCommands; - GLPtr fPathCoords; - GLPtr fPathSubCommands; - GLPtr fPathSubCoords; - GLPtr fPathString; - GLPtr fPathGlyphs; - GLPtr fPathGlyphRange; - GLPtr fWeightPaths; - GLPtr fCopyPath; - GLPtr fInterpolatePaths; - GLPtr fTransformPath; - GLPtr fPathParameteriv; - GLPtr fPathParameteri; - GLPtr fPathParameterfv; - GLPtr fPathParameterf; - GLPtr fPathDashArray; - GLPtr fGenPaths; - GLPtr fDeletePaths; - GLPtr fIsPath; - GLPtr fPathStencilFunc; - GLPtr fPathStencilDepthOffset; - GLPtr fStencilFillPath; - GLPtr fStencilStrokePath; - GLPtr fStencilFillPathInstanced; - GLPtr fStencilStrokePathInstanced; - GLPtr fPathCoverDepthFunc; - GLPtr fPathColorGen; - GLPtr fPathTexGen; - GLPtr fPathFogGen; - GLPtr fCoverFillPath; - GLPtr fCoverStrokePath; - GLPtr fCoverFillPathInstanced; - GLPtr fCoverStrokePathInstanced; - GLPtr fGetPathParameteriv; - GLPtr fGetPathParameterfv; - GLPtr fGetPathCommands; - GLPtr fGetPathCoords; - GLPtr fGetPathDashArray; - GLPtr fGetPathMetrics; - GLPtr fGetPathMetricRange; - GLPtr fGetPathSpacing; - GLPtr fGetPathColorGeniv; - GLPtr fGetPathColorGenfv; - GLPtr fGetPathTexGeniv; - GLPtr fGetPathTexGenfv; - GLPtr fIsPointInFillPath; - GLPtr fIsPointInStrokePath; - GLPtr fGetPathLength; - GLPtr fPointAlongPath; - - // Per-GL func callback -#if GR_GL_PER_GL_FUNC_CALLBACK - GrGLInterfaceCallbackProc fCallback; - GrGLInterfaceCallbackData fCallbackData; -#endif - -}; - -#endif diff --git a/gfx/skia/include/images/SkBitmapRegionDecoder.h b/gfx/skia/include/images/SkBitmapRegionDecoder.h deleted file mode 100644 index 56332343ccf3..000000000000 --- a/gfx/skia/include/images/SkBitmapRegionDecoder.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#ifndef SkBitmapRegionDecoder_DEFINED -#define SkBitmapRegionDecoder_DEFINED - -#include "SkBitmap.h" -#include "SkImageDecoder.h" -#include "SkStream.h" - -struct SkIRect; - -/** - * SkBitmapRegionDecoder can be used to decode a specified rect from an image. - * This is particularly useful when the original image is large and you only - * need parts of the image. - * - * However, not all image codecs on all platforms support this feature so be - * prepared to fallback to standard decoding if decodeRegion(...) returns false. - */ -class SkBitmapRegionDecoder { -public: - SkBitmapRegionDecoder(SkImageDecoder* decoder, SkStream* stream, - int width, int height) { - fDecoder = decoder; - fStream = stream; - fWidth = width; - fHeight = height; - } - ~SkBitmapRegionDecoder() { - SkDELETE(fDecoder); - SkSafeUnref(fStream); - } - - bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, - SkBitmap::Config pref, int sampleSize); - - SkImageDecoder* getDecoder() const { return fDecoder; } - int getWidth() const { return fWidth; } - int getHeight() const { return fHeight; } - -private: - SkImageDecoder* fDecoder; - SkStream* fStream; - int fWidth; - int fHeight; -}; - -#endif diff --git a/gfx/skia/include/lazy/SkBitmapFactory.h b/gfx/skia/include/lazy/SkBitmapFactory.h deleted file mode 100644 index eb427ee390c8..000000000000 --- a/gfx/skia/include/lazy/SkBitmapFactory.h +++ /dev/null @@ -1,95 +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 SkBitmapFactory_DEFINED -#define SkBitmapFactory_DEFINED - -#include "SkImage.h" -#include "SkTypes.h" - -class SkBitmap; -class SkData; -class SkImageCache; - -/** - * Factory for creating a bitmap from encoded data. - */ -class SkBitmapFactory { - -public: - /** - * Struct containing information about a pixel destination. - */ - struct Target { - /** - * Pre-allocated memory. - */ - void* fAddr; - - /** - * Rowbytes of the allocated memory. - */ - size_t fRowBytes; - }; - - /** - * Signature for a function to decode an image from encoded data. - */ - typedef bool (*DecodeProc)(const void* data, size_t length, SkImage::Info*, const Target*); - - /** - * Create a bitmap factory which uses DecodeProc for decoding. - * @param DecodeProc Must not be NULL. - */ - SkBitmapFactory(DecodeProc); - - ~SkBitmapFactory(); - - /** - * Set an image cache to use on pixelrefs provided by installPixelRef. Mutually exclusive - * with fCacheSelector. - */ - void setImageCache(SkImageCache* cache); - - /** - * Sets up an SkBitmap from encoded data. On success, the SkBitmap will have its Config, - * width, height, rowBytes and pixelref set. If fImageCache is non-NULL, or if fCacheSelector - * is set and returns non-NULL, the pixelref will lazily decode, and that SkImageCache will - * handle the pixel memory. Otherwise installPixelRef will do an immediate decode. - * @param SkData Encoded data. - * @param SkBitmap to install the pixel ref on. - * @return bool Whether or not a pixel ref was successfully installed. - */ - bool installPixelRef(SkData*, SkBitmap*); - - /** - * An object for selecting an SkImageCache to use based on an SkImage::Info. - */ - class CacheSelector : public SkRefCnt { - - public: - /** - * Return an SkImageCache to use based on the provided SkImage::Info. If the caller decides - * to hang on to the result, it will call ref, so the implementation should not add a ref - * as a result of this call. - */ - virtual SkImageCache* selectCache(const SkImage::Info&) = 0; - }; - - /** - * Set the function to be used to select which SkImageCache to use. Mutually exclusive with - * fImageCache. - */ - void setCacheSelector(CacheSelector*); - -private: - DecodeProc fDecodeProc; - SkImageCache* fImageCache; - CacheSelector* fCacheSelector; -}; - -#endif // SkBitmapFactory_DEFINED diff --git a/gfx/skia/include/lazy/SkImageCache.h b/gfx/skia/include/lazy/SkImageCache.h deleted file mode 100644 index bfd5269ee905..000000000000 --- a/gfx/skia/include/lazy/SkImageCache.h +++ /dev/null @@ -1,125 +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 SkImageCache_DEFINED -#define SkImageCache_DEFINED - -#include "SkRefCnt.h" -#include "SkTypes.h" - -/** - * Interface for a cache that manages pixel memory. - */ -class SkImageCache : public SkRefCnt { - -public: - /** - * Allocate memory whose lifetime is managed by the cache. On success, MUST be balanced with a - * call to releaseCache and a call to throwAwayCache. - * @param bytes Number of bytes needed. - * @param ID Output parameter which must not be NULL. On success, ID will be set to a value - * associated with that memory which can be used as a parameter to the other functions - * in SkImageCache. On failure, ID is unchanged. - * @return Pointer to the newly allocated memory, or NULL. This memory is safe to use until - * releaseCache is called with ID. - */ - virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) = 0; - - /** - * Output parameter for pinCache, stating whether the memory still contains the data it held - * when releaseCache was last called for the same ID. - */ - enum DataStatus { - /** - * The data has been purged, and therefore needs to be rewritten to the returned memory. - */ - kUninitialized_DataStatus, - - /** - * The memory still contains the data it held when releaseCache was last called with the - * same ID. - */ - kRetained_DataStatus, - }; - - /** - * Re-request the memory associated with ID and pin it so that it will not be reclaimed until - * the next call to releaseCache with the same ID. - * @param ID Unique ID for the memory block. - * @param status Output parameter which must not be NULL. On success (i.e. the return value is - * not NULL), status will be set to one of two states representing the cached memory. If - * status is set to kRetained_DataStatus, the memory contains the same data it did - * before releaseCache was called with this ID. If status is set to - * kUninitialized_DataStatus, the memory is still pinned, but the previous data is no - * longer available. If the return value is NULL, status is unchanged. - * @return Pointer: If non-NULL, points to the previously allocated memory, in which case - * this call must be balanced with a call to releaseCache. If NULL, the memory - * has been reclaimed, and throwAwayCache MUST NOT be called. - */ - virtual void* pinCache(intptr_t ID, DataStatus* status) = 0; - - /** - * Inform the cache that it is safe to free the block of memory corresponding to ID. After - * calling this function, the pointer returned by allocAndPinCache or pinCache must not be - * used again. In order to access the same memory after this, pinCache must be called with - * the same ID. - * @param ID Unique ID for the memory block which is now safe to age out of the cache. - */ - virtual void releaseCache(intptr_t ID) = 0; - - /** - * Inform the cache that the block of memory associated with ID will not be asked for again. - * After this call, ID is no longer valid. Must not be called while the associated memory is - * pinned. Must be called to balance a successful allocAndPinCache. - */ - virtual void throwAwayCache(intptr_t ID) = 0; - - /** - * ID which does not correspond to any valid cache. - */ - static const intptr_t UNINITIALIZED_ID = 0; - -#ifdef SK_DEBUG - /** - * Debug only status of a memory block. - */ - enum MemoryStatus { - /** - * It is safe to use the pointer returned by the most recent of allocAndPinCache(ID) or - * pinCache(ID) with the same ID. - */ - kPinned_MemoryStatus, - - /** - * The pointer returned by the most recent call to allocAndPinCache(ID) or pinCache(ID) has - * since been released by releaseCache(ID). In order to reuse it, pinCache(ID) must be - * called again. Note that after calling releaseCache(ID), the status of that particular - * ID may not be kUnpinned_MemoryStatus, depending on the implementation, but it will not - * be kPinned_MemoryStatus. - */ - kUnpinned_MemoryStatus, - - /** - * The memory associated with ID has been thrown away. No calls should be made using the - * same ID. - */ - kFreed_MemoryStatus, - }; - - /** - * Debug only function to get the status of a particular block of memory. Safe to call after - * throwAwayCache has been called with this ID. - */ - virtual MemoryStatus getMemoryStatus(intptr_t ID) const = 0; - - /** - * Debug only function to clear all unpinned caches. - */ - virtual void purgeAllUnpinnedCaches() = 0; -#endif -}; -#endif // SkImageCache_DEFINED diff --git a/gfx/skia/include/lazy/SkLruImageCache.h b/gfx/skia/include/lazy/SkLruImageCache.h deleted file mode 100644 index f655230a9328..000000000000 --- a/gfx/skia/include/lazy/SkLruImageCache.h +++ /dev/null @@ -1,89 +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 SkLruImageCache_DEFINED -#define SkLruImageCache_DEFINED - -#include "SkImageCache.h" -#include "SkThread.h" -#include "SkTInternalLList.h" - -class CachedPixels; - -/** - * SkImageCache implementation that uses an LRU cache to age out old images. - */ -class SkLruImageCache : public SkImageCache { - -public: - SkLruImageCache(size_t budget); - - virtual ~SkLruImageCache(); - -#ifdef SK_DEBUG - virtual MemoryStatus getMemoryStatus(intptr_t ID) const SK_OVERRIDE; - virtual void purgeAllUnpinnedCaches() SK_OVERRIDE; -#endif - - /** - * Set the byte limit on cached pixels. If more bytes are used than this, the cache will free - * unpinned memory until under the new limit or until all unpinned memory is freed. This will - * never free pinned memory, so the cache can potentially remain over the limit. The limit is - * enforced each time memory is allocated or released. - * 0 is a special flag for an infinite budget. - * @return size_t The previous limit. - */ - size_t setImageCacheLimit(size_t newLimit); - - /** - * Return the number of bytes of memory currently in use by the cache. Can include memory that - * is no longer pinned, but has not been freed. - */ - size_t getImageCacheUsed() const { return fRamUsed; } - - virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) SK_OVERRIDE; - virtual void* pinCache(intptr_t ID, SkImageCache::DataStatus*) SK_OVERRIDE; - virtual void releaseCache(intptr_t ID) SK_OVERRIDE; - virtual void throwAwayCache(intptr_t ID) SK_OVERRIDE; - -private: - // Linked list of recently used. Head is the most recently used, and tail is the least. - SkTInternalLList fLRU; - typedef SkTInternalLList::Iter Iter; - -#ifdef SK_DEBUG - // fMutex is mutable so that getMemoryStatus can be const - mutable -#endif - SkMutex fMutex; - size_t fRamBudget; - size_t fRamUsed; - - /** - * Find the CachedPixels represented by ID, or NULL if not in the cache. Mutex must be locked - * before calling. - */ - CachedPixels* findByID(intptr_t ID) const; - - /** - * If over budget, throw away pixels which are not currently in use until below budget or there - * are no more pixels eligible to be thrown away. Mutex must be locked before calling. - */ - void purgeIfNeeded(); - - /** - * Purge until below limit. Mutex must be locked before calling. - */ - void purgeTilAtOrBelow(size_t limit); - - /** - * Remove a set of CachedPixels. Mutex must be locked before calling. - */ - void removePixels(CachedPixels*); -}; - -#endif // SkLruImageCache_DEFINED diff --git a/gfx/skia/include/lazy/SkPurgeableImageCache.h b/gfx/skia/include/lazy/SkPurgeableImageCache.h deleted file mode 100644 index 0516ff18eff5..000000000000 --- a/gfx/skia/include/lazy/SkPurgeableImageCache.h +++ /dev/null @@ -1,45 +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 SkPurgeableImageCache_DEFINED -#define SkPurgeableImageCache_DEFINED - -#include "SkImageCache.h" - -#ifdef SK_DEBUG - #include "SkTDArray.h" -#endif - -/** - * Implementation for SkImageCache that uses system defined purgeable memory. - */ -class SkPurgeableImageCache : public SkImageCache { - -public: - static SkImageCache* Create(); - - virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) SK_OVERRIDE; - virtual void* pinCache(intptr_t ID, SkImageCache::DataStatus*) SK_OVERRIDE; - virtual void releaseCache(intptr_t ID) SK_OVERRIDE; - virtual void throwAwayCache(intptr_t ID) SK_OVERRIDE; - -#ifdef SK_DEBUG - virtual MemoryStatus getMemoryStatus(intptr_t ID) const SK_OVERRIDE; - virtual void purgeAllUnpinnedCaches() SK_OVERRIDE; - virtual ~SkPurgeableImageCache(); -#endif - -private: - SkPurgeableImageCache(); - -#ifdef SK_DEBUG - SkTDArray fRecs; - int findRec(intptr_t) const; -#endif - void removeRec(intptr_t); -}; -#endif // SkPurgeableImageCache_DEFINED diff --git a/gfx/skia/include/ports/SkTypeface_android.h b/gfx/skia/include/ports/SkTypeface_android.h deleted file mode 100644 index 05921679649e..000000000000 --- a/gfx/skia/include/ports/SkTypeface_android.h +++ /dev/null @@ -1,98 +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 SkTypeface_android_DEFINED -#define SkTypeface_android_DEFINED - -#include "SkTypeface.h" - -enum FallbackScripts { - kArabic_FallbackScript, - kArmenian_FallbackScript, - kBengali_FallbackScript, - kDevanagari_FallbackScript, - kEthiopic_FallbackScript, - kGeorgian_FallbackScript, - kHebrewRegular_FallbackScript, - kHebrewBold_FallbackScript, - kKannada_FallbackScript, - kMalayalam_FallbackScript, - kTamilRegular_FallbackScript, - kTamilBold_FallbackScript, - kThai_FallbackScript, - kTelugu_FallbackScript, - kFallbackScriptNumber -}; - -// This particular mapping will be removed after WebKit is updated to use the -// new mappings. No new caller should use the kTamil_FallbackScript but rather -// the more specific Tamil scripts in the standard enum. -#define kTamil_FallbackScript kTamilRegular_FallbackScript - -#define SkTypeface_ValidScript(s) (s >= 0 && s < kFallbackScriptNumber) - -/** - * Return a new typeface for a fallback script. If the script is - * not valid, or can not map to a font, returns null. - * @param script The script id. - * @return reference to the matching typeface. Caller must call - * unref() when they are done. - */ -SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script); - -/** - * Return the string representation for the fallback script on Android. - * If the script is not valid, returns null. - */ -SK_API const char* SkGetFallbackScriptID(FallbackScripts script); - -/** - * Return the fallback script enum for the ID on Android. - * If the ID is not valid, or can not map to a fallback - * script, returns kFallbackScriptNumber. - */ -SK_API FallbackScripts SkGetFallbackScriptFromID(const char* id); - -/** - * Return a new typeface of the font in the fallback font list containing - * the specified chararacter. If no typeface is found, returns null. - */ -SK_API SkTypeface* SkCreateFallbackTypefaceForChar(SkUnichar uni, - SkTypeface::Style style); - -/** - * Get the family name of the font in the fallback font list containing - * the specified chararacter. if no font is found, returns false. - */ -SK_API bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name); - -/** - * For test only. - * Load font config from given xml files, instead of those from Android system. - */ -SK_API void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, - const char* fontsdir); - -/** - * Given a "current" fontID, return a ref to the next logical typeface - * when searching fonts for a given unicode value. Typically the caller - * will query a given font, and if a unicode value is not supported, they - * will call this, and if 0 is not returned, will search that font, and so - * on. This process must be finite, and when the fonthost sees a - * font with no logical successor, it must return NULL. - * - * The original fontID is also provided. This is the initial font that was - * stored in the typeface of the caller. It is provided as an aid to choose - * the best next logical font. e.g. If the original font was bold or serif, - * but the 2nd in the logical chain was plain, then a subsequent call to - * get the 3rd can still inspect the original, and try to match its - * stylistic attributes. - */ -SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID); - -#endif diff --git a/gfx/skia/include/utils/SkPictureUtils.h b/gfx/skia/include/utils/SkPictureUtils.h deleted file mode 100644 index 5e6b051f4548..000000000000 --- a/gfx/skia/include/utils/SkPictureUtils.h +++ /dev/null @@ -1,31 +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 SkPictureUtils_DEFINED -#define SkPictureUtils_DEFINED - -#include "SkPicture.h" - -class SkData; -struct SkRect; - -class SK_API SkPictureUtils { -public: - /** - * Given a rectangular visible "window" into the picture, return an array - * of SkPixelRefs that might intersect that area. To keep the call fast, - * the returned list is not guaranteed to be exact, so it may miss some, - * and it may return false positives. - * - * The pixelrefs returned in the SkData are already owned by the picture, - * so the returned pointers are only valid while the picture is in scope - * and remains unchanged. - */ - static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area); -}; - -#endif diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build index 64fd62cfc72e..c1a400f50743 100644 --- a/gfx/skia/moz.build +++ b/gfx/skia/moz.build @@ -1,620 +1,831 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - EXPORTS.skia += [ - 'include/config/SkUserConfig.h', - 'include/core/Sk64.h', - 'include/core/SkAdvancedTypefaceMetrics.h', - 'include/core/SkBitmap.h', - 'include/core/SkBlitRow.h', - 'include/core/SkBounder.h', - 'include/core/SkCanvas.h', - 'include/core/SkChunkAlloc.h', - 'include/core/SkClipStack.h', - 'include/core/SkColor.h', - 'include/core/SkColorFilter.h', - 'include/core/SkColorPriv.h', - 'include/core/SkColorShader.h', - 'include/core/SkColorTable.h', - 'include/core/SkComposeShader.h', - 'include/core/SkData.h', - 'include/core/SkDeque.h', - 'include/core/SkDevice.h', - 'include/core/SkDeviceProperties.h', - 'include/core/SkDither.h', - 'include/core/SkDraw.h', - 'include/core/SkDrawFilter.h', - 'include/core/SkDrawLooper.h', - 'include/core/SkEmptyShader.h', - 'include/core/SkEndian.h', - 'include/core/SkFixed.h', - 'include/core/SkFlattenable.h', - 'include/core/SkFloatBits.h', - 'include/core/SkFloatingPoint.h', - 'include/core/SkFontHost.h', - 'include/core/SkFontLCDConfig.h', - 'include/core/SkGeometry.h', - 'include/core/SkGraphics.h', - 'include/core/SkInstCnt.h', - 'include/core/SkLineClipper.h', - 'include/core/SkMallocPixelRef.h', - 'include/core/SkMask.h', - 'include/core/SkMaskFilter.h', - 'include/core/SkMath.h', - 'include/core/SkMatrix.h', - 'include/core/SkMetaData.h', - 'include/core/SkOSFile.h', - 'include/core/SkPackBits.h', - 'include/core/SkPaint.h', - 'include/core/SkPath.h', - 'include/core/SkPathEffect.h', - 'include/core/SkPathMeasure.h', - 'include/core/SkPicture.h', - 'include/core/SkPixelRef.h', - 'include/core/SkPoint.h', - 'include/core/SkPostConfig.h', - 'include/core/SkPreConfig.h', - 'include/core/SkRasterizer.h', - 'include/core/SkReader32.h', - 'include/core/SkRect.h', - 'include/core/SkRefCnt.h', - 'include/core/SkRegion.h', - 'include/core/SkScalar.h', - 'include/core/SkScalarCompare.h', - 'include/core/SkShader.h', - 'include/core/SkSize.h', - 'include/core/SkStream.h', - 'include/core/SkString.h', - 'include/core/SkStrokeRec.h', - 'include/core/SkTArray.h', - 'include/core/SkTDArray.h', - 'include/core/SkTDict.h', - 'include/core/SkTDStack.h', - 'include/core/SkTemplates.h', - 'include/core/SkThread.h', - 'include/core/SkThread_platform.h', - 'include/core/SkTime.h', - 'include/core/SkTInternalLList.h', - 'include/core/SkTLazy.h', - 'include/core/SkTrace.h', - 'include/core/SkTRegistry.h', - 'include/core/SkTScopedPtr.h', - 'include/core/SkTSearch.h', - 'include/core/SkTypeface.h', - 'include/core/SkTypes.h', - 'include/core/SkUnitMapper.h', - 'include/core/SkUnPreMultiply.h', - 'include/core/SkUtils.h', - 'include/core/SkWeakRefCnt.h', - 'include/core/SkWriter32.h', - 'include/core/SkXfermode.h', - 'include/effects/SkBlurDrawLooper.h', - 'include/effects/SkBlurMaskFilter.h', - 'include/effects/SkDashPathEffect.h', - 'include/effects/SkGradientShader.h', - 'include/effects/SkLayerDrawLooper.h', - 'include/effects/SkLayerRasterizer.h', - 'include/effects/SkMorphologyImageFilter.h', - 'include/gpu/gl/GrGLConfig.h', - 'include/gpu/gl/GrGLFunctions.h', - 'include/gpu/gl/GrGLInterface.h', - 'include/gpu/gl/SkANGLEGLContext.h', - 'include/gpu/gl/SkDebugGLContext.h', - 'include/gpu/gl/SkMesaGLContext.h', - 'include/gpu/gl/SkNativeGLContext.h', - 'include/gpu/gl/SkNullGLContext.h', - 'include/gpu/GrAARectRenderer.h', - 'include/gpu/GrBackendEffectFactory.h', - 'include/gpu/GrClipData.h', - 'include/gpu/GrColor.h', - 'include/gpu/GrConfig.h', - 'include/gpu/GrContext.h', - 'include/gpu/GrContextFactory.h', - 'include/gpu/GrEffect.h', - 'include/gpu/GrEffectStage.h', - 'include/gpu/GrEffectUnitTest.h', - 'include/gpu/GrFontScaler.h', - 'include/gpu/GrGlyph.h', - 'include/gpu/GrKey.h', - 'include/gpu/GrNoncopyable.h', - 'include/gpu/GrPaint.h', - 'include/gpu/GrPathRendererChain.h', - 'include/gpu/GrPoint.h', - 'include/gpu/GrRect.h', - 'include/gpu/GrRefCnt.h', - 'include/gpu/GrRenderTarget.h', - 'include/gpu/GrResource.h', - 'include/gpu/GrSurface.h', - 'include/gpu/GrTextContext.h', - 'include/gpu/GrTexture.h', - 'include/gpu/GrTextureAccess.h', - 'include/gpu/GrTypes.h', - 'include/gpu/GrTypesPriv.h', - 'include/gpu/GrUserConfig.h', - 'include/gpu/SkGpuDevice.h', - 'include/gpu/SkGr.h', - 'include/gpu/SkGrPixelRef.h', - 'include/gpu/SkGrTexturePixelRef.h', - 'include/lazy/SkBitmapFactory.h', - 'include/utils/SkDeferredCanvas.h', - 'include/utils/SkRandom.h', - 'include/views/SkTextBox.h', - 'src/core/SkTypefaceCache.h', -] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - EXPORTS.skia += [ - 'include/ports/SkTypeface_mac.h', + 'trunk/include/animator/SkAnimator.h', + 'trunk/include/animator/SkAnimatorView.h', + 'trunk/include/config/SkUserConfig.h', + 'trunk/include/core/Sk64.h', + 'trunk/include/core/SkAdvancedTypefaceMetrics.h', + 'trunk/include/core/SkAnnotation.h', + 'trunk/include/core/SkBitmap.h', + 'trunk/include/core/SkBitmapDevice.h', + 'trunk/include/core/SkBlitRow.h', + 'trunk/include/core/SkBounder.h', + 'trunk/include/core/SkCanvas.h', + 'trunk/include/core/SkChecksum.h', + 'trunk/include/core/SkChunkAlloc.h', + 'trunk/include/core/SkClipStack.h', + 'trunk/include/core/SkColor.h', + 'trunk/include/core/SkColorFilter.h', + 'trunk/include/core/SkColorPriv.h', + 'trunk/include/core/SkColorShader.h', + 'trunk/include/core/SkColorTable.h', + 'trunk/include/core/SkComposeShader.h', + 'trunk/include/core/SkData.h', + 'trunk/include/core/SkDataTable.h', + 'trunk/include/core/SkDeque.h', + 'trunk/include/core/SkDevice.h', + 'trunk/include/core/SkDeviceProperties.h', + 'trunk/include/core/SkDither.h', + 'trunk/include/core/SkDocument.h', + 'trunk/include/core/SkDraw.h', + 'trunk/include/core/SkDrawFilter.h', + 'trunk/include/core/SkDrawLooper.h', + 'trunk/include/core/SkDynamicAnnotations.h', + 'trunk/include/core/SkEmptyShader.h', + 'trunk/include/core/SkEndian.h', + 'trunk/include/core/SkError.h', + 'trunk/include/core/SkFixed.h', + 'trunk/include/core/SkFlate.h', + 'trunk/include/core/SkFlattenable.h', + 'trunk/include/core/SkFlattenableBuffers.h', + 'trunk/include/core/SkFlattenableSerialization.h', + 'trunk/include/core/SkFloatBits.h', + 'trunk/include/core/SkFloatingPoint.h', + 'trunk/include/core/SkFontHost.h', + 'trunk/include/core/SkFontLCDConfig.h', + 'trunk/include/core/SkGeometry.h', + 'trunk/include/core/SkGraphics.h', + 'trunk/include/core/SkImage.h', + 'trunk/include/core/SkImageDecoder.h', + 'trunk/include/core/SkImageEncoder.h', + 'trunk/include/core/SkImageFilter.h', + 'trunk/include/core/SkImageFilterUtils.h', + 'trunk/include/core/SkImageGenerator.h', + 'trunk/include/core/SkImageInfo.h', + 'trunk/include/core/SkInstCnt.h', + 'trunk/include/core/SkLineClipper.h', + 'trunk/include/core/SkMallocPixelRef.h', + 'trunk/include/core/SkMask.h', + 'trunk/include/core/SkMaskFilter.h', + 'trunk/include/core/SkMath.h', + 'trunk/include/core/SkMatrix.h', + 'trunk/include/core/SkMetaData.h', + 'trunk/include/core/SkOnce.h', + 'trunk/include/core/SkOSFile.h', + 'trunk/include/core/SkPackBits.h', + 'trunk/include/core/SkPaint.h', + 'trunk/include/core/SkPaintOptionsAndroid.h', + 'trunk/include/core/SkPath.h', + 'trunk/include/core/SkPathEffect.h', + 'trunk/include/core/SkPathMeasure.h', + 'trunk/include/core/SkPathRef.h', + 'trunk/include/core/SkPicture.h', + 'trunk/include/core/SkPixelRef.h', + 'trunk/include/core/SkPoint.h', + 'trunk/include/core/SkPostConfig.h', + 'trunk/include/core/SkPreConfig.h', + 'trunk/include/core/SkRasterizer.h', + 'trunk/include/core/SkReadBuffer.h', + 'trunk/include/core/SkReader32.h', + 'trunk/include/core/SkRect.h', + 'trunk/include/core/SkRefCnt.h', + 'trunk/include/core/SkRegion.h', + 'trunk/include/core/SkRRect.h', + 'trunk/include/core/SkScalar.h', + 'trunk/include/core/SkScalarCompare.h', + 'trunk/include/core/SkShader.h', + 'trunk/include/core/SkSize.h', + 'trunk/include/core/SkStream.h', + 'trunk/include/core/SkString.h', + 'trunk/include/core/SkStringUtils.h', + 'trunk/include/core/SkStrokeRec.h', + 'trunk/include/core/SkSurface.h', + 'trunk/include/core/SkTArray.h', + 'trunk/include/core/SkTDArray.h', + 'trunk/include/core/SkTDict.h', + 'trunk/include/core/SkTDStack.h', + 'trunk/include/core/SkTemplates.h', + 'trunk/include/core/SkThread.h', + 'trunk/include/core/SkThread_platform.h', + 'trunk/include/core/SkTileGridPicture.h', + 'trunk/include/core/SkTime.h', + 'trunk/include/core/SkTInternalLList.h', + 'trunk/include/core/SkTLazy.h', + 'trunk/include/core/SkTrace.h', + 'trunk/include/core/SkTRegistry.h', + 'trunk/include/core/SkTSearch.h', + 'trunk/include/core/SkTypeface.h', + 'trunk/include/core/SkTypes.h', + 'trunk/include/core/SkUnitMapper.h', + 'trunk/include/core/SkUnPreMultiply.h', + 'trunk/include/core/SkUtils.h', + 'trunk/include/core/SkWeakRefCnt.h', + 'trunk/include/core/SkWriteBuffer.h', + 'trunk/include/core/SkWriter32.h', + 'trunk/include/core/SkXfermode.h', + 'trunk/include/device/xps/SkConstexprMath.h', + 'trunk/include/device/xps/SkXPSDevice.h', + 'trunk/include/effects/Sk1DPathEffect.h', + 'trunk/include/effects/Sk2DPathEffect.h', + 'trunk/include/effects/SkAlphaThresholdFilter.h', + 'trunk/include/effects/SkArithmeticMode.h', + 'trunk/include/effects/SkAvoidXfermode.h', + 'trunk/include/effects/SkBicubicImageFilter.h', + 'trunk/include/effects/SkBitmapAlphaThresholdShader.h', + 'trunk/include/effects/SkBitmapSource.h', + 'trunk/include/effects/SkBlurDrawLooper.h', + 'trunk/include/effects/SkBlurImageFilter.h', + 'trunk/include/effects/SkBlurMaskFilter.h', + 'trunk/include/effects/SkColorFilterImageFilter.h', + 'trunk/include/effects/SkColorMatrix.h', + 'trunk/include/effects/SkColorMatrixFilter.h', + 'trunk/include/effects/SkComposeImageFilter.h', + 'trunk/include/effects/SkCornerPathEffect.h', + 'trunk/include/effects/SkDashPathEffect.h', + 'trunk/include/effects/SkDiscretePathEffect.h', + 'trunk/include/effects/SkDisplacementMapEffect.h', + 'trunk/include/effects/SkDrawExtraPathEffect.h', + 'trunk/include/effects/SkDropShadowImageFilter.h', + 'trunk/include/effects/SkEmbossMaskFilter.h', + 'trunk/include/effects/SkGradientShader.h', + 'trunk/include/effects/SkKernel33MaskFilter.h', + 'trunk/include/effects/SkLayerDrawLooper.h', + 'trunk/include/effects/SkLayerRasterizer.h', + 'trunk/include/effects/SkLerpXfermode.h', + 'trunk/include/effects/SkLightingImageFilter.h', + 'trunk/include/effects/SkLumaColorFilter.h', + 'trunk/include/effects/SkMagnifierImageFilter.h', + 'trunk/include/effects/SkMatrixConvolutionImageFilter.h', + 'trunk/include/effects/SkMergeImageFilter.h', + 'trunk/include/effects/SkMorphologyImageFilter.h', + 'trunk/include/effects/SkOffsetImageFilter.h', + 'trunk/include/effects/SkPaintFlagsDrawFilter.h', + 'trunk/include/effects/SkPerlinNoiseShader.h', + 'trunk/include/effects/SkPictureImageFilter.h', + 'trunk/include/effects/SkPixelXorXfermode.h', + 'trunk/include/effects/SkPorterDuff.h', + 'trunk/include/effects/SkRectShaderImageFilter.h', + 'trunk/include/effects/SkResizeImageFilter.h', + 'trunk/include/effects/SkStippleMaskFilter.h', + 'trunk/include/effects/SkTableColorFilter.h', + 'trunk/include/effects/SkTableMaskFilter.h', + 'trunk/include/effects/SkTestImageFilters.h', + 'trunk/include/effects/SkTileImageFilter.h', + 'trunk/include/effects/SkTransparentShader.h', + 'trunk/include/effects/SkXfermodeImageFilter.h', + 'trunk/include/gpu/gl/GrGLConfig.h', + 'trunk/include/gpu/gl/GrGLConfig_chrome.h', + 'trunk/include/gpu/gl/GrGLExtensions.h', + 'trunk/include/gpu/gl/GrGLFunctions.h', + 'trunk/include/gpu/gl/GrGLInterface.h', + 'trunk/include/gpu/gl/SkANGLEGLContext.h', + 'trunk/include/gpu/gl/SkDebugGLContext.h', + 'trunk/include/gpu/gl/SkGLContextHelper.h', + 'trunk/include/gpu/gl/SkMesaGLContext.h', + 'trunk/include/gpu/gl/SkNativeGLContext.h', + 'trunk/include/gpu/gl/SkNullGLContext.h', + 'trunk/include/gpu/GrBackendEffectFactory.h', + 'trunk/include/gpu/GrBitmapTextContext.h', + 'trunk/include/gpu/GrClipData.h', + 'trunk/include/gpu/GrColor.h', + 'trunk/include/gpu/GrConfig.h', + 'trunk/include/gpu/GrContext.h', + 'trunk/include/gpu/GrContextFactory.h', + 'trunk/include/gpu/GrCoordTransform.h', + 'trunk/include/gpu/GrDistanceFieldTextContext.h', + 'trunk/include/gpu/GrDrawEffect.h', + 'trunk/include/gpu/GrEffect.h', + 'trunk/include/gpu/GrEffectStage.h', + 'trunk/include/gpu/GrEffectUnitTest.h', + 'trunk/include/gpu/GrFontScaler.h', + 'trunk/include/gpu/GrGlyph.h', + 'trunk/include/gpu/GrKey.h', + 'trunk/include/gpu/GrPaint.h', + 'trunk/include/gpu/GrPathRendererChain.h', + 'trunk/include/gpu/GrPoint.h', + 'trunk/include/gpu/GrRect.h', + 'trunk/include/gpu/GrRenderTarget.h', + 'trunk/include/gpu/GrResource.h', + 'trunk/include/gpu/GrSurface.h', + 'trunk/include/gpu/GrTBackendEffectFactory.h', + 'trunk/include/gpu/GrTextContext.h', + 'trunk/include/gpu/GrTexture.h', + 'trunk/include/gpu/GrTextureAccess.h', + 'trunk/include/gpu/GrTypes.h', + 'trunk/include/gpu/GrTypesPriv.h', + 'trunk/include/gpu/GrUserConfig.h', + 'trunk/include/gpu/SkGpuDevice.h', + 'trunk/include/gpu/SkGr.h', + 'trunk/include/gpu/SkGrPixelRef.h', + 'trunk/include/gpu/SkGrTexturePixelRef.h', + 'trunk/include/images/SkForceLinking.h', + 'trunk/include/images/SkImageRef.h', + 'trunk/include/images/SkImageRef_GlobalPool.h', + 'trunk/include/images/SkImages.h', + 'trunk/include/images/SkMovie.h', + 'trunk/include/images/SkPageFlipper.h', + 'trunk/include/pathops/SkPathOps.h', + 'trunk/include/pdf/SkPDFDevice.h', + 'trunk/include/pdf/SkPDFDocument.h', + 'trunk/include/pipe/SkGPipe.h', + 'trunk/include/ports/SkFontConfigInterface.h', + 'trunk/include/ports/SkFontMgr.h', + 'trunk/include/ports/SkFontStyle.h', + 'trunk/include/ports/SkHarfBuzzFont.h', + 'trunk/include/ports/SkTypeface_android.h', + 'trunk/include/ports/SkTypeface_cairo.h', + 'trunk/include/ports/SkTypeface_mac.h', + 'trunk/include/ports/SkTypeface_win.h', + 'trunk/include/svg/SkSVGAttribute.h', + 'trunk/include/svg/SkSVGBase.h', + 'trunk/include/svg/SkSVGPaintState.h', + 'trunk/include/svg/SkSVGParser.h', + 'trunk/include/svg/SkSVGTypes.h', + 'trunk/include/text/SkTextLayout.h', + 'trunk/include/utils/ios/SkStream_NSData.h', + 'trunk/include/utils/mac/SkCGUtils.h', + 'trunk/include/utils/SkBoundaryPatch.h', + 'trunk/include/utils/SkCamera.h', + 'trunk/include/utils/SkCanvasStateUtils.h', + 'trunk/include/utils/SkCondVar.h', + 'trunk/include/utils/SkCountdown.h', + 'trunk/include/utils/SkCubicInterval.h', + 'trunk/include/utils/SkCullPoints.h', + 'trunk/include/utils/SkDebugUtils.h', + 'trunk/include/utils/SkDeferredCanvas.h', + 'trunk/include/utils/SkDumpCanvas.h', + 'trunk/include/utils/SkEventTracer.h', + 'trunk/include/utils/SkFrontBufferedStream.h', + 'trunk/include/utils/SkInterpolator.h', + 'trunk/include/utils/SkJSON.h', + 'trunk/include/utils/SkJSONCPP.h', + 'trunk/include/utils/SkLayer.h', + 'trunk/include/utils/SkLua.h', + 'trunk/include/utils/SkLuaCanvas.h', + 'trunk/include/utils/SkMatrix44.h', + 'trunk/include/utils/SkMeshUtils.h', + 'trunk/include/utils/SkNinePatch.h', + 'trunk/include/utils/SkNullCanvas.h', + 'trunk/include/utils/SkNWayCanvas.h', + 'trunk/include/utils/SkParse.h', + 'trunk/include/utils/SkParsePaint.h', + 'trunk/include/utils/SkParsePath.h', + 'trunk/include/utils/SkPathUtils.h', + 'trunk/include/utils/SkPictureUtils.h', + 'trunk/include/utils/SkProxyCanvas.h', + 'trunk/include/utils/SkRandom.h', + 'trunk/include/utils/SkRTConf.h', + 'trunk/include/utils/SkRunnable.h', + 'trunk/include/utils/SkThreadPool.h', + 'trunk/include/utils/SkUnitMappers.h', + 'trunk/include/utils/SkWGL.h', + 'trunk/include/utils/win/SkAutoCoInitialize.h', + 'trunk/include/utils/win/SkHRESULT.h', + 'trunk/include/utils/win/SkIStream.h', + 'trunk/include/utils/win/SkTScopedComPtr.h', + 'trunk/include/views/android/AndroidKeyToSkKey.h', + 'trunk/include/views/animated/SkBorderView.h', + 'trunk/include/views/animated/SkImageView.h', + 'trunk/include/views/animated/SkProgressBarView.h', + 'trunk/include/views/animated/SkScrollBarView.h', + 'trunk/include/views/animated/SkWidgetViews.h', + 'trunk/include/views/SkApplication.h', + 'trunk/include/views/SkBGViewArtist.h', + 'trunk/include/views/SkEvent.h', + 'trunk/include/views/SkEventSink.h', + 'trunk/include/views/SkKey.h', + 'trunk/include/views/SkOSMenu.h', + 'trunk/include/views/SkOSWindow_Android.h', + 'trunk/include/views/SkOSWindow_iOS.h', + 'trunk/include/views/SkOSWindow_Mac.h', + 'trunk/include/views/SkOSWindow_NaCl.h', + 'trunk/include/views/SkOSWindow_SDL.h', + 'trunk/include/views/SkOSWindow_Unix.h', + 'trunk/include/views/SkOSWindow_Win.h', + 'trunk/include/views/SkStackViewLayout.h', + 'trunk/include/views/SkSystemEventTypes.h', + 'trunk/include/views/SkTextBox.h', + 'trunk/include/views/SkTouchGesture.h', + 'trunk/include/views/SkView.h', + 'trunk/include/views/SkViewInflate.h', + 'trunk/include/views/SkWidget.h', + 'trunk/include/views/SkWindow.h', + 'trunk/include/views/unix/keysym2ucs.h', + 'trunk/include/views/unix/XkeysToSkKeys.h', + 'trunk/include/xml/SkBML_WXMLParser.h', + 'trunk/include/xml/SkBML_XMLParser.h', + 'trunk/include/xml/SkDOM.h', + 'trunk/include/xml/SkJS.h', + 'trunk/include/xml/SkXMLParser.h', + 'trunk/include/xml/SkXMLWriter.h', + 'trunk/src/ports/SkAtomics_android.h', + 'trunk/src/ports/SkAtomics_sync.h', + 'trunk/src/ports/SkAtomics_win.h', + 'trunk/src/ports/SkMutex_pthread.h', + 'trunk/src/ports/SkMutex_win.h', ] - UNIFIED_SOURCES += [ - 'src/ports/SkThread_pthread.cpp', - 'src/ports/SkTime_Unix.cpp', - 'src/utils/mac/SkStream_mac.cpp', - 'src/utils/SkThreadUtils_pthread.cpp', - 'src/utils/SkThreadUtils_pthread_mach.cpp', +SOURCES += [ + 'trunk/src/core/SkAAClip.cpp', + 'trunk/src/core/SkAdvancedTypefaceMetrics.cpp', + 'trunk/src/core/SkAlphaRuns.cpp', + 'trunk/src/core/SkAnnotation.cpp', + 'trunk/src/core/SkBBoxHierarchyRecord.cpp', + 'trunk/src/core/SkBBoxRecord.cpp', + 'trunk/src/core/SkBitmap.cpp', + 'trunk/src/core/SkBitmap_scroll.cpp', + 'trunk/src/core/SkBitmapDevice.cpp', + 'trunk/src/core/SkBitmapFilter.cpp', + 'trunk/src/core/SkBitmapHeap.cpp', + 'trunk/src/core/SkBitmapProcShader.cpp', + 'trunk/src/core/SkBitmapProcState.cpp', + 'trunk/src/core/SkBitmapProcState_matrixProcs.cpp', + 'trunk/src/core/SkBitmapScaler.cpp', + 'trunk/src/core/SkBlitMask_D32.cpp', + 'trunk/src/core/SkBlitRow_D16.cpp', + 'trunk/src/core/SkBlitRow_D32.cpp', + 'trunk/src/core/SkBlitter.cpp', + 'trunk/src/core/SkBlitter_A8.cpp', + 'trunk/src/core/SkBlitter_ARGB32.cpp', + 'trunk/src/core/SkBlitter_RGB16.cpp', + 'trunk/src/core/SkBlitter_Sprite.cpp', + 'trunk/src/core/SkBuffer.cpp', + 'trunk/src/core/SkCanvas.cpp', + 'trunk/src/core/SkChunkAlloc.cpp', + 'trunk/src/core/SkClipStack.cpp', + 'trunk/src/core/SkColor.cpp', + 'trunk/src/core/SkColorFilter.cpp', + 'trunk/src/core/SkColorTable.cpp', + 'trunk/src/core/SkComposeShader.cpp', + 'trunk/src/core/SkConfig8888.cpp', + 'trunk/src/core/SkConvolver.cpp', + 'trunk/src/core/SkCubicClipper.cpp', + 'trunk/src/core/SkData.cpp', + 'trunk/src/core/SkDataTable.cpp', + 'trunk/src/core/SkDebug.cpp', + 'trunk/src/core/SkDeque.cpp', + 'trunk/src/core/SkDevice.cpp', + 'trunk/src/core/SkDeviceLooper.cpp', + 'trunk/src/core/SkDeviceProfile.cpp', + 'trunk/src/core/SkDither.cpp', + 'trunk/src/core/SkDraw.cpp', + 'trunk/src/core/SkDrawLooper.cpp', + 'trunk/src/core/SkEdge.cpp', + 'trunk/src/core/SkEdgeBuilder.cpp', + 'trunk/src/core/SkEdgeClipper.cpp', + 'trunk/src/core/SkError.cpp', + 'trunk/src/core/SkFilterProc.cpp', + 'trunk/src/core/SkFilterShader.cpp', + 'trunk/src/core/SkFlattenable.cpp', + 'trunk/src/core/SkFlattenableSerialization.cpp', + 'trunk/src/core/SkFloat.cpp', + 'trunk/src/core/SkFloatBits.cpp', + 'trunk/src/core/SkFontDescriptor.cpp', + 'trunk/src/core/SkFontHost.cpp', + 'trunk/src/core/SkFontStream.cpp', + 'trunk/src/core/SkGeometry.cpp', + 'trunk/src/core/SkGlyphCache.cpp', + 'trunk/src/core/SkGraphics.cpp', + 'trunk/src/core/SkImageFilter.cpp', + 'trunk/src/core/SkImageFilterUtils.cpp', + 'trunk/src/core/SkImageInfo.cpp', + 'trunk/src/core/SkInstCnt.cpp', + 'trunk/src/core/SkLineClipper.cpp', + 'trunk/src/core/SkMallocPixelRef.cpp', + 'trunk/src/core/SkMask.cpp', + 'trunk/src/core/SkMaskFilter.cpp', + 'trunk/src/core/SkMaskGamma.cpp', + 'trunk/src/core/SkMath.cpp', + 'trunk/src/core/SkMatrix.cpp', + 'trunk/src/core/SkMatrixClipStateMgr.cpp', + 'trunk/src/core/SkMetaData.cpp', + 'trunk/src/core/SkMipMap.cpp', + 'trunk/src/core/SkPackBits.cpp', + 'trunk/src/core/SkPaint.cpp', + 'trunk/src/core/SkPaintOptionsAndroid.cpp', + 'trunk/src/core/SkPaintPriv.cpp', + 'trunk/src/core/SkPath.cpp', + 'trunk/src/core/SkPathEffect.cpp', + 'trunk/src/core/SkPathHeap.cpp', + 'trunk/src/core/SkPathMeasure.cpp', + 'trunk/src/core/SkPathRef.cpp', + 'trunk/src/core/SkPicture.cpp', + 'trunk/src/core/SkPictureFlat.cpp', + 'trunk/src/core/SkPicturePlayback.cpp', + 'trunk/src/core/SkPictureRecord.cpp', + 'trunk/src/core/SkPictureStateTree.cpp', + 'trunk/src/core/SkPixelRef.cpp', + 'trunk/src/core/SkPoint.cpp', + 'trunk/src/core/SkProcSpriteBlitter.cpp', + 'trunk/src/core/SkPtrRecorder.cpp', + 'trunk/src/core/SkQuadClipper.cpp', + 'trunk/src/core/SkQuadTree.cpp', + 'trunk/src/core/SkQuadTreePicture.cpp', + 'trunk/src/core/SkRasterClip.cpp', + 'trunk/src/core/SkRasterizer.cpp', + 'trunk/src/core/SkReadBuffer.cpp', + 'trunk/src/core/SkRect.cpp', + 'trunk/src/core/SkRefDict.cpp', + 'trunk/src/core/SkRegion.cpp', + 'trunk/src/core/SkRegion_path.cpp', + 'trunk/src/core/SkRRect.cpp', + 'trunk/src/core/SkRTree.cpp', + 'trunk/src/core/SkScalar.cpp', + 'trunk/src/core/SkScaledImageCache.cpp', + 'trunk/src/core/SkScalerContext.cpp', + 'trunk/src/core/SkScan.cpp', + 'trunk/src/core/SkScan_Antihair.cpp', + 'trunk/src/core/SkScan_AntiPath.cpp', + 'trunk/src/core/SkScan_Hairline.cpp', + 'trunk/src/core/SkScan_Path.cpp', + 'trunk/src/core/SkShader.cpp', + 'trunk/src/core/SkSpriteBlitter_ARGB32.cpp', + 'trunk/src/core/SkSpriteBlitter_RGB16.cpp', + 'trunk/src/core/SkStream.cpp', + 'trunk/src/core/SkString.cpp', + 'trunk/src/core/SkStringUtils.cpp', + 'trunk/src/core/SkStroke.cpp', + 'trunk/src/core/SkStrokeRec.cpp', + 'trunk/src/core/SkStrokerPriv.cpp', + 'trunk/src/core/SkTileGrid.cpp', + 'trunk/src/core/SkTileGridPicture.cpp', + 'trunk/src/core/SkTLS.cpp', + 'trunk/src/core/SkTSearch.cpp', + 'trunk/src/core/SkTypeface.cpp', + 'trunk/src/core/SkTypefaceCache.cpp', + 'trunk/src/core/SkUnPreMultiply.cpp', + 'trunk/src/core/SkUtils.cpp', + 'trunk/src/core/SkValidatingReadBuffer.cpp', + 'trunk/src/core/SkWriteBuffer.cpp', + 'trunk/src/core/SkWriter32.cpp', + 'trunk/src/core/SkXfermode.cpp', + 'trunk/src/doc/SkDocument.cpp', + 'trunk/src/effects/gradients/SkBitmapCache.cpp', + 'trunk/src/effects/gradients/SkClampRange.cpp', + 'trunk/src/effects/gradients/SkGradientShader.cpp', + 'trunk/src/effects/gradients/SkLinearGradient.cpp', + 'trunk/src/effects/gradients/SkRadialGradient.cpp', + 'trunk/src/effects/gradients/SkSweepGradient.cpp', + 'trunk/src/effects/gradients/SkTwoPointConicalGradient.cpp', + 'trunk/src/effects/gradients/SkTwoPointRadialGradient.cpp', + 'trunk/src/effects/Sk1DPathEffect.cpp', + 'trunk/src/effects/Sk2DPathEffect.cpp', + 'trunk/src/effects/SkAlphaThresholdFilter.cpp', + 'trunk/src/effects/SkArithmeticMode.cpp', + 'trunk/src/effects/SkAvoidXfermode.cpp', + 'trunk/src/effects/SkBicubicImageFilter.cpp', + 'trunk/src/effects/SkBitmapSource.cpp', + 'trunk/src/effects/SkBlurDrawLooper.cpp', + 'trunk/src/effects/SkBlurImageFilter.cpp', + 'trunk/src/effects/SkBlurMask.cpp', + 'trunk/src/effects/SkBlurMaskFilter.cpp', + 'trunk/src/effects/SkColorFilterImageFilter.cpp', + 'trunk/src/effects/SkColorFilters.cpp', + 'trunk/src/effects/SkColorMatrix.cpp', + 'trunk/src/effects/SkColorMatrixFilter.cpp', + 'trunk/src/effects/SkComposeImageFilter.cpp', + 'trunk/src/effects/SkCornerPathEffect.cpp', + 'trunk/src/effects/SkDashPathEffect.cpp', + 'trunk/src/effects/SkDiscretePathEffect.cpp', + 'trunk/src/effects/SkDisplacementMapEffect.cpp', + 'trunk/src/effects/SkDropShadowImageFilter.cpp', + 'trunk/src/effects/SkEmbossMask.cpp', + 'trunk/src/effects/SkEmbossMaskFilter.cpp', + 'trunk/src/effects/SkGpuBlurUtils.cpp', + 'trunk/src/effects/SkKernel33MaskFilter.cpp', + 'trunk/src/effects/SkLayerDrawLooper.cpp', + 'trunk/src/effects/SkLayerRasterizer.cpp', + 'trunk/src/effects/SkLerpXfermode.cpp', + 'trunk/src/effects/SkLightingImageFilter.cpp', + 'trunk/src/effects/SkLumaColorFilter.cpp', + 'trunk/src/effects/SkMagnifierImageFilter.cpp', + 'trunk/src/effects/SkMatrixConvolutionImageFilter.cpp', + 'trunk/src/effects/SkMergeImageFilter.cpp', + 'trunk/src/effects/SkMorphologyImageFilter.cpp', + 'trunk/src/effects/SkOffsetImageFilter.cpp', + 'trunk/src/effects/SkPaintFlagsDrawFilter.cpp', + 'trunk/src/effects/SkPerlinNoiseShader.cpp', + 'trunk/src/effects/SkPictureImageFilter.cpp', + 'trunk/src/effects/SkPixelXorXfermode.cpp', + 'trunk/src/effects/SkPorterDuff.cpp', + 'trunk/src/effects/SkRectShaderImageFilter.cpp', + 'trunk/src/effects/SkResizeImageFilter.cpp', + 'trunk/src/effects/SkStippleMaskFilter.cpp', + 'trunk/src/effects/SkTableColorFilter.cpp', + 'trunk/src/effects/SkTableMaskFilter.cpp', + 'trunk/src/effects/SkTestImageFilters.cpp', + 'trunk/src/effects/SkTileImageFilter.cpp', + 'trunk/src/effects/SkTransparentShader.cpp', + 'trunk/src/effects/SkXfermodeImageFilter.cpp', + 'trunk/src/fonts/SkGScalerContext.cpp', + 'trunk/src/gpu/effects/GrBezierEffect.cpp', + 'trunk/src/gpu/effects/GrBicubicEffect.cpp', + 'trunk/src/gpu/effects/GrConfigConversionEffect.cpp', + 'trunk/src/gpu/effects/GrConvexPolyEffect.cpp', + 'trunk/src/gpu/effects/GrConvolutionEffect.cpp', + 'trunk/src/gpu/effects/GrCustomCoordsTextureEffect.cpp', + 'trunk/src/gpu/effects/GrSimpleTextureEffect.cpp', + 'trunk/src/gpu/effects/GrSingleTextureEffect.cpp', + 'trunk/src/gpu/effects/GrTextureDomain.cpp', + 'trunk/src/gpu/effects/GrTextureStripAtlas.cpp', + 'trunk/src/gpu/gl/debug/GrBufferObj.cpp', + 'trunk/src/gpu/gl/debug/GrDebugGL.cpp', + 'trunk/src/gpu/gl/debug/GrFrameBufferObj.cpp', + 'trunk/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp', + 'trunk/src/gpu/gl/debug/GrProgramObj.cpp', + 'trunk/src/gpu/gl/debug/GrShaderObj.cpp', + 'trunk/src/gpu/gl/debug/GrTextureObj.cpp', + 'trunk/src/gpu/gl/debug/GrTextureUnitObj.cpp', + 'trunk/src/gpu/gl/debug/SkDebugGLContext.cpp', + 'trunk/src/gpu/gl/GrGLBufferImpl.cpp', + 'trunk/src/gpu/gl/GrGLCaps.cpp', + 'trunk/src/gpu/gl/GrGLContext.cpp', + 'trunk/src/gpu/gl/GrGLCreateNativeInterface_none.cpp', + 'trunk/src/gpu/gl/GrGLCreateNullInterface.cpp', + 'trunk/src/gpu/gl/GrGLDefaultInterface_native.cpp', + 'trunk/src/gpu/gl/GrGLExtensions.cpp', + 'trunk/src/gpu/gl/GrGLIndexBuffer.cpp', + 'trunk/src/gpu/gl/GrGLInterface.cpp', + 'trunk/src/gpu/gl/GrGLNoOpInterface.cpp', + 'trunk/src/gpu/gl/GrGLPath.cpp', + 'trunk/src/gpu/gl/GrGLProgram.cpp', + 'trunk/src/gpu/gl/GrGLProgramDesc.cpp', + 'trunk/src/gpu/gl/GrGLProgramEffects.cpp', + 'trunk/src/gpu/gl/GrGLRenderTarget.cpp', + 'trunk/src/gpu/gl/GrGLShaderBuilder.cpp', + 'trunk/src/gpu/gl/GrGLSL.cpp', + 'trunk/src/gpu/gl/GrGLStencilBuffer.cpp', + 'trunk/src/gpu/gl/GrGLTexture.cpp', + 'trunk/src/gpu/gl/GrGLUniformManager.cpp', + 'trunk/src/gpu/gl/GrGLUtil.cpp', + 'trunk/src/gpu/gl/GrGLVertexArray.cpp', + 'trunk/src/gpu/gl/GrGLVertexBuffer.cpp', + 'trunk/src/gpu/gl/GrGpuGL.cpp', + 'trunk/src/gpu/gl/GrGpuGL_program.cpp', + 'trunk/src/gpu/gl/SkGLContextHelper.cpp', + 'trunk/src/gpu/gl/SkNullGLContext.cpp', + 'trunk/src/gpu/GrAAConvexPathRenderer.cpp', + 'trunk/src/gpu/GrAAHairLinePathRenderer.cpp', + 'trunk/src/gpu/GrAARectRenderer.cpp', + 'trunk/src/gpu/GrAddPathRenderers_default.cpp', + 'trunk/src/gpu/GrAllocPool.cpp', + 'trunk/src/gpu/GrAtlas.cpp', + 'trunk/src/gpu/GrBitmapTextContext.cpp', + 'trunk/src/gpu/GrBlend.cpp', + 'trunk/src/gpu/GrBufferAllocPool.cpp', + 'trunk/src/gpu/GrCacheID.cpp', + 'trunk/src/gpu/GrClipData.cpp', + 'trunk/src/gpu/GrClipMaskCache.cpp', + 'trunk/src/gpu/GrClipMaskManager.cpp', + 'trunk/src/gpu/GrContext.cpp', + 'trunk/src/gpu/GrDefaultPathRenderer.cpp', + 'trunk/src/gpu/GrDrawState.cpp', + 'trunk/src/gpu/GrDrawTarget.cpp', + 'trunk/src/gpu/GrEffect.cpp', + 'trunk/src/gpu/GrGpu.cpp', + 'trunk/src/gpu/GrGpuFactory.cpp', + 'trunk/src/gpu/GrInOrderDrawBuffer.cpp', + 'trunk/src/gpu/GrMemoryPool.cpp', + 'trunk/src/gpu/GrOvalRenderer.cpp', + 'trunk/src/gpu/GrPaint.cpp', + 'trunk/src/gpu/GrPath.cpp', + 'trunk/src/gpu/GrPathRenderer.cpp', + 'trunk/src/gpu/GrPathRendererChain.cpp', + 'trunk/src/gpu/GrPathUtils.cpp', + 'trunk/src/gpu/GrRectanizer.cpp', + 'trunk/src/gpu/GrRectanizer_skyline.cpp', + 'trunk/src/gpu/GrReducedClip.cpp', + 'trunk/src/gpu/GrRenderTarget.cpp', + 'trunk/src/gpu/GrResource.cpp', + 'trunk/src/gpu/GrResourceCache.cpp', + 'trunk/src/gpu/GrSoftwarePathRenderer.cpp', + 'trunk/src/gpu/GrStencil.cpp', + 'trunk/src/gpu/GrStencilAndCoverPathRenderer.cpp', + 'trunk/src/gpu/GrStencilBuffer.cpp', + 'trunk/src/gpu/GrSurface.cpp', + 'trunk/src/gpu/GrSWMaskHelper.cpp', + 'trunk/src/gpu/GrTextContext.cpp', + 'trunk/src/gpu/GrTextStrike.cpp', + 'trunk/src/gpu/GrTexture.cpp', + 'trunk/src/gpu/GrTextureAccess.cpp', + 'trunk/src/gpu/SkGpuDevice.cpp', + 'trunk/src/gpu/SkGr.cpp', + 'trunk/src/gpu/SkGrFontScaler.cpp', + 'trunk/src/gpu/SkGrPixelRef.cpp', + 'trunk/src/gpu/SkGrTexturePixelRef.cpp', + 'trunk/src/image/SkImage.cpp', + 'trunk/src/image/SkImage_Gpu.cpp', + 'trunk/src/image/SkImage_Picture.cpp', + 'trunk/src/image/SkImage_Raster.cpp', + 'trunk/src/image/SkImagePriv.cpp', + 'trunk/src/image/SkSurface.cpp', + 'trunk/src/image/SkSurface_Gpu.cpp', + 'trunk/src/image/SkSurface_Picture.cpp', + 'trunk/src/image/SkSurface_Raster.cpp', + 'trunk/src/images/bmpdecoderhelper.cpp', + 'trunk/src/images/SkDecodingImageGenerator.cpp', + 'trunk/src/images/SkImageRef.cpp', + 'trunk/src/images/SkImageRef_GlobalPool.cpp', + 'trunk/src/images/SkImageRefPool.cpp', + 'trunk/src/images/SkPageFlipper.cpp', + 'trunk/src/images/SkScaledBitmapSampler.cpp', + 'trunk/src/images/SkStreamHelpers.cpp', + 'trunk/src/lazy/SkCachingPixelRef.cpp', + 'trunk/src/lazy/SkDiscardableMemoryPool.cpp', + 'trunk/src/lazy/SkDiscardablePixelRef.cpp', + 'trunk/src/pathops/SkAddIntersections.cpp', + 'trunk/src/pathops/SkDCubicIntersection.cpp', + 'trunk/src/pathops/SkDCubicLineIntersection.cpp', + 'trunk/src/pathops/SkDCubicToQuads.cpp', + 'trunk/src/pathops/SkDLineIntersection.cpp', + 'trunk/src/pathops/SkDQuadImplicit.cpp', + 'trunk/src/pathops/SkDQuadIntersection.cpp', + 'trunk/src/pathops/SkDQuadLineIntersection.cpp', + 'trunk/src/pathops/SkIntersections.cpp', + 'trunk/src/pathops/SkOpAngle.cpp', + 'trunk/src/pathops/SkOpContour.cpp', + 'trunk/src/pathops/SkOpEdgeBuilder.cpp', + 'trunk/src/pathops/SkOpSegment.cpp', + 'trunk/src/pathops/SkPathOpsBounds.cpp', + 'trunk/src/pathops/SkPathOpsCommon.cpp', + 'trunk/src/pathops/SkPathOpsCubic.cpp', + 'trunk/src/pathops/SkPathOpsDebug.cpp', + 'trunk/src/pathops/SkPathOpsLine.cpp', + 'trunk/src/pathops/SkPathOpsOp.cpp', + 'trunk/src/pathops/SkPathOpsPoint.cpp', + 'trunk/src/pathops/SkPathOpsQuad.cpp', + 'trunk/src/pathops/SkPathOpsRect.cpp', + 'trunk/src/pathops/SkPathOpsSimplify.cpp', + 'trunk/src/pathops/SkPathOpsTriangle.cpp', + 'trunk/src/pathops/SkPathOpsTypes.cpp', + 'trunk/src/pathops/SkPathWriter.cpp', + 'trunk/src/pathops/SkQuarticRoot.cpp', + 'trunk/src/pathops/SkReduceOrder.cpp', + 'trunk/src/pipe/SkGPipeRead.cpp', + 'trunk/src/pipe/SkGPipeWrite.cpp', + 'trunk/src/ports/SkDiscardableMemory_none.cpp', + 'trunk/src/ports/SkGlobalInitialization_default.cpp', + 'trunk/src/ports/SkImageDecoder_empty.cpp', + 'trunk/src/ports/SkMemory_malloc.cpp', + 'trunk/src/ports/SkOSFile_stdio.cpp', + 'trunk/src/sfnt/SkOTTable_name.cpp', + 'trunk/src/sfnt/SkOTUtils.cpp', + 'trunk/src/utils/SkBase64.cpp', + 'trunk/src/utils/SkBitSet.cpp', + 'trunk/src/utils/SkBoundaryPatch.cpp', + 'trunk/src/utils/SkCamera.cpp', + 'trunk/src/utils/SkCanvasStack.cpp', + 'trunk/src/utils/SkCanvasStateUtils.cpp', + 'trunk/src/utils/SkCondVar.cpp', + 'trunk/src/utils/SkCountdown.cpp', + 'trunk/src/utils/SkCubicInterval.cpp', + 'trunk/src/utils/SkCullPoints.cpp', + 'trunk/src/utils/SkDeferredCanvas.cpp', + 'trunk/src/utils/SkDumpCanvas.cpp', + 'trunk/src/utils/SkEventTracer.cpp', + 'trunk/src/utils/SkFrontBufferedStream.cpp', + 'trunk/src/utils/SkGatherPixelRefsAndRects.cpp', + 'trunk/src/utils/SkInterpolator.cpp', + 'trunk/src/utils/SkLayer.cpp', + 'trunk/src/utils/SkMatrix44.cpp', + 'trunk/src/utils/SkMD5.cpp', + 'trunk/src/utils/SkMeshUtils.cpp', + 'trunk/src/utils/SkNinePatch.cpp', + 'trunk/src/utils/SkNullCanvas.cpp', + 'trunk/src/utils/SkNWayCanvas.cpp', + 'trunk/src/utils/SkOSFile.cpp', + 'trunk/src/utils/SkParse.cpp', + 'trunk/src/utils/SkParseColor.cpp', + 'trunk/src/utils/SkParsePath.cpp', + 'trunk/src/utils/SkPathUtils.cpp', + 'trunk/src/utils/SkPictureUtils.cpp', + 'trunk/src/utils/SkProxyCanvas.cpp', + 'trunk/src/utils/SkRTConf.cpp', + 'trunk/src/utils/SkSHA1.cpp', + 'trunk/src/utils/SkThreadPool.cpp', + 'trunk/src/utils/SkUnitMappers.cpp', ] - # left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. - SOURCES += [ - 'src/ports/SkFontHost_mac.cpp', - ] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': - EXPORTS.skia += [ - 'include/config/sk_stdint.h', - 'include/ports/SkTypeface_win.h', - ] - UNIFIED_SOURCES += [ - 'src/ports/SkThread_win.cpp', - 'src/ports/SkTime_win.cpp', - 'src/utils/SkThreadUtils_win.cpp', - ] - # left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. - SOURCES += [ - 'src/ports/SkFontHost_sandbox_none.cpp', - 'src/ports/SkFontHost_win.cpp', - ] - DEFINES['SKIA_IMPLEMENTATION'] = 1 - DEFINES['GR_IMPLEMENTATION'] = 1 -elif CONFIG['MOZ_WIDGET_GTK']: - EXPORTS.skia += [ - 'include/ports/SkTypeface_cairo.h', - ] - UNIFIED_SOURCES += [ - 'src/ports/SkThread_pthread.cpp', - 'src/ports/SkTime_Unix.cpp', - 'src/utils/SkOSFile.cpp', - 'src/utils/SkThreadUtils_pthread.cpp', - ] - # left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. - SOURCES += [ - 'src/ports/SkFontHost_cairo.cpp', - 'src/ports/SkFontHost_FreeType_common.cpp', - ] - if CONFIG['OS_TARGET'] in ('Linux', 'FreeBSD', 'NetBSD'): - UNIFIED_SOURCES += [ - 'src/utils/SkThreadUtils_pthread_linux.cpp', - ] - else: - UNIFIED_SOURCES += [ - 'src/utils/SkThreadUtils_pthread_other.cpp', - ] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt': - UNIFIED_SOURCES += [ - 'src/utils/SkOSFile.cpp', - ] - # left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. - SOURCES += [ - 'src/ports/SkFontHost_cairo.cpp', - 'src/ports/SkFontHost_FreeType_common.cpp', - ] - if CONFIG['OS_TARGET'] == 'Linux': - EXPORTS.skia += [ - 'include/ports/SkTypeface_cairo.h', - ] - UNIFIED_SOURCES += [ - 'src/ports/SkThread_pthread.cpp', - 'src/ports/SkTime_Unix.cpp', - 'src/utils/SkThreadUtils_pthread.cpp', - 'src/utils/SkThreadUtils_pthread_linux.cpp', - ] - DEFINES['SK_USE_POSIX_THREADS'] = 1 -# Separate 'if' from above, since the else below applies to all != 'android' -# toolkits. if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'): - EXPORTS.skia += [ - 'include/ports/SkTypeface_cairo.h', - ] - UNIFIED_SOURCES += [ - 'src/images/SkImageRef_ashmem.cpp', - 'src/ports/SkDebug_android.cpp', - 'src/ports/SkThread_pthread.cpp', - 'src/ports/SkTime_Unix.cpp', - 'src/utils/android/ashmem.cpp', - 'src/utils/SkOSFile.cpp', - 'src/utils/SkThreadUtils_pthread.cpp', - 'src/utils/SkThreadUtils_pthread_other.cpp', - ] - # left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. SOURCES += [ - 'src/ports/SkFontHost_android_old.cpp', - 'src/ports/SkFontHost_cairo.cpp', - 'src/ports/SkFontHost_FreeType.cpp', - 'src/ports/SkFontHost_FreeType_common.cpp', + 'trunk/src/images/SkImageRef_ashmem.cpp', + 'trunk/src/ports/SkDebug_android.cpp', + 'trunk/src/ports/SkFontHost_android_old.cpp', + 'trunk/src/ports/SkFontHost_cairo.cpp', + 'trunk/src/ports/SkFontHost_FreeType.cpp', + 'trunk/src/ports/SkFontHost_FreeType_common.cpp', + 'trunk/src/ports/SkOSFile_posix.cpp', + 'trunk/src/ports/SkPurgeableMemoryBlock_android.cpp', + 'trunk/src/ports/SkTime_Unix.cpp', + 'trunk/src/ports/SkTLS_pthread.cpp', + 'trunk/src/utils/android/ashmem.cpp', + 'trunk/src/utils/SkThreadUtils_pthread.cpp', + 'trunk/src/utils/SkThreadUtils_pthread_other.cpp', ] DEFINES['SK_FONTHOST_CAIRO_STANDALONE'] = 0 -else: - UNIFIED_SOURCES += [ - 'src/ports/SkDebug_stdio.cpp', - ] - -if CONFIG['INTEL_ARCHITECTURE']: - # We need to build SSE2-enabled files separately so that we're able - # to pass -msse2 for them. We won't be able to unify them with the rest, - # but we should at least be able to unify them with each other. +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': SOURCES += [ - 'src/opts/opts_check_SSE2.cpp', - 'src/opts/SkBitmapProcState_opts_SSE2.cpp', - 'src/opts/SkBlitRect_opts_SSE2.cpp', - 'src/opts/SkBlitRow_opts_SSE2.cpp', - 'src/opts/SkUtils_opts_SSE2.cpp', - ] - if CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']: - SOURCES += [ - 'src/opts/SkBitmapProcState_opts_SSSE3.cpp', - ] -elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: - UNIFIED_SOURCES += [ - 'src/opts/opts_check_arm.cpp', - 'src/opts/SkBlitRow_opts_arm.cpp', - ] - SOURCES += [ - 'src/opts/SkBitmapProcState_opts_arm.cpp', - ] -else: - UNIFIED_SOURCES += [ - 'src/opts/SkBlitRow_opts_none.cpp', - 'src/opts/SkUtils_opts_none.cpp', + 'trunk/src/ports/SkDebug_stdio.cpp', + 'trunk/src/ports/SkFontHost_mac.cpp', + 'trunk/src/ports/SkOSFile_posix.cpp', + 'trunk/src/ports/SkPurgeableMemoryBlock_mac.cpp', + 'trunk/src/ports/SkTime_Unix.cpp', + 'trunk/src/ports/SkTLS_pthread.cpp', + 'trunk/src/utils/mac/SkCreateCGImageRef.cpp', + 'trunk/src/utils/mac/SkStream_mac.cpp', + 'trunk/src/utils/SkThreadUtils_pthread.cpp', + 'trunk/src/utils/SkThreadUtils_pthread_mach.cpp', ] +if CONFIG['MOZ_WIDGET_GTK']: SOURCES += [ - 'src/opts/SkBitmapProcState_opts_none.cpp', + 'trunk/src/ports/SkDebug_stdio.cpp', + 'trunk/src/ports/SkFontHost_cairo.cpp', + 'trunk/src/ports/SkFontHost_FreeType.cpp', + 'trunk/src/ports/SkFontHost_FreeType_common.cpp', + 'trunk/src/ports/SkOSFile_posix.cpp', + 'trunk/src/ports/SkTime_Unix.cpp', + 'trunk/src/ports/SkTLS_pthread.cpp', + 'trunk/src/utils/SkThreadUtils_pthread.cpp', + 'trunk/src/utils/SkThreadUtils_pthread_linux.cpp', ] - -if CONFIG['MOZ_ENABLE_SKIA_GPU']: - UNIFIED_SOURCES += [ - 'src/gpu/effects/GrConfigConversionEffect.cpp', - 'src/gpu/effects/GrConvolutionEffect.cpp', - 'src/gpu/effects/GrSimpleTextureEffect.cpp', - 'src/gpu/effects/GrSingleTextureEffect.cpp', - 'src/gpu/effects/GrTextureDomainEffect.cpp', - 'src/gpu/effects/GrTextureStripAtlas.cpp', - 'src/gpu/gl/GrGLBufferImpl.cpp', - 'src/gpu/gl/GrGLCaps.cpp', - 'src/gpu/gl/GrGLContext.cpp', - 'src/gpu/gl/GrGLCreateNativeInterface_none.cpp', - 'src/gpu/gl/GrGLCreateNullInterface.cpp', - 'src/gpu/gl/GrGLDefaultInterface_native.cpp', - 'src/gpu/gl/GrGLEffect.cpp', - 'src/gpu/gl/GrGLEffectMatrix.cpp', - 'src/gpu/gl/GrGLExtensions.cpp', - 'src/gpu/gl/GrGLIndexBuffer.cpp', - 'src/gpu/gl/GrGLInterface.cpp', - 'src/gpu/gl/GrGLNoOpInterface.cpp', - 'src/gpu/gl/GrGLPath.cpp', - 'src/gpu/gl/GrGLProgram.cpp', - 'src/gpu/gl/GrGLProgramDesc.cpp', - 'src/gpu/gl/GrGLRenderTarget.cpp', - 'src/gpu/gl/GrGLShaderBuilder.cpp', - 'src/gpu/gl/GrGLSL.cpp', - 'src/gpu/gl/GrGLStencilBuffer.cpp', - 'src/gpu/gl/GrGLTexture.cpp', - 'src/gpu/gl/GrGLUniformManager.cpp', - 'src/gpu/gl/GrGLUtil.cpp', - 'src/gpu/gl/GrGLVertexArray.cpp', - 'src/gpu/gl/GrGLVertexBuffer.cpp', - 'src/gpu/gl/GrGpuGL.cpp', - 'src/gpu/gl/GrGpuGL_program.cpp', - 'src/gpu/gl/SkGLContextHelper.cpp', - 'src/gpu/gl/SkNullGLContext.cpp', - 'src/gpu/GrAAConvexPathRenderer.cpp', - 'src/gpu/GrAAHairLinePathRenderer.cpp', - 'src/gpu/GrAARectRenderer.cpp', - 'src/gpu/GrAddPathRenderers_default.cpp', - 'src/gpu/GrAllocPool.cpp', - 'src/gpu/GrAtlas.cpp', - 'src/gpu/GrBufferAllocPool.cpp', - 'src/gpu/GrCacheID.cpp', - 'src/gpu/GrClipData.cpp', - 'src/gpu/GrClipMaskCache.cpp', - 'src/gpu/GrClipMaskManager.cpp', - 'src/gpu/GrContext.cpp', - 'src/gpu/GrDefaultPathRenderer.cpp', - 'src/gpu/GrDrawState.cpp', - 'src/gpu/GrDrawTarget.cpp', - 'src/gpu/GrEffect.cpp', - 'src/gpu/GrGeometryBuffer.cpp', - 'src/gpu/GrGpu.cpp', - 'src/gpu/GrGpuFactory.cpp', - 'src/gpu/GrInOrderDrawBuffer.cpp', - 'src/gpu/GrMemory.cpp', - 'src/gpu/GrMemoryPool.cpp', - 'src/gpu/GrOvalRenderer.cpp', - 'src/gpu/GrPath.cpp', - 'src/gpu/GrPathRenderer.cpp', - 'src/gpu/GrPathRendererChain.cpp', - 'src/gpu/GrPathUtils.cpp', - 'src/gpu/GrRectanizer.cpp', - 'src/gpu/GrReducedClip.cpp', - 'src/gpu/GrRenderTarget.cpp', - 'src/gpu/GrResource.cpp', - 'src/gpu/GrResourceCache.cpp', - 'src/gpu/GrSoftwarePathRenderer.cpp', - 'src/gpu/GrStencil.cpp', - 'src/gpu/GrStencilAndCoverPathRenderer.cpp', - 'src/gpu/GrStencilBuffer.cpp', - 'src/gpu/GrSurface.cpp', - 'src/gpu/GrSWMaskHelper.cpp', - 'src/gpu/GrTextContext.cpp', - 'src/gpu/GrTextStrike.cpp', - 'src/gpu/GrTexture.cpp', - 'src/gpu/GrTextureAccess.cpp', - 'src/gpu/SkGpuDevice.cpp', - 'src/gpu/SkGr.cpp', - 'src/gpu/SkGrFontScaler.cpp', - 'src/gpu/SkGrPixelRef.cpp', - 'src/gpu/SkGrTexturePixelRef.cpp', - ] - -UNIFIED_SOURCES += [ - 'src/core/Sk64.cpp', - 'src/core/SkAAClip.cpp', - 'src/core/SkAdvancedTypefaceMetrics.cpp', - 'src/core/SkAlphaRuns.cpp', - 'src/core/SkAnnotation.cpp', - 'src/core/SkBBoxHierarchy.cpp', - 'src/core/SkBBoxHierarchyRecord.cpp', - 'src/core/SkBBoxRecord.cpp', - 'src/core/SkBitmap.cpp', - 'src/core/SkBitmap_scroll.cpp', - 'src/core/SkBitmapHeap.cpp', - 'src/core/SkBitmapProcShader.cpp', - 'src/core/SkBitmapProcState.cpp', - 'src/core/SkBitmapSampler.cpp', - 'src/core/SkBlitMask_D32.cpp', - 'src/core/SkBlitRow_D16.cpp', - 'src/core/SkBlitRow_D32.cpp', - 'src/core/SkBlitRow_D4444.cpp', - 'src/core/SkBlitter.cpp', - 'src/core/SkBuffer.cpp', - 'src/core/SkCanvas.cpp', - 'src/core/SkChunkAlloc.cpp', - 'src/core/SkClipStack.cpp', - 'src/core/SkColor.cpp', - 'src/core/SkColorFilter.cpp', - 'src/core/SkColorTable.cpp', - 'src/core/SkComposeShader.cpp', - 'src/core/SkConfig8888.cpp', - 'src/core/SkCordic.cpp', - 'src/core/SkCubicClipper.cpp', - 'src/core/SkData.cpp', - 'src/core/SkDebug.cpp', - 'src/core/SkDeque.cpp', - 'src/core/SkDevice.cpp', - 'src/core/SkDeviceProfile.cpp', - 'src/core/SkDither.cpp', - 'src/core/SkDraw.cpp', - 'src/core/SkEdge.cpp', - 'src/core/SkEdgeBuilder.cpp', - 'src/core/SkEdgeClipper.cpp', - 'src/core/SkFilterProc.cpp', - 'src/core/SkFlattenable.cpp', - 'src/core/SkFlattenableBuffers.cpp', - 'src/core/SkFloat.cpp', - 'src/core/SkFloatBits.cpp', - 'src/core/SkFontDescriptor.cpp', - 'src/core/SkFontHost.cpp', - 'src/core/SkFontStream.cpp', - 'src/core/SkGeometry.cpp', - 'src/core/SkGlyphCache.cpp', - 'src/core/SkGraphics.cpp', - 'src/core/SkImageFilter.cpp', - 'src/core/SkInstCnt.cpp', - 'src/core/SkLineClipper.cpp', - 'src/core/SkMallocPixelRef.cpp', - 'src/core/SkMask.cpp', - 'src/core/SkMaskFilter.cpp', - 'src/core/SkMaskGamma.cpp', - 'src/core/SkMath.cpp', - 'src/core/SkMatrix.cpp', - 'src/core/SkMetaData.cpp', - 'src/core/SkOrderedReadBuffer.cpp', - 'src/core/SkOrderedWriteBuffer.cpp', - 'src/core/SkPackBits.cpp', - 'src/core/SkPaint.cpp', - 'src/core/SkPaintPriv.cpp', - 'src/core/SkPath.cpp', - 'src/core/SkPathEffect.cpp', - 'src/core/SkPathHeap.cpp', - 'src/core/SkPathMeasure.cpp', - 'src/core/SkPicture.cpp', - 'src/core/SkPictureFlat.cpp', - 'src/core/SkPicturePlayback.cpp', - 'src/core/SkPictureRecord.cpp', - 'src/core/SkPictureStateTree.cpp', - 'src/core/SkPixelRef.cpp', - 'src/core/SkPoint.cpp', - 'src/core/SkProcSpriteBlitter.cpp', - 'src/core/SkPtrRecorder.cpp', - 'src/core/SkQuadClipper.cpp', - 'src/core/SkRasterClip.cpp', - 'src/core/SkRasterizer.cpp', - 'src/core/SkRect.cpp', - 'src/core/SkRefCnt.cpp', - 'src/core/SkRefDict.cpp', - 'src/core/SkRegion.cpp', - 'src/core/SkRegion_path.cpp', - 'src/core/SkRegion_rects.cpp', - 'src/core/SkRRect.cpp', - 'src/core/SkRTree.cpp', - 'src/core/SkScalar.cpp', - 'src/core/SkScalerContext.cpp', - 'src/core/SkScan.cpp', - 'src/core/SkShader.cpp', - 'src/core/SkSpriteBlitter_ARGB32.cpp', - 'src/core/SkSpriteBlitter_RGB16.cpp', - 'src/core/SkStream.cpp', - 'src/core/SkString.cpp', - 'src/core/SkStroke.cpp', - 'src/core/SkStrokeRec.cpp', - 'src/core/SkStrokerPriv.cpp', - 'src/core/SkTileGrid.cpp', - 'src/core/SkTileGridPicture.cpp', - 'src/core/SkTLS.cpp', - 'src/core/SkTSearch.cpp', - 'src/core/SkTypeface.cpp', - 'src/core/SkTypefaceCache.cpp', - 'src/core/SkUnPreMultiply.cpp', - 'src/core/SkUtils.cpp', - 'src/core/SkWriter32.cpp', - 'src/core/SkXfermode.cpp', - 'src/effects/gradients/SkBitmapCache.cpp', - 'src/effects/gradients/SkClampRange.cpp', - 'src/effects/gradients/SkGradientShader.cpp', - 'src/effects/gradients/SkGradientTileProc.cpp', - 'src/effects/gradients/SkLinearGradient.cpp', - 'src/effects/gradients/SkRadialGradient.cpp', - 'src/effects/gradients/SkSweepGradient.cpp', - 'src/effects/Sk1DPathEffect.cpp', - 'src/effects/Sk2DPathEffect.cpp', - 'src/effects/SkAvoidXfermode.cpp', - 'src/effects/SkBicubicImageFilter.cpp', - 'src/effects/SkBitmapSource.cpp', - 'src/effects/SkBlendImageFilter.cpp', - 'src/effects/SkBlurDrawLooper.cpp', - 'src/effects/SkBlurImageFilter.cpp', - 'src/effects/SkBlurMask.cpp', - 'src/effects/SkBlurMaskFilter.cpp', - 'src/effects/SkColorFilterImageFilter.cpp', - 'src/effects/SkColorFilters.cpp', - 'src/effects/SkColorMatrix.cpp', - 'src/effects/SkColorMatrixFilter.cpp', - 'src/effects/SkCornerPathEffect.cpp', - 'src/effects/SkDashPathEffect.cpp', - 'src/effects/SkDiscretePathEffect.cpp', - 'src/effects/SkDisplacementMapEffect.cpp', - 'src/effects/SkEmbossMask.cpp', - 'src/effects/SkEmbossMaskFilter.cpp', - 'src/effects/SkImageFilterUtils.cpp', - 'src/effects/SkLayerDrawLooper.cpp', - 'src/effects/SkLayerRasterizer.cpp', - 'src/effects/SkLightingImageFilter.cpp', - 'src/effects/SkMagnifierImageFilter.cpp', - 'src/effects/SkMatrixConvolutionImageFilter.cpp', - 'src/effects/SkMergeImageFilter.cpp', - 'src/effects/SkMorphologyImageFilter.cpp', - 'src/effects/SkOffsetImageFilter.cpp', - 'src/effects/SkPixelXorXfermode.cpp', - 'src/effects/SkStippleMaskFilter.cpp', - 'src/effects/SkTableColorFilter.cpp', - 'src/effects/SkTableMaskFilter.cpp', - 'src/effects/SkTestImageFilters.cpp', - 'src/image/SkDataPixelRef.cpp', - 'src/image/SkImage.cpp', - 'src/image/SkImage_Codec.cpp', - 'src/image/SkImage_Picture.cpp', - 'src/image/SkImage_Raster.cpp', - 'src/image/SkImagePriv.cpp', - 'src/image/SkSurface.cpp', - 'src/image/SkSurface_Picture.cpp', - 'src/image/SkSurface_Raster.cpp', - 'src/images/SkImageDecoder.cpp', - 'src/images/SkImageDecoder_Factory.cpp', - 'src/images/SkImageRef.cpp', - 'src/images/SkImageRef_GlobalPool.cpp', - 'src/images/SkImageRefPool.cpp', - 'src/images/SkImages.cpp', - 'src/lazy/SkBitmapFactory.cpp', - 'src/lazy/SkLazyPixelRef.cpp', - 'src/pipe/SkGPipeRead.cpp', - 'src/pipe/SkGPipeWrite.cpp', - 'src/ports/SkGlobalInitialization_default.cpp', - 'src/ports/SkMemory_malloc.cpp', - 'src/ports/SkOSFile_stdio.cpp', - 'src/sfnt/SkOTUtils.cpp', - 'src/utils/SkBase64.cpp', - 'src/utils/SkBitmapTransformer.cpp', - 'src/utils/SkBitSet.cpp', - 'src/utils/SkCountdown.cpp', - 'src/utils/SkDeferredCanvas.cpp', - 'src/utils/SkPictureUtils.cpp', - 'src/utils/SkRTConf.cpp', - 'src/utils/SkThreadPool.cpp', -] - -# left out of UNIFIED_SOURCES for now to avoid having to patch skia. Should revisit eventually. -SOURCES += [ - 'src/core/SkBitmapProcState_matrixProcs.cpp', - 'src/core/SkBlitter_4444.cpp', - 'src/core/SkBlitter_A1.cpp', - 'src/core/SkBlitter_A8.cpp', - 'src/core/SkBlitter_ARGB32.cpp', - 'src/core/SkBlitter_RGB16.cpp', - 'src/core/SkBlitter_Sprite.cpp', - 'src/core/SkScan_Antihair.cpp', - 'src/core/SkScan_AntiPath.cpp', - 'src/core/SkScan_Hairline.cpp', - 'src/core/SkScan_Path.cpp', - 'src/effects/gradients/SkTwoPointConicalGradient.cpp', - 'src/effects/gradients/SkTwoPointRadialGradient.cpp', -] - -# On Windows, SkCondVar needs to be built separately because it relies on -# windows.h providing such functions as InitializeConditionVariable. if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': SOURCES += [ - 'src/utils/SkCondVar.cpp', + 'trunk/src/ports/SkDebug_win.cpp', + 'trunk/src/ports/SkFontHost_win.cpp', + 'trunk/src/ports/SkFontMgr_default_gdi.cpp', + 'trunk/src/ports/SkOSFile_win.cpp', + 'trunk/src/ports/SkTime_win.cpp', + 'trunk/src/ports/SkTLS_win.cpp', + 'trunk/src/utils/SkThreadUtils_win.cpp', + 'trunk/src/utils/win/SkAutoCoInitialize.cpp', + 'trunk/src/utils/win/SkDWriteFontFileStream.cpp', + 'trunk/src/utils/win/SkDWriteGeometrySink.cpp', + 'trunk/src/utils/win/SkHRESULT.cpp', + 'trunk/src/utils/win/SkIStream.cpp', + ] + + +if CONFIG['INTEL_ARCHITECTURE']: + SOURCES += [ + 'trunk/src/opts/opts_check_SSE2.cpp', + 'trunk/src/opts/SkBitmapFilter_opts_SSE2.cpp', + 'trunk/src/opts/SkBitmapProcState_opts_SSE2.cpp', + 'trunk/src/opts/SkBitmapProcState_opts_SSSE3.cpp', + 'trunk/src/opts/SkBlitRect_opts_SSE2.cpp', + 'trunk/src/opts/SkBlitRow_opts_SSE2.cpp', + 'trunk/src/opts/SkBlurImage_opts_SSE2.cpp', + 'trunk/src/opts/SkMorphology_opts_SSE2.cpp', + 'trunk/src/opts/SkUtils_opts_SSE2.cpp', + 'trunk/src/opts/SkXfermode_opts_none.cpp', + ] +elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: + SOURCES += [ + 'trunk/src/opts/SkBitmapProcState_opts_arm.cpp', + 'trunk/src/opts/SkBlitMask_opts_arm.cpp', + 'trunk/src/opts/SkBlitRow_opts_arm.cpp', + 'trunk/src/opts/SkBlurImage_opts_arm.cpp', + 'trunk/src/opts/SkMorphology_opts_arm.cpp', + 'trunk/src/opts/SkUtils_opts_arm.cpp', + 'trunk/src/opts/SkXfermode_opts_arm.cpp', ] else: - UNIFIED_SOURCES += [ - 'src/utils/SkCondVar.cpp', + SOURCES += [ + 'trunk/src/opts/SkBitmapProcState_opts_none.cpp', + 'trunk/src/opts/SkBlitMask_opts_none.cpp', + 'trunk/src/opts/SkBlitRow_opts_none.cpp', + 'trunk/src/opts/SkBlurImage_opts_none.cpp', + 'trunk/src/opts/SkMorphology_opts_none.cpp', + 'trunk/src/opts/SkUtils_opts_none.cpp', + 'trunk/src/opts/SkXfermode_opts_none.cpp', + 'trunk/src/ports/SkDiscardableMemory_none.cpp', + 'trunk/src/ports/SkPurgeableMemoryBlock_none.cpp', ] # left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']: SOURCES += [ - 'src/opts/memset.arm.S', + 'trunk/src/opts/memset.arm.S', ] MSVC_ENABLE_PGO = True FINAL_LIBRARY = 'gkmedias' LOCAL_INCLUDES += [ - 'include/config', - 'include/core', - 'include/effects', - 'include/gpu', - 'include/images', - 'include/lazy', - 'include/pipe', - 'include/ports', - 'include/utils', - 'include/utils/mac', - 'include/utils/win', - 'include/views', - 'src/core', - 'src/gpu', - 'src/gpu/effects', - 'src/gpu/gl', - 'src/image', - 'src/lazy', - 'src/sfnt', - 'src/utils', - 'src/utils/android', + 'trunk/include/config', + 'trunk/include/core', + 'trunk/include/effects', + 'trunk/include/gpu', + 'trunk/include/images', + 'trunk/include/lazy', + 'trunk/include/pathops', + 'trunk/include/pipe', + 'trunk/include/ports', + 'trunk/include/utils', + 'trunk/include/utils/mac', + 'trunk/include/utils/win', + 'trunk/include/views', + 'trunk/src/core', + 'trunk/src/gpu', + 'trunk/src/gpu/effects', + 'trunk/src/gpu/gl', + 'trunk/src/image', + 'trunk/src/lazy', + 'trunk/src/opts', + 'trunk/src/sfnt', + 'trunk/src/utils', + 'trunk/src/utils/android', + 'trunk/src/utils/mac', + 'trunk/src/utils/win', ] - DEFINES['SK_A32_SHIFT'] = 24 DEFINES['SK_R32_SHIFT'] = 16 DEFINES['SK_G32_SHIFT'] = 8 @@ -625,3 +836,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'cocoa'): if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']: DEFINES['SK_BUILD_SSSE3'] = 1 + +if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk') or (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or CONFIG['MOZ_WIDGET_GTK']: + DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1 + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + DEFINES['SKIA_DLL'] = 1 + +DEFINES['SKIA_IMPLEMENTATION'] = 1 +DEFINES['GR_IMPLEMENTATION'] = 1 diff --git a/gfx/skia/src/core/SkAlphaRuns.cpp b/gfx/skia/src/core/SkAlphaRuns.cpp deleted file mode 100644 index 1b0415814f6f..000000000000 --- a/gfx/skia/src/core/SkAlphaRuns.cpp +++ /dev/null @@ -1,178 +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 "SkAntiRun.h" -#include "SkUtils.h" - -void SkAlphaRuns::reset(int width) { - SkASSERT(width > 0); - -#ifdef SK_DEBUG - sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width); -#endif - fRuns[0] = SkToS16(width); - fRuns[width] = 0; - fAlpha[0] = 0; - - SkDEBUGCODE(fWidth = width;) - SkDEBUGCODE(this->validate();) -} - -void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) { - SkASSERT(count > 0 && x >= 0); - -// SkAlphaRuns::BreakAt(runs, alpha, x); -// SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count); - - int16_t* next_runs = runs + x; - uint8_t* next_alpha = alpha + x; - - while (x > 0) { - int n = runs[0]; - SkASSERT(n > 0); - - if (x < n) { - alpha[x] = alpha[0]; - runs[0] = SkToS16(x); - runs[x] = SkToS16(n - x); - break; - } - runs += n; - alpha += n; - x -= n; - } - - runs = next_runs; - alpha = next_alpha; - x = count; - - for (;;) { - int n = runs[0]; - SkASSERT(n > 0); - - if (x < n) { - alpha[x] = alpha[0]; - runs[0] = SkToS16(x); - runs[x] = SkToS16(n - x); - break; - } - x -= n; - if (x <= 0) { - break; - } - runs += n; - alpha += n; - } -} - -int SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, - U8CPU maxValue, int offsetX) { - SkASSERT(middleCount >= 0); - SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); - - SkASSERT(fRuns[offsetX] >= 0); - - int16_t* runs = fRuns + offsetX; - uint8_t* alpha = fAlpha + offsetX; - uint8_t* lastAlpha = alpha; - x -= offsetX; - - if (startAlpha) { - SkAlphaRuns::Break(runs, alpha, x, 1); - /* I should be able to just add alpha[x] + startAlpha. - However, if the trailing edge of the previous span and the leading - edge of the current span round to the same super-sampled x value, - I might overflow to 256 with this add, hence the funny subtract (crud). - */ - unsigned tmp = alpha[x] + startAlpha; - SkASSERT(tmp <= 256); - alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256 - - runs += x + 1; - alpha += x + 1; - x = 0; - lastAlpha += x; // we don't want the +1 - SkDEBUGCODE(this->validate();) - } - - if (middleCount) { - SkAlphaRuns::Break(runs, alpha, x, middleCount); - alpha += x; - runs += x; - x = 0; - do { - alpha[0] = SkToU8(alpha[0] + maxValue); - int n = runs[0]; - SkASSERT(n <= middleCount); - alpha += n; - runs += n; - middleCount -= n; - } while (middleCount > 0); - SkDEBUGCODE(this->validate();) - lastAlpha = alpha; - } - - if (stopAlpha) { - SkAlphaRuns::Break(runs, alpha, x, 1); - alpha += x; - alpha[0] = SkToU8(alpha[0] + stopAlpha); - SkDEBUGCODE(this->validate();) - lastAlpha = alpha; - } - - return SkToS32(lastAlpha - fAlpha); // new offsetX -} - -#ifdef SK_DEBUG - void SkAlphaRuns::assertValid(int y, int maxStep) const { - int max = (y + 1) * maxStep - (y == maxStep - 1); - - const int16_t* runs = fRuns; - const uint8_t* alpha = fAlpha; - - while (*runs) { - SkASSERT(*alpha <= max); - alpha += *runs; - runs += *runs; - } - } - - void SkAlphaRuns::dump() const { - const int16_t* runs = fRuns; - const uint8_t* alpha = fAlpha; - - SkDebugf("Runs"); - while (*runs) { - int n = *runs; - - SkDebugf(" %02x", *alpha); - if (n > 1) { - SkDebugf(",%d", n); - } - alpha += n; - runs += n; - } - SkDebugf("\n"); - } - - void SkAlphaRuns::validate() const { - SkASSERT(fWidth > 0); - - int count = 0; - const int16_t* runs = fRuns; - - while (*runs) { - SkASSERT(*runs > 0); - count += *runs; - SkASSERT(count <= fWidth); - runs += *runs; - } - SkASSERT(count == fWidth); - } -#endif diff --git a/gfx/skia/src/core/SkAntiRun.h b/gfx/skia/src/core/SkAntiRun.h deleted file mode 100644 index 123972692eb6..000000000000 --- a/gfx/skia/src/core/SkAntiRun.h +++ /dev/null @@ -1,92 +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 SkAntiRun_DEFINED -#define SkAntiRun_DEFINED - -#include "SkBlitter.h" - -/** Sparse array of run-length-encoded alpha (supersampling coverage) values. - Sparseness allows us to independently compose several paths into the - same SkAlphaRuns buffer. -*/ - -class SkAlphaRuns { -public: - int16_t* fRuns; - uint8_t* fAlpha; - - /// Returns true if the scanline contains only a single run, - /// of alpha value 0. - bool empty() const { - SkASSERT(fRuns[0] > 0); - return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0; - } - - /// Reinitialize for a new scanline. - void reset(int width); - - /** - * Insert into the buffer a run starting at (x-offsetX): - * if startAlpha > 0 - * one pixel with value += startAlpha, - * max 255 - * if middleCount > 0 - * middleCount pixels with value += maxValue - * if stopAlpha > 0 - * one pixel with value += stopAlpha - * Returns the offsetX value that should be passed on the next call, - * assuming we're on the same scanline. If the caller is switching - * scanlines, then offsetX should be 0 when this is called. - */ - int add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, - U8CPU maxValue, int offsetX); - - SkDEBUGCODE(void assertValid(int y, int maxStep) const;) - SkDEBUGCODE(void dump() const;) - - /** - * Break the runs in the buffer at offsets x and x+count, properly - * updating the runs to the right and left. - * i.e. from the state AAAABBBB, run-length encoded as A4B4, - * Break(..., 2, 5) would produce AAAABBBB rle as A2A2B3B1. - * Allows add() to sum another run to some of the new sub-runs. - * i.e. adding ..CCCCC. would produce AADDEEEB, rle as A2D2E3B1. - */ - static void Break(int16_t runs[], uint8_t alpha[], int x, int count); - - /** - * Cut (at offset x in the buffer) a run into two shorter runs with - * matching alpha values. - * Used by the RectClipBlitter to trim a RLE encoding to match the - * clipping rectangle. - */ - static void BreakAt(int16_t runs[], uint8_t alpha[], int x) { - while (x > 0) { - int n = runs[0]; - SkASSERT(n > 0); - - if (x < n) { - alpha[x] = alpha[0]; - runs[0] = SkToS16(x); - runs[x] = SkToS16(n - x); - break; - } - runs += n; - alpha += n; - x -= n; - } - } - -private: - SkDEBUGCODE(int fWidth;) - SkDEBUGCODE(void validate() const;) -}; - -#endif diff --git a/gfx/skia/src/core/SkBBoxHierarchy.cpp b/gfx/skia/src/core/SkBBoxHierarchy.cpp deleted file mode 100644 index 5232fb7c1815..000000000000 --- a/gfx/skia/src/core/SkBBoxHierarchy.cpp +++ /dev/null @@ -1,11 +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 "SkBBoxHierarchy.h" - -SK_DEFINE_INST_COUNT(SkBBoxHierarchy) diff --git a/gfx/skia/src/core/SkBitmapProcState.cpp b/gfx/skia/src/core/SkBitmapProcState.cpp deleted file mode 100644 index e44237880f77..000000000000 --- a/gfx/skia/src/core/SkBitmapProcState.cpp +++ /dev/null @@ -1,720 +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 "SkBitmapProcState.h" -#include "SkColorPriv.h" -#include "SkFilterProc.h" -#include "SkPaint.h" -#include "SkShader.h" // for tilemodes -#include "SkUtilsArm.h" - -#if !SK_ARM_NEON_IS_NONE -// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp -extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; -extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; -extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); -extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); -extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); -extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); -extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); -extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); -#endif - -#define NAME_WRAP(x) x -#include "SkBitmapProcState_filter.h" -#include "SkBitmapProcState_procs.h" - -/////////////////////////////////////////////////////////////////////////////// - -/** - * For the purposes of drawing bitmaps, if a matrix is "almost" translate - * go ahead and treat it as if it were, so that subsequent code can go fast. - */ -static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { - SkMatrix::TypeMask mask = matrix.getType(); - - if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { - return false; - } - if (mask & SkMatrix::kScale_Mask) { - SkScalar sx = matrix[SkMatrix::kMScaleX]; - SkScalar sy = matrix[SkMatrix::kMScaleY]; - int w = bitmap.width(); - int h = bitmap.height(); - int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w))); - int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h))); - return sw == w && sh == h; - } - // if we got here, we're either kTranslate_Mask or identity - return true; -} - -static bool just_trans_general(const SkMatrix& matrix) { - SkMatrix::TypeMask mask = matrix.getType(); - - if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { - return false; - } - if (mask & SkMatrix::kScale_Mask) { - const SkScalar tol = SK_Scalar1 / 32768; - - if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { - return false; - } - if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { - return false; - } - } - // if we got here, treat us as either kTranslate_Mask or identity - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -static bool valid_for_filtering(unsigned dimension) { - // for filtering, width and height must fit in 14bits, since we use steal - // 2 bits from each to store our 4bit subpixel data - return (dimension & ~0x3FFF) == 0; -} - -bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { - if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) { - return false; - } - - const SkMatrix* m; - bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0; - bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX && - SkShader::kClamp_TileMode == fTileModeY; - - if (clamp_clamp || trivial_matrix) { - m = &inv; - } else { - fUnitInvMatrix = inv; - fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); - m = &fUnitInvMatrix; - } - - fBitmap = &fOrigBitmap; - if (fOrigBitmap.hasMipMap()) { - int shift = fOrigBitmap.extractMipLevel(&fMipBitmap, - SkScalarToFixed(m->getScaleX()), - SkScalarToFixed(m->getSkewY())); - - if (shift > 0) { - if (m != &fUnitInvMatrix) { - fUnitInvMatrix = *m; - m = &fUnitInvMatrix; - } - - SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); - fUnitInvMatrix.postScale(scale, scale); - - // now point here instead of fOrigBitmap - fBitmap = &fMipBitmap; - } - } - - // wack our matrix to exactly no-scale, if we're really close to begin with - { - bool fixupMatrix = clamp_clamp ? - just_trans_clamp(*m, *fBitmap) : just_trans_general(*m); - if (fixupMatrix) { - // If we can be treated just like translate, construct that inverse - // such that we landed in the proper place. Given that m may have - // some slight scale, we have to invert it to compute this new - // matrix. - SkMatrix forward; - if (m->invert(&forward)) { - SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); - SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); - fUnitInvMatrix.setTranslate(tx, ty); - m = &fUnitInvMatrix; - // now the following code will sniff m, and decide to take the - // fast case (since m is purely translate). - } - } - } - - // Below this point, we should never refer to the inv parameter, since we - // may be using a munged version for "our" inverse. - - fInvMatrix = m; - fInvProc = m->getMapXYProc(); - fInvType = m->getType(); - fInvSx = SkScalarToFixed(m->getScaleX()); - fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX()); - fInvKy = SkScalarToFixed(m->getSkewY()); - fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY()); - - fAlphaScale = SkAlpha255To256(paint.getAlpha()); - - // pick-up filtering from the paint, but only if the matrix is - // more complex than identity/translate (i.e. no need to pay the cost - // of filtering if we're not scaled etc.). - // note: we explicitly check inv, since m might be scaled due to unitinv - // trickery, but we don't want to see that for this test - fDoFilter = paint.isFilterBitmap() && - (fInvType > SkMatrix::kTranslate_Mask && - valid_for_filtering(fBitmap->width() | fBitmap->height())); - - fShaderProc32 = NULL; - fShaderProc16 = NULL; - fSampleProc32 = NULL; - fSampleProc16 = NULL; - - fMatrixProc = this->chooseMatrixProc(trivial_matrix); - if (NULL == fMatrixProc) { - return false; - } - - /////////////////////////////////////////////////////////////////////// - - int index = 0; - if (fAlphaScale < 256) { // note: this distinction is not used for D16 - index |= 1; - } - if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { - index |= 2; - } - if (fDoFilter) { - index |= 4; - } - // bits 3,4,5 encoding the source bitmap format - switch (fBitmap->config()) { - case SkBitmap::kARGB_8888_Config: - index |= 0; - break; - case SkBitmap::kRGB_565_Config: - index |= 8; - break; - case SkBitmap::kIndex8_Config: - index |= 16; - break; - case SkBitmap::kARGB_4444_Config: - index |= 24; - break; - case SkBitmap::kA8_Config: - index |= 32; - fPaintPMColor = SkPreMultiplyColor(paint.getColor()); - break; - default: - return false; - } - -#if !SK_ARM_NEON_IS_ALWAYS - static const SampleProc32 gSkBitmapProcStateSample32[] = { - S32_opaque_D32_nofilter_DXDY, - S32_alpha_D32_nofilter_DXDY, - S32_opaque_D32_nofilter_DX, - S32_alpha_D32_nofilter_DX, - S32_opaque_D32_filter_DXDY, - S32_alpha_D32_filter_DXDY, - S32_opaque_D32_filter_DX, - S32_alpha_D32_filter_DX, - - S16_opaque_D32_nofilter_DXDY, - S16_alpha_D32_nofilter_DXDY, - S16_opaque_D32_nofilter_DX, - S16_alpha_D32_nofilter_DX, - S16_opaque_D32_filter_DXDY, - S16_alpha_D32_filter_DXDY, - S16_opaque_D32_filter_DX, - S16_alpha_D32_filter_DX, - - SI8_opaque_D32_nofilter_DXDY, - SI8_alpha_D32_nofilter_DXDY, - SI8_opaque_D32_nofilter_DX, - SI8_alpha_D32_nofilter_DX, - SI8_opaque_D32_filter_DXDY, - SI8_alpha_D32_filter_DXDY, - SI8_opaque_D32_filter_DX, - SI8_alpha_D32_filter_DX, - - S4444_opaque_D32_nofilter_DXDY, - S4444_alpha_D32_nofilter_DXDY, - S4444_opaque_D32_nofilter_DX, - S4444_alpha_D32_nofilter_DX, - S4444_opaque_D32_filter_DXDY, - S4444_alpha_D32_filter_DXDY, - S4444_opaque_D32_filter_DX, - S4444_alpha_D32_filter_DX, - - // A8 treats alpha/opaque the same (equally efficient) - SA8_alpha_D32_nofilter_DXDY, - SA8_alpha_D32_nofilter_DXDY, - SA8_alpha_D32_nofilter_DX, - SA8_alpha_D32_nofilter_DX, - SA8_alpha_D32_filter_DXDY, - SA8_alpha_D32_filter_DXDY, - SA8_alpha_D32_filter_DX, - SA8_alpha_D32_filter_DX - }; - - static const SampleProc16 gSkBitmapProcStateSample16[] = { - S32_D16_nofilter_DXDY, - S32_D16_nofilter_DX, - S32_D16_filter_DXDY, - S32_D16_filter_DX, - - S16_D16_nofilter_DXDY, - S16_D16_nofilter_DX, - S16_D16_filter_DXDY, - S16_D16_filter_DX, - - SI8_D16_nofilter_DXDY, - SI8_D16_nofilter_DX, - SI8_D16_filter_DXDY, - SI8_D16_filter_DX, - - // Don't support 4444 -> 565 - NULL, NULL, NULL, NULL, - // Don't support A8 -> 565 - NULL, NULL, NULL, NULL - }; -#endif - - fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; - index >>= 1; // shift away any opaque/alpha distinction - fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; - - // our special-case shaderprocs - if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { - if (clamp_clamp) { - fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); - } else if (SkShader::kRepeat_TileMode == fTileModeX && - SkShader::kRepeat_TileMode == fTileModeY) { - fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); - } - } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clamp_clamp) { - fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); - } - - if (NULL == fShaderProc32) { - fShaderProc32 = this->chooseShaderProc32(); - } - - // see if our platform has any accelerated overrides - this->platformProcs(); - return true; -} - -static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, - int x, int y, - SkPMColor* SK_RESTRICT colors, - int count) { - SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); - SkASSERT(s.fInvKy == 0); - SkASSERT(count > 0 && colors != NULL); - SkASSERT(!s.fDoFilter); - - const int maxX = s.fBitmap->width() - 1; - const int maxY = s.fBitmap->height() - 1; - int ix = s.fFilterOneX + x; - int iy = SkClampMax(s.fFilterOneY + y, maxY); -#ifdef SK_DEBUG - { - SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &pt); - int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); - int ix2 = SkScalarFloorToInt(pt.fX); - - SkASSERT(iy == iy2); - SkASSERT(ix == ix2); - } -#endif - const SkPMColor* row = s.fBitmap->getAddr32(0, iy); - - // clamp to the left - if (ix < 0) { - int n = SkMin32(-ix, count); - sk_memset32(colors, row[0], n); - count -= n; - if (0 == count) { - return; - } - colors += n; - SkASSERT(-ix == n); - ix = 0; - } - // copy the middle - if (ix <= maxX) { - int n = SkMin32(maxX - ix + 1, count); - memcpy(colors, row + ix, n * sizeof(SkPMColor)); - count -= n; - if (0 == count) { - return; - } - colors += n; - } - SkASSERT(count > 0); - // clamp to the right - sk_memset32(colors, row[maxX], count); -} - -static inline int sk_int_mod(int x, int n) { - SkASSERT(n > 0); - if ((unsigned)x >= (unsigned)n) { - if (x < 0) { - x = n + ~(~x % n); - } else { - x = x % n; - } - } - return x; -} - -static inline int sk_int_mirror(int x, int n) { - x = sk_int_mod(x, 2 * n); - if (x >= n) { - x = n + ~(x - n); - } - return x; -} - -static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, - int x, int y, - SkPMColor* SK_RESTRICT colors, - int count) { - SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); - SkASSERT(s.fInvKy == 0); - SkASSERT(count > 0 && colors != NULL); - SkASSERT(!s.fDoFilter); - - const int stopX = s.fBitmap->width(); - const int stopY = s.fBitmap->height(); - int ix = s.fFilterOneX + x; - int iy = sk_int_mod(s.fFilterOneY + y, stopY); -#ifdef SK_DEBUG - { - SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &pt); - int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); - int ix2 = SkScalarFloorToInt(pt.fX); - - SkASSERT(iy == iy2); - SkASSERT(ix == ix2); - } -#endif - const SkPMColor* row = s.fBitmap->getAddr32(0, iy); - - ix = sk_int_mod(ix, stopX); - for (;;) { - int n = SkMin32(stopX - ix, count); - memcpy(colors, row + ix, n * sizeof(SkPMColor)); - count -= n; - if (0 == count) { - return; - } - colors += n; - ix = 0; - } -} - -static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, - int x, int y, - SkPMColor* SK_RESTRICT colors, - int count) { - SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); - SkASSERT(s.fInvKy == 0); - SkASSERT(count > 0 && colors != NULL); - SkASSERT(1 == s.fBitmap->width()); - - int iY0; - int iY1 SK_INIT_TO_AVOID_WARNING; - int iSubY SK_INIT_TO_AVOID_WARNING; - - if (s.fDoFilter) { - SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); - uint32_t xy[2]; - - mproc(s, xy, 1, x, y); - - iY0 = xy[0] >> 18; - iY1 = xy[0] & 0x3FFF; - iSubY = (xy[0] >> 14) & 0xF; - } else { - int yTemp; - - if (s.fInvType > SkMatrix::kTranslate_Mask) { - SkPoint pt; - s.fInvProc(*s.fInvMatrix, - SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, - &pt); - // When the matrix has a scale component the setup code in - // chooseProcs multiples the inverse matrix by the inverse of the - // bitmap's width and height. Since this method is going to do - // its own tiling and sampling we need to undo that here. - if (SkShader::kClamp_TileMode != s.fTileModeX || - SkShader::kClamp_TileMode != s.fTileModeY) { - yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); - } else { - yTemp = SkScalarFloorToInt(pt.fY); - } - } else { - yTemp = s.fFilterOneY + y; - } - - const int stopY = s.fBitmap->height(); - switch (s.fTileModeY) { - case SkShader::kClamp_TileMode: - iY0 = SkClampMax(yTemp, stopY-1); - break; - case SkShader::kRepeat_TileMode: - iY0 = sk_int_mod(yTemp, stopY); - break; - case SkShader::kMirror_TileMode: - default: - iY0 = sk_int_mirror(yTemp, stopY); - break; - } - -#ifdef SK_DEBUG - { - SkPoint pt; - s.fInvProc(*s.fInvMatrix, - SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, - &pt); - if (s.fInvType > SkMatrix::kTranslate_Mask && - (SkShader::kClamp_TileMode != s.fTileModeX || - SkShader::kClamp_TileMode != s.fTileModeY)) { - pt.fY *= s.fBitmap->height(); - } - int iY2; - - switch (s.fTileModeY) { - case SkShader::kClamp_TileMode: - iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); - break; - case SkShader::kRepeat_TileMode: - iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); - break; - case SkShader::kMirror_TileMode: - default: - iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); - break; - } - - SkASSERT(iY0 == iY2); - } -#endif - } - - const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); - SkPMColor color; - - if (s.fDoFilter) { - const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); - - if (s.fAlphaScale < 256) { - Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); - } else { - Filter_32_opaque(iSubY, *row0, *row1, &color); - } - } else { - if (s.fAlphaScale < 256) { - color = SkAlphaMulQ(*row0, s.fAlphaScale); - } else { - color = *row0; - } - } - - sk_memset32(colors, color, count); -} - -static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, - SkPMColor* SK_RESTRICT colors, int count) { - // if we get called, the matrix is too tricky, so we just draw nothing - sk_memset32(colors, 0, count); -} - -bool SkBitmapProcState::setupForTranslate() { - SkPoint pt; - fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); - - /* - * if the translate is larger than our ints, we can get random results, or - * worse, we might get 0x80000000, which wreaks havoc on us, since we can't - * negate it. - */ - const SkScalar too_big = SkIntToScalar(1 << 30); - if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { - return false; - } - - // Since we know we're not filtered, we re-purpose these fields allow - // us to go from device -> src coordinates w/ just an integer add, - // rather than running through the inverse-matrix - fFilterOneX = SkScalarFloorToInt(pt.fX); - fFilterOneY = SkScalarFloorToInt(pt.fY); - return true; -} - -SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { - - if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { - return NULL; - } - - static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; - - if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { - if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) { - return DoNothing_shaderproc; - } - return S32_D32_constX_shaderproc; - } - - if (fAlphaScale < 256) { - return NULL; - } - if (fInvType > SkMatrix::kTranslate_Mask) { - return NULL; - } - if (fDoFilter) { - return NULL; - } - - SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; - SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; - - if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { - if (this->setupForTranslate()) { - return Clamp_S32_D32_nofilter_trans_shaderproc; - } - return DoNothing_shaderproc; - } - if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { - if (this->setupForTranslate()) { - return Repeat_S32_D32_nofilter_trans_shaderproc; - } - return DoNothing_shaderproc; - } - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -#ifdef SK_DEBUG - -static void check_scale_nofilter(uint32_t bitmapXY[], int count, - unsigned mx, unsigned my) { - unsigned y = *bitmapXY++; - SkASSERT(y < my); - - const uint16_t* xptr = reinterpret_cast(bitmapXY); - for (int i = 0; i < count; ++i) { - SkASSERT(xptr[i] < mx); - } -} - -static void check_scale_filter(uint32_t bitmapXY[], int count, - unsigned mx, unsigned my) { - uint32_t YY = *bitmapXY++; - unsigned y0 = YY >> 18; - unsigned y1 = YY & 0x3FFF; - SkASSERT(y0 < my); - SkASSERT(y1 < my); - - for (int i = 0; i < count; ++i) { - uint32_t XX = bitmapXY[i]; - unsigned x0 = XX >> 18; - unsigned x1 = XX & 0x3FFF; - SkASSERT(x0 < mx); - SkASSERT(x1 < mx); - } -} - -static void check_affine_nofilter(uint32_t bitmapXY[], int count, - unsigned mx, unsigned my) { - for (int i = 0; i < count; ++i) { - uint32_t XY = bitmapXY[i]; - unsigned x = XY & 0xFFFF; - unsigned y = XY >> 16; - SkASSERT(x < mx); - SkASSERT(y < my); - } -} - -static void check_affine_filter(uint32_t bitmapXY[], int count, - unsigned mx, unsigned my) { - for (int i = 0; i < count; ++i) { - uint32_t YY = *bitmapXY++; - unsigned y0 = YY >> 18; - unsigned y1 = YY & 0x3FFF; - SkASSERT(y0 < my); - SkASSERT(y1 < my); - - uint32_t XX = *bitmapXY++; - unsigned x0 = XX >> 18; - unsigned x1 = XX & 0x3FFF; - SkASSERT(x0 < mx); - SkASSERT(x1 < mx); - } -} - -void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, - uint32_t bitmapXY[], int count, - int x, int y) { - SkASSERT(bitmapXY); - SkASSERT(count > 0); - - state.fMatrixProc(state, bitmapXY, count, x, y); - - void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); - - // There are four formats possible: - // scale -vs- affine - // filter -vs- nofilter - if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { - proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter; - } else { - proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter; - } - proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); -} - -SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { - return DebugMatrixProc; -} - -#endif - -/////////////////////////////////////////////////////////////////////////////// -/* - The storage requirements for the different matrix procs are as follows, - where each X or Y is 2 bytes, and N is the number of pixels/elements: - - scale/translate nofilter Y(4bytes) + N * X - affine/perspective nofilter N * (X Y) - scale/translate filter Y Y + N * (X X) - affine/perspective filter N * (Y Y X X) - */ -int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { - int32_t size = static_cast(bufferSize); - - size &= ~3; // only care about 4-byte aligned chunks - if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { - size -= 4; // the shared Y (or YY) coordinate - if (size < 0) { - size = 0; - } - size >>= 1; - } else { - size >>= 2; - } - - if (fDoFilter) { - size >>= 1; - } - - return size; -} diff --git a/gfx/skia/src/core/SkBitmapSampler.cpp b/gfx/skia/src/core/SkBitmapSampler.cpp deleted file mode 100644 index 2b68510445c7..000000000000 --- a/gfx/skia/src/core/SkBitmapSampler.cpp +++ /dev/null @@ -1,414 +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 "SkBitmapSampler.h" - -static SkTileModeProc get_tilemode_proc(SkShader::TileMode mode) -{ - switch (mode) { - case SkShader::kClamp_TileMode: - return do_clamp; - case SkShader::kRepeat_TileMode: - return do_repeat_mod; - case SkShader::kMirror_TileMode: - return do_mirror_mod; - default: - SkDEBUGFAIL("unknown mode"); - return NULL; - } -} - -SkBitmapSampler::SkBitmapSampler(const SkBitmap& bm, bool filter, - SkShader::TileMode tmx, SkShader::TileMode tmy) - : fBitmap(bm), fFilterBitmap(filter), fTileModeX(tmx), fTileModeY(tmy) -{ - SkASSERT(bm.width() > 0 && bm.height() > 0); - - fMaxX = SkToU16(bm.width() - 1); - fMaxY = SkToU16(bm.height() - 1); - - fTileProcX = get_tilemode_proc(tmx); - fTileProcY = get_tilemode_proc(tmy); -} - -void SkBitmapSampler::setPaint(const SkPaint& paint) -{ -} - -class SkNullBitmapSampler : public SkBitmapSampler { -public: - SkNullBitmapSampler(const SkBitmap& bm, bool filter, - SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, filter, tmx, tmy) {} - - virtual SkPMColor sample(SkFixed x, SkFixed y) const { return 0; } -}; - -///////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////// - -#define BITMAP_CLASSNAME_PREFIX(name) ARGB32##name -#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) *bitmap.getAddr32(x, y) -#include "SkBitmapSamplerTemplate.h" - -#include "SkColorPriv.h" - -#define BITMAP_CLASSNAME_PREFIX(name) RGB16##name -#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) SkPixel16ToPixel32(*bitmap.getAddr16(x, y)) -#include "SkBitmapSamplerTemplate.h" - -#define BITMAP_CLASSNAME_PREFIX(name) Index8##name -#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) bitmap.getIndex8Color(x, y) -#include "SkBitmapSamplerTemplate.h" - -///////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////// -///////////////// The Bilinear versions - -#include "SkFilterProc.h" - -class ARGB32_Bilinear_Sampler : public SkBitmapSampler { -public: - ARGB32_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, true, tmx, tmy) - { - fPtrProcTable = SkGetBilinearFilterPtrProcTable(); - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - const uint32_t *p00, *p01, *p10, *p11; - - // turn pixel centers into the top-left of our filter-box - x -= SK_FixedHalf; - y -= SK_FixedHalf; - - // compute our pointers - { - const SkBitmap* bitmap = &fBitmap; - int ix = x >> 16; - int iy = y >> 16; - - int maxX = fMaxX; - SkTileModeProc procX = fTileProcX; - int maxY = fMaxY; - SkTileModeProc procY = fTileProcY; - - int tmpx = procX(ix, maxX); - int tmpy = procY(iy, maxY); - p00 = bitmap->getAddr32(tmpx, tmpy); - - int tmpx1 = procX(ix + 1, maxX); - p01 = bitmap->getAddr32(tmpx1, tmpy); - - int tmpy1 = procY(iy + 1, maxY); - p10 = bitmap->getAddr32(tmpx, tmpy1); - - p11 = bitmap->getAddr32(tmpx1, tmpy1); - } - - SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y); - return proc(p00, p01, p10, p11); - } - -private: - const SkFilterPtrProc* fPtrProcTable; -}; - -class RGB16_Bilinear_Sampler : public SkBitmapSampler { -public: - RGB16_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, true, tmx, tmy) - { - fProcTable = SkGetBilinearFilterProcTable(); - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - const uint16_t *p00, *p01, *p10, *p11; - - // turn pixel centers into the top-left of our filter-box - x -= SK_FixedHalf; - y -= SK_FixedHalf; - - // compute our pointers - { - const SkBitmap* bitmap = &fBitmap; - int ix = x >> 16; - int iy = y >> 16; - - int maxX = fMaxX; - SkTileModeProc procX = fTileProcX; - int maxY = fMaxY; - SkTileModeProc procY = fTileProcY; - - int tmpx = procX(ix, maxX); - int tmpy = procY(iy, maxY); - p00 = bitmap->getAddr16(tmpx, tmpy); - - int tmpx1 = procX(ix + 1, maxX); - p01 = bitmap->getAddr16(tmpx1, tmpy); - - int tmpy1 = procY(iy + 1, maxY); - p10 = bitmap->getAddr16(tmpx, tmpy1); - - p11 = bitmap->getAddr16(tmpx1, tmpy1); - } - - SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y); - uint32_t c = proc(SkExpand_rgb_16(*p00), SkExpand_rgb_16(*p01), - SkExpand_rgb_16(*p10), SkExpand_rgb_16(*p11)); - - return SkPixel16ToPixel32((uint16_t)SkCompact_rgb_16(c)); - } - -private: - const SkFilterProc* fProcTable; -}; - -// If we had a init/term method on sampler, we could avoid the per-pixel -// call to lockColors/unlockColors - -class Index8_Bilinear_Sampler : public SkBitmapSampler { -public: - Index8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, true, tmx, tmy) - { - fPtrProcTable = SkGetBilinearFilterPtrProcTable(); - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - const SkBitmap* bitmap = &fBitmap; - - const uint8_t *p00, *p01, *p10, *p11; - - // turn pixel centers into the top-left of our filter-box - x -= SK_FixedHalf; - y -= SK_FixedHalf; - - // compute our pointers - { - int ix = x >> 16; - int iy = y >> 16; - - int maxX = fMaxX; - SkTileModeProc procX = fTileProcX; - int maxY = fMaxY; - SkTileModeProc procY = fTileProcY; - - int tmpx = procX(ix, maxX); - int tmpy = procY(iy, maxY); - p00 = bitmap->getAddr8(tmpx, tmpy); - - int tmpx1 = procX(ix + 1, maxX); - p01 = bitmap->getAddr8(tmpx1, tmpy); - - int tmpy1 = procY(iy + 1, maxY); - p10 = bitmap->getAddr8(tmpx, tmpy1); - - p11 = bitmap->getAddr8(tmpx1, tmpy1); - } - - const SkPMColor* colors = bitmap->getColorTable()->lockColors(); - - SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y); - uint32_t c = proc(&colors[*p00], &colors[*p01], &colors[*p10], &colors[*p11]); - - bitmap->getColorTable()->unlockColors(false); - - return c; - } - -private: - const SkFilterPtrProc* fPtrProcTable; -}; - -class A8_Bilinear_Sampler : public SkBitmapSampler { -public: - A8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, true, tmx, tmy) - , fColor(0) - { - fProcTable = SkGetBilinearFilterProcTable(); - } - - virtual void setPaint(const SkPaint& paint) - { - fColor = SkPreMultiplyColor(paint.getColor()); - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - const uint8_t *p00, *p01, *p10, *p11; - - // turn pixel centers into the top-left of our filter-box - x -= SK_FixedHalf; - y -= SK_FixedHalf; - - // compute our pointers - { - const SkBitmap* bitmap = &fBitmap; - int ix = x >> 16; - int iy = y >> 16; - - int maxX = fMaxX; - SkTileModeProc procX = fTileProcX; - int maxY = fMaxY; - SkTileModeProc procY = fTileProcY; - - int tmpx = procX(ix, maxX); - int tmpy = procY(iy, maxY); - p00 = bitmap->getAddr8(tmpx, tmpy); - - int tmpx1 = procX(ix + 1, maxX); - p01 = bitmap->getAddr8(tmpx1, tmpy); - - int tmpy1 = procY(iy + 1, maxY); - p10 = bitmap->getAddr8(tmpx, tmpy1); - - p11 = bitmap->getAddr8(tmpx1, tmpy1); - } - - SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y); - int alpha = proc(*p00, *p01, *p10, *p11); - return SkAlphaMulQ(fColor, SkAlpha255To256(alpha)); - } - -private: - const SkFilterProc* fProcTable; - SkPMColor fColor; -}; - -class A8_NoFilter_Sampler : public SkBitmapSampler { -public: - A8_NoFilter_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, false, tmx, tmy) - { - } - - virtual void setPaint(const SkPaint& paint) - { - fColor = SkPreMultiplyColor(paint.getColor()); - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - int ix = SkFixedFloor(x); - int iy = SkFixedFloor(y); - - int alpha = *fBitmap.getAddr8(fTileProcX(ix, fMaxX), fTileProcY(iy, fMaxY)); - return SkAlphaMulQ(fColor, SkAlpha255To256(alpha)); - } - -private: - SkPMColor fColor; -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -SkBitmapSampler* SkBitmapSampler::Create(const SkBitmap& bm, bool doFilter, - SkShader::TileMode tmx, - SkShader::TileMode tmy) -{ - switch (bm.getConfig()) { - case SkBitmap::kARGB_8888_Config: - if (doFilter) - return SkNEW_ARGS(ARGB32_Bilinear_Sampler, (bm, tmx, tmy)); - - if (tmx == tmy) { - switch (tmx) { - case SkShader::kClamp_TileMode: - return SkNEW_ARGS(ARGB32_Point_Clamp_Sampler, (bm)); - case SkShader::kRepeat_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(ARGB32_Point_Repeat_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(ARGB32_Point_Repeat_Mod_Sampler, (bm)); - case SkShader::kMirror_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(ARGB32_Point_Mirror_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(ARGB32_Point_Mirror_Mod_Sampler, (bm)); - default: - SkDEBUGFAIL("unknown mode"); - } - } - else { // tmx != tmy - return SkNEW_ARGS(ARGB32_Point_Sampler, (bm, tmx, tmy)); - } - break; - - case SkBitmap::kRGB_565_Config: - if (doFilter) - return SkNEW_ARGS(RGB16_Bilinear_Sampler, (bm, tmx, tmy)); - - if (tmx == tmy) { - switch (tmx) { - case SkShader::kClamp_TileMode: - return SkNEW_ARGS(RGB16_Point_Clamp_Sampler, (bm)); - case SkShader::kRepeat_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(RGB16_Point_Repeat_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(RGB16_Point_Repeat_Mod_Sampler, (bm)); - case SkShader::kMirror_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(RGB16_Point_Mirror_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(RGB16_Point_Mirror_Mod_Sampler, (bm)); - default: - SkDEBUGFAIL("unknown mode"); - } - } - else { // tmx != tmy - return SkNEW_ARGS(RGB16_Point_Sampler, (bm, tmx, tmy)); - } - break; - - case SkBitmap::kIndex8_Config: - if (doFilter) - return SkNEW_ARGS(Index8_Bilinear_Sampler, (bm, tmx, tmy)); - - if (tmx == tmy) { - switch (tmx) { - case SkShader::kClamp_TileMode: - return SkNEW_ARGS(Index8_Point_Clamp_Sampler, (bm)); - case SkShader::kRepeat_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(Index8_Point_Repeat_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(Index8_Point_Repeat_Mod_Sampler, (bm)); - case SkShader::kMirror_TileMode: - if (is_pow2(bm.width()) && is_pow2(bm.height())) - return SkNEW_ARGS(Index8_Point_Mirror_Pow2_Sampler, (bm)); - else - return SkNEW_ARGS(Index8_Point_Mirror_Mod_Sampler, (bm)); - default: - SkDEBUGFAIL("unknown mode"); - } - } - else { // tmx != tmy - return SkNEW_ARGS(Index8_Point_Sampler, (bm, tmx, tmy)); - } - break; - - case SkBitmap::kA8_Config: - if (doFilter) - return SkNEW_ARGS(A8_Bilinear_Sampler, (bm, tmx, tmy)); - else - return SkNEW_ARGS(A8_NoFilter_Sampler, (bm, tmx, tmy)); - break; - - default: - SkDEBUGFAIL("unknown device"); - } - return SkNEW_ARGS(SkNullBitmapSampler, (bm, doFilter, tmx, tmy)); -} diff --git a/gfx/skia/src/core/SkBitmapSampler.h b/gfx/skia/src/core/SkBitmapSampler.h deleted file mode 100644 index 47ec3313a670..000000000000 --- a/gfx/skia/src/core/SkBitmapSampler.h +++ /dev/null @@ -1,162 +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 SkBitmapSampler_DEFINED -#define SkBitmapSampler_DEFINED - -#include "SkBitmap.h" -#include "SkPaint.h" -#include "SkShader.h" - -typedef int (*SkTileModeProc)(int value, unsigned max); - -class SkBitmapSampler { -public: - SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy); - virtual ~SkBitmapSampler() {} - - const SkBitmap& getBitmap() const { return fBitmap; } - bool getFilterBitmap() const { return fFilterBitmap; } - SkShader::TileMode getTileModeX() const { return fTileModeX; } - SkShader::TileMode getTileModeY() const { return fTileModeY; } - - /** Given a pixel center at [x,y], return the color sample - */ - virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0; - - virtual void setPaint(const SkPaint& paint); - - // This is the factory for finding an optimal subclass - static SkBitmapSampler* Create(const SkBitmap&, bool filter, - SkShader::TileMode tmx, SkShader::TileMode tmy); - -protected: - const SkBitmap& fBitmap; - uint16_t fMaxX, fMaxY; - bool fFilterBitmap; - SkShader::TileMode fTileModeX; - SkShader::TileMode fTileModeY; - SkTileModeProc fTileProcX; - SkTileModeProc fTileProcY; - - // illegal - SkBitmapSampler& operator=(const SkBitmapSampler&); -}; - -static inline int fixed_clamp(SkFixed x) -{ -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (x >> 16) - x = 0xFFFF; - if (x < 0) - x = 0; -#else - if (x >> 16) - { - if (x < 0) - x = 0; - else - x = 0xFFFF; - } -#endif - return x; -} - -////////////////////////////////////////////////////////////////////////////////////// - -static inline int fixed_repeat(SkFixed x) -{ - return x & 0xFFFF; -} - -static inline int 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; -} - -static inline bool is_pow2(int count) -{ - SkASSERT(count > 0); - return (count & (count - 1)) == 0; -} - -static inline int do_clamp(int index, unsigned max) -{ - SkASSERT((int)max >= 0); - -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (index > (int)max) - index = max; - if (index < 0) - index = 0; -#else - if ((unsigned)index > max) - { - if (index < 0) - index = 0; - else - index = max; - } -#endif - return index; -} - -static inline int do_repeat_mod(int index, unsigned max) -{ - SkASSERT((int)max >= 0); - - if ((unsigned)index > max) - { - if (index < 0) - index = max - (~index % (max + 1)); - else - index = index % (max + 1); - } - return index; -} - -static inline int do_repeat_pow2(int index, unsigned max) -{ - SkASSERT((int)max >= 0 && is_pow2(max + 1)); - - return index & max; -} - -static inline int do_mirror_mod(int index, unsigned max) -{ - SkASSERT((int)max >= 0); - - // have to handle negatives so that - // -1 -> 0, -2 -> 1, -3 -> 2, etc. - // so we can't just cal abs - index ^= index >> 31; - - if ((unsigned)index > max) - { - int mod = (max + 1) << 1; - index = index % mod; - if ((unsigned)index > max) - index = mod - index - 1; - } - return index; -} - -static inline int do_mirror_pow2(int index, unsigned max) -{ - SkASSERT((int)max >= 0 && is_pow2(max + 1)); - - int s = (index & (max + 1)) - 1; - s = ~(s >> 31); - // at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval - return (index ^ s) & max; -} - -#endif diff --git a/gfx/skia/src/core/SkBitmapSamplerTemplate.h b/gfx/skia/src/core/SkBitmapSamplerTemplate.h deleted file mode 100644 index 7b56af79843d..000000000000 --- a/gfx/skia/src/core/SkBitmapSamplerTemplate.h +++ /dev/null @@ -1,108 +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. - */ - - -/* this guy is pulled in multiple times, with the following symbols defined each time: - - #define BITMAP_CLASSNAME_PREFIX(name) ARGB32##name - #defube BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) *bitmap.getAddr32(x, y) -*/ - -class BITMAP_CLASSNAME_PREFIX(_Point_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Sampler)(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy) - : SkBitmapSampler(bm, false, tmx, tmy) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = fTileProcX(SkFixedFloor(x), fMaxX); - y = fTileProcY(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - - -class BITMAP_CLASSNAME_PREFIX(_Point_Clamp_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Clamp_Sampler)(const SkBitmap& bm) - : SkBitmapSampler(bm, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = do_clamp(SkFixedFloor(x), fMaxX); - y = do_clamp(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - -class BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Pow2_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Pow2_Sampler)(const SkBitmap& bm) - : SkBitmapSampler(bm, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = do_repeat_pow2(SkFixedFloor(x), fMaxX); - y = do_repeat_pow2(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - -class BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Mod_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Mod_Sampler)(const SkBitmap& bm) - : SkBitmapSampler(bm, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = do_repeat_mod(SkFixedFloor(x), fMaxX); - y = do_repeat_mod(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - -class BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Pow2_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Pow2_Sampler)(const SkBitmap& bm) - : SkBitmapSampler(bm, false, SkShader::kMirror_TileMode, SkShader::kMirror_TileMode) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = do_mirror_pow2(SkFixedFloor(x), fMaxX); - y = do_mirror_pow2(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - -class BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Mod_Sampler) : public SkBitmapSampler { -public: - BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Mod_Sampler)(const SkBitmap& bm) - : SkBitmapSampler(bm, false, SkShader::kMirror_TileMode, SkShader::kMirror_TileMode) - { - } - - virtual SkPMColor sample(SkFixed x, SkFixed y) const - { - x = do_mirror_mod(SkFixedFloor(x), fMaxX); - y = do_mirror_mod(SkFixedFloor(y), fMaxY); - return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y); - } -}; - -#undef BITMAP_CLASSNAME_PREFIX -#undef BITMAP_PIXEL_TO_PMCOLOR diff --git a/gfx/skia/src/core/SkBlitRow_D4444.cpp b/gfx/skia/src/core/SkBlitRow_D4444.cpp deleted file mode 100644 index 026d15637644..000000000000 --- a/gfx/skia/src/core/SkBlitRow_D4444.cpp +++ /dev/null @@ -1,218 +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 "SkBlitRow.h" -#include "SkColorPriv.h" -#include "SkDither.h" - -/////////////////////////////////////////////////////////////////////////////// - -static void S32_D4444_Opaque(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - U8CPU alpha, int /*x*/, int /*y*/) { - SkASSERT(255 == alpha); - - if (count > 0) { - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - SkASSERT(SkGetPackedA32(c) == 255); - *dst++ = SkPixel32ToPixel4444(c); - } while (--count != 0); - } -} - -static void S32_D4444_Blend(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - U8CPU alpha, int /*x*/, int /*y*/) { - SkASSERT(255 > alpha); - - if (count > 0) { - unsigned scale16 = SkAlpha255To256(alpha) >> 4; - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - SkASSERT(SkGetPackedA32(c) == 255); - - uint32_t src_expand = SkExpand32_4444(c); - uint32_t dst_expand = SkExpand_4444(*dst); - dst_expand += (src_expand - dst_expand) * scale16 >> 4; - *dst++ = SkCompact_4444(dst_expand); - } while (--count != 0); - } -} - -static void S32A_D4444_Opaque(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - U8CPU alpha, int /*x*/, int /*y*/) { - SkASSERT(255 == alpha); - - if (count > 0) { - do { - SkPMColor c = *src++; - SkPMColorAssert(c); -// if (__builtin_expect(c!=0, 1)) - if (c) - { - unsigned scale16 = SkAlpha255To256(255 - SkGetPackedA32(c)) >> 4; - uint32_t src_expand = SkExpand_8888(c); - uint32_t dst_expand = SkExpand_4444(*dst) * scale16; - *dst = SkCompact_4444((src_expand + dst_expand) >> 4); - } - dst += 1; - } while (--count != 0); - } -} - -static void S32A_D4444_Blend(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - U8CPU alpha, int /*x*/, int /*y*/) { - SkASSERT(255 > alpha); - - if (count > 0) { - int src_scale = SkAlpha255To256(alpha) >> 4; - do { - SkPMColor sc = *src++; - SkPMColorAssert(sc); - - if (sc) { - unsigned dst_scale = 16 - (SkGetPackedA32(sc) * src_scale >> 8); - uint32_t src_expand = SkExpand32_4444(sc) * src_scale; - uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale; - *dst = SkCompact_4444((src_expand + dst_expand) >> 4); - } - dst += 1; - } while (--count != 0); - } -} - -///////////////////////////////////////////////////////////////////////////// - -static void S32_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, - int count, U8CPU alpha, int x, int y) { - SkASSERT(255 == alpha); - - if (count > 0) { - DITHER_4444_SCAN(y); - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - - unsigned dither = DITHER_VALUE(x); - *dst++ = SkDitherARGB32To4444(c, dither); - DITHER_INC_X(x); - } while (--count != 0); - } -} - -static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, - int count, U8CPU alpha, int x, int y) { - SkASSERT(255 > alpha); - - if (count > 0) { - int scale16 = SkAlpha255To256(alpha) >> 4; - DITHER_4444_SCAN(y); - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - SkASSERT(SkGetPackedA32(c) == 255); - - uint32_t src_expand = SkExpand32_4444(c) * scale16; - uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16); - - c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor - *dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x)); - DITHER_INC_X(x); - } while (--count != 0); - } -} - -static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, - int count, U8CPU alpha, int x, int y) { - SkASSERT(255 == alpha); - - if (count > 0) { - DITHER_4444_SCAN(y); - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - if (c) { - unsigned a = SkGetPackedA32(c); - int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a)); - - unsigned scale16 = SkAlpha255To256(255 - a) >> 4; - uint32_t src_expand = SkExpand_8888(c); - uint32_t dst_expand = SkExpand_4444(*dst) * scale16; - // convert back to SkPMColor - c = SkCompact_8888(src_expand + dst_expand); - *dst = SkDitherARGB32To4444(c, d); - } - dst += 1; - DITHER_INC_X(x); - } while (--count != 0); - } -} - -// need DitherExpand888To4444(expand, dither) - -static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, - int count, U8CPU alpha, int x, int y) { - SkASSERT(255 > alpha); - - if (count > 0) { - int src_scale = SkAlpha255To256(alpha) >> 4; - DITHER_4444_SCAN(y); - do { - SkPMColor c = *src++; - SkPMColorAssert(c); - if (c) { - unsigned a = SkAlpha255To256(SkGetPackedA32(c)); - int d = SkAlphaMul(DITHER_VALUE(x), a); - - unsigned dst_scale = 16 - SkAlphaMul(src_scale, a); - uint32_t src_expand = SkExpand32_4444(c) * src_scale; - uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale; - // convert back to SkPMColor - c = SkCompact_8888(src_expand + dst_expand); - *dst = SkDitherARGB32To4444(c, d); - } - dst += 1; - DITHER_INC_X(x); - } while (--count != 0); - } -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -static const SkBlitRow::Proc gProcs4444[] = { - // no dither - S32_D4444_Opaque, - S32_D4444_Blend, - - S32A_D4444_Opaque, - S32A_D4444_Blend, - - // dither - S32_D4444_Opaque_Dither, - S32_D4444_Blend_Dither, - - S32A_D4444_Opaque_Dither, - S32A_D4444_Blend_Dither -}; - -SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags); -SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags) -{ - SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444)); - - return gProcs4444[flags]; -} diff --git a/gfx/skia/src/core/SkBlitter_4444.cpp b/gfx/skia/src/core/SkBlitter_4444.cpp deleted file mode 100644 index 0d81f8ddb677..000000000000 --- a/gfx/skia/src/core/SkBlitter_4444.cpp +++ /dev/null @@ -1,480 +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 "SkCoreBlitters.h" -#include "SkColorPriv.h" -#include "SkDither.h" -#include "SkShader.h" -#include "SkTemplatesPriv.h" -#include "SkUtils.h" -#include "SkXfermode.h" - -static inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst, - U8CPU aa) { - SkASSERT((unsigned)aa <= 255); - - unsigned src_scale = SkAlpha255To256(aa) >> 4; - unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale)); - - uint32_t src32 = SkExpand_4444(src) * src_scale; - uint32_t dst32 = SkExpand_4444(dst) * dst_scale; - return SkCompact_4444((src32 + dst32) >> 4); -} - -/////////////////////////////////////////////////////////////////////////////// - -class SkARGB4444_Blitter : public SkRasterBlitter { -public: - SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint); - virtual void blitH(int x, int y, int width); - virtual void blitAntiH(int x, int y, const SkAlpha antialias[], - const int16_t runs[]); - virtual void blitV(int x, int y, int height, SkAlpha alpha); - virtual void blitRect(int x, int y, int width, int height); - virtual void blitMask(const SkMask&, const SkIRect&); - virtual const SkBitmap* justAnOpaqueColor(uint32_t*); - -protected: - SkPMColor16 fPMColor16, fPMColor16Other; - SkPMColor16 fRawColor16, fRawColor16Other; - uint8_t fScale16; - -private: - // illegal - SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&); - - typedef SkRasterBlitter INHERITED; -}; - - -SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, - const SkPaint& paint) : INHERITED(device) { - // cache premultiplied versions in 4444 - SkPMColor c = SkPreMultiplyColor(paint.getColor()); - fPMColor16 = SkPixel32ToPixel4444(c); - if (paint.isDither()) { - fPMColor16Other = SkDitherPixel32To4444(c); - } else { - fPMColor16Other = fPMColor16; - } - - // cache raw versions in 4444 - fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4, - SkColorGetG(c) >> 4, SkColorGetB(c) >> 4); - if (paint.isDither()) { - fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c), - SkColorGetG(c), SkColorGetB(c)); - } else { - fRawColor16Other = fRawColor16; - } - - fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); - if (16 == fScale16) { - // force the original to also be opaque - fPMColor16 |= (0xF << SK_A4444_SHIFT); - } -} - -const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) { - if (16 == fScale16) { - *value = fPMColor16; - return &fDevice; - } - return NULL; -} - -static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, - SkPMColor16 other, unsigned invScale, int count) { - int twice = count >> 1; - while (--twice >= 0) { - *dst = color + SkAlphaMulQ4(*dst, invScale); - dst++; - *dst = other + SkAlphaMulQ4(*dst, invScale); - dst++; - } - if (count & 1) { - *dst = color + SkAlphaMulQ4(*dst, invScale); - } -} - -static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) { - uint32_t c32 = SkExpand_4444(c); - return c32 | (c32 << 4); -} - -static void src_over_4444x(SkPMColor16 dst[], uint32_t color, - uint32_t other, unsigned invScale, int count) { - int twice = count >> 1; - uint32_t tmp; - while (--twice >= 0) { - tmp = SkExpand_4444(*dst) * invScale; - *dst++ = SkCompact_4444((color + tmp) >> 4); - tmp = SkExpand_4444(*dst) * invScale; - *dst++ = SkCompact_4444((other + tmp) >> 4); - } - if (count & 1) { - tmp = SkExpand_4444(*dst) * invScale; - *dst = SkCompact_4444((color + tmp) >> 4); - } -} - -void SkARGB4444_Blitter::blitH(int x, int y, int width) { - SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); - - if (0 == fScale16) { - return; - } - - SkPMColor16* device = fDevice.getAddr16(x, y); - SkPMColor16 color = fPMColor16; - SkPMColor16 other = fPMColor16Other; - - if ((x ^ y) & 1) { - SkTSwap(color, other); - } - - if (16 == fScale16) { - sk_dither_memset16(device, color, other, width); - } else { - src_over_4444x(device, SkExpand_4444_Replicate(color), - SkExpand_4444_Replicate(other), - 16 - fScale16, width); - } -} - -void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { - if (0 == alpha || 0 == fScale16) { - return; - } - - SkPMColor16* device = fDevice.getAddr16(x, y); - SkPMColor16 color = fPMColor16; - SkPMColor16 other = fPMColor16Other; - size_t rb = fDevice.rowBytes(); - - if ((x ^ y) & 1) { - SkTSwap(color, other); - } - - if (16 == fScale16 && 255 == alpha) { - while (--height >= 0) { - *device = color; - device = (SkPMColor16*)((char*)device + rb); - SkTSwap(color, other); - } - } else { - unsigned alphaScale = SkAlpha255To256(alpha); - uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4); - // need to normalize the low nibble of each expanded component - // so we don't overflow the add with d32 - c32 = SkCompact_4444(c32 >> 4); - unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32)); - // now re-expand and replicate - c32 = SkExpand_4444_Replicate(c32); - - while (--height >= 0) { - uint32_t d32 = SkExpand_4444(*device) * invScale; - *device = SkCompact_4444((c32 + d32) >> 4); - device = (SkPMColor16*)((char*)device + rb); - } - } -} - -void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) { - SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && - y + height <= fDevice.height()); - - if (0 == fScale16) { - return; - } - - SkPMColor16* device = fDevice.getAddr16(x, y); - SkPMColor16 color = fPMColor16; - SkPMColor16 other = fPMColor16Other; - - if ((x ^ y) & 1) { - SkTSwap(color, other); - } - - if (16 == fScale16) { - while (--height >= 0) { - sk_dither_memset16(device, color, other, width); - device = (SkPMColor16*)((char*)device + fDevice.rowBytes()); - SkTSwap(color, other); - } - } else { - unsigned invScale = 16 - fScale16; - - uint32_t c32 = SkExpand_4444_Replicate(color); - uint32_t o32 = SkExpand_4444_Replicate(other); - while (--height >= 0) { - src_over_4444x(device, c32, o32, invScale, width); - device = (SkPMColor16*)((char*)device + fDevice.rowBytes()); - SkTSwap(c32, o32); - } - } -} - -void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], - const int16_t runs[]) { - if (0 == fScale16) { - return; - } - - SkPMColor16* device = fDevice.getAddr16(x, y); - SkPMColor16 color = fPMColor16; - SkPMColor16 other = fPMColor16Other; - - if ((x ^ y) & 1) { - SkTSwap(color, other); - } - - for (;;) { - int count = runs[0]; - SkASSERT(count >= 0); - if (count <= 0) { - return; - } - - unsigned aa = antialias[0]; - if (aa) { - if (0xFF == aa) { - if (16 == fScale16) { - sk_dither_memset16(device, color, other, count); - } else { - src_over_4444(device, color, other, 16 - fScale16, count); - } - } else { - // todo: respect dithering - aa = SkAlpha255To256(aa); // FIX - SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4); - unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX - int n = count; - do { - --n; - device[n] = src + SkAlphaMulQ4(device[n], dst_scale); - } while (n > 0); - } - } - - runs += count; - antialias += count; - device += count; - - if (count & 1) { - SkTSwap(color, other); - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -#define solid_8_pixels(mask, dst, color) \ - do { \ - if (mask & 0x80) dst[0] = color; \ - if (mask & 0x40) dst[1] = color; \ - if (mask & 0x20) dst[2] = color; \ - if (mask & 0x10) dst[3] = color; \ - if (mask & 0x08) dst[4] = color; \ - if (mask & 0x04) dst[5] = color; \ - if (mask & 0x02) dst[6] = color; \ - if (mask & 0x01) dst[7] = color; \ - } while (0) - -#define SK_BLITBWMASK_NAME SkARGB4444_BlitBW -#define SK_BLITBWMASK_ARGS , SkPMColor16 color -#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) -#define SK_BLITBWMASK_GETADDR getAddr16 -#define SK_BLITBWMASK_DEVTYPE uint16_t -#include "SkBlitBWMaskTemplate.h" - -#define blend_8_pixels(mask, dst, sc, dst_scale) \ - do { \ - if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ - if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ - if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ - if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ - if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ - if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ - if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ - if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ - } while (0) - -#define SK_BLITBWMASK_NAME SkARGB4444_BlendBW -#define SK_BLITBWMASK_ARGS , uint16_t sc, unsigned dst_scale -#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale) -#define SK_BLITBWMASK_GETADDR getAddr16 -#define SK_BLITBWMASK_DEVTYPE uint16_t -#include "SkBlitBWMaskTemplate.h" - -void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { - SkASSERT(mask.fBounds.contains(clip)); - - if (0 == fScale16) { - return; - } - - if (mask.fFormat == SkMask::kBW_Format) { - if (16 == fScale16) { - SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16); - } else { - SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16); - } - return; - } - - int x = clip.fLeft; - int y = clip.fTop; - int width = clip.width(); - int height = clip.height(); - - SkPMColor16* device = fDevice.getAddr16(x, y); - const uint8_t* alpha = mask.getAddr8(x, y); - SkPMColor16 srcColor = fPMColor16; - size_t devRB = fDevice.rowBytes() - (width << 1); - unsigned maskRB = mask.fRowBytes - width; - - do { - int w = width; - do { - unsigned aa = *alpha++; - *device = SkBlendARGB4444(srcColor, *device, aa); - device += 1; - } while (--w != 0); - device = (SkPMColor16*)((char*)device + devRB); - alpha += maskRB; - } while (--height != 0); -} - -/////////////////////////////////////////////////////////////////////////////// - -class SkARGB4444_Shader_Blitter : public SkShaderBlitter { - SkXfermode* fXfermode; - SkBlitRow::Proc fOpaqueProc; - SkBlitRow::Proc fAlphaProc; - SkPMColor* fBuffer; - uint8_t* fAAExpand; -public: - -SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device, paint) { - const int width = device.width(); - fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width); - fAAExpand = (uint8_t*)(fBuffer + width); - - fXfermode = paint.getXfermode(); - SkSafeRef(fXfermode); - - unsigned flags = 0; - if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { - flags |= SkBlitRow::kSrcPixelAlpha_Flag; - } - if (paint.isDither()) { - flags |= SkBlitRow::kDither_Flag; - } - fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config); - fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, - SkBitmap::kARGB_4444_Config); -} - -virtual ~SkARGB4444_Shader_Blitter() { - SkSafeUnref(fXfermode); - sk_free(fBuffer); -} - -virtual void blitH(int x, int y, int width) { - SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); - - SkPMColor16* device = fDevice.getAddr16(x, y); - SkPMColor* span = fBuffer; - - fShader->shadeSpan(x, y, span, width); - if (fXfermode) { - fXfermode->xfer4444(device, span, width, NULL); - } else { - fOpaqueProc(device, span, width, 0xFF, x, y); - } -} - -virtual void blitAntiH(int x, int y, const SkAlpha antialias[], - const int16_t runs[]) { - SkPMColor* SK_RESTRICT span = fBuffer; - uint8_t* SK_RESTRICT aaExpand = fAAExpand; - SkPMColor16* device = fDevice.getAddr16(x, y); - SkShader* shader = fShader; - SkXfermode* xfer = fXfermode; - - if (NULL != xfer) { - for (;;) { - int count = *runs; - if (count <= 0) { - break; - } - int aa = *antialias; - if (aa) { - shader->shadeSpan(x, y, span, count); - if (255 == aa) { - xfer->xfer4444(device, span, count, NULL); - } else { - const uint8_t* aaBuffer = antialias; - if (count > 1) { - memset(aaExpand, aa, count); - aaBuffer = aaExpand; - } - xfer->xfer4444(device, span, count, aaBuffer); - } - } - device += count; - runs += count; - antialias += count; - x += count; - } - } else { // no xfermode - for (;;) { - int count = *runs; - if (count <= 0) { - break; - } - int aa = *antialias; - if (aa) { - fShader->shadeSpan(x, y, span, count); - if (255 == aa) { - fOpaqueProc(device, span, count, aa, x, y); - } else { - fAlphaProc(device, span, count, aa, x, y); - } - } - device += count; - runs += count; - antialias += count; - x += count; - } - } -} - -private: - typedef SkShaderBlitter INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device, - const SkPaint& paint, - void* storage, size_t storageSize) -{ - SkBlitter* blitter; - - if (paint.getShader()) { - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint)); - } else { - SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint)); - } - return blitter; -} diff --git a/gfx/skia/src/core/SkBlitter_A1.cpp b/gfx/skia/src/core/SkBlitter_A1.cpp deleted file mode 100644 index b64afe2ae98e..000000000000 --- a/gfx/skia/src/core/SkBlitter_A1.cpp +++ /dev/null @@ -1,50 +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 "SkCoreBlitters.h" - -SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) { - fSrcA = paint.getAlpha(); -} - -void SkA1_Blitter::blitH(int x, int y, int width) { - SkASSERT(x >= 0 && y >= 0 && - (unsigned)(x + width) <= (unsigned)fDevice.width()); - - if (fSrcA <= 0x7F) { - return; - } - uint8_t* dst = fDevice.getAddr1(x, y); - int right = x + width; - - int left_mask = 0xFF >> (x & 7); - int rite_mask = 0xFF << (8 - (right & 7)); - int full_runs = (right >> 3) - ((x + 7) >> 3); - - // check for empty right mask, so we don't read off the end - // (or go slower than we need to) - if (rite_mask == 0) { - SkASSERT(full_runs >= 0); - full_runs -= 1; - rite_mask = 0xFF; - } - if (left_mask == 0xFF) { - full_runs -= 1; - } - if (full_runs < 0) { - SkASSERT((left_mask & rite_mask) != 0); - *dst |= (left_mask & rite_mask); - } else { - *dst++ |= left_mask; - memset(dst, 0xFF, full_runs); - dst += full_runs; - *dst |= rite_mask; - } -} diff --git a/gfx/skia/src/core/SkColorTable.cpp b/gfx/skia/src/core/SkColorTable.cpp deleted file mode 100644 index e1ebf9202dc3..000000000000 --- a/gfx/skia/src/core/SkColorTable.cpp +++ /dev/null @@ -1,159 +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 "SkColorTable.h" -#include "SkFlattenableBuffers.h" -#include "SkStream.h" -#include "SkTemplates.h" - -SK_DEFINE_INST_COUNT(SkColorTable) - -SkColorTable::SkColorTable(int count) - : f16BitCache(NULL), fFlags(0) -{ - if (count < 0) - count = 0; - else if (count > 256) - count = 256; - - fCount = SkToU16(count); - fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor)); - memset(fColors, 0, count * sizeof(SkPMColor)); - - SkDEBUGCODE(fColorLockCount = 0;) - SkDEBUGCODE(f16BitCacheLockCount = 0;) -} - -// As copy constructor is hidden in the class hierarchy, we need to call -// default constructor explicitly to suppress a compiler warning. -SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() { - f16BitCache = NULL; - fFlags = src.fFlags; - int count = src.count(); - fCount = SkToU16(count); - fColors = reinterpret_cast( - sk_malloc_throw(count * sizeof(SkPMColor))); - memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); - - SkDEBUGCODE(fColorLockCount = 0;) - SkDEBUGCODE(f16BitCacheLockCount = 0;) -} - -SkColorTable::SkColorTable(const SkPMColor colors[], int count) - : f16BitCache(NULL), fFlags(0) -{ - if (count < 0) - count = 0; - else if (count > 256) - count = 256; - - fCount = SkToU16(count); - fColors = reinterpret_cast( - sk_malloc_throw(count * sizeof(SkPMColor))); - - if (colors) - memcpy(fColors, colors, count * sizeof(SkPMColor)); - - SkDEBUGCODE(fColorLockCount = 0;) - SkDEBUGCODE(f16BitCacheLockCount = 0;) -} - -SkColorTable::~SkColorTable() -{ - SkASSERT(fColorLockCount == 0); - SkASSERT(f16BitCacheLockCount == 0); - - sk_free(fColors); - sk_free(f16BitCache); -} - -void SkColorTable::setFlags(unsigned flags) -{ - fFlags = SkToU8(flags); -} - -void SkColorTable::unlockColors(bool changed) -{ - SkASSERT(fColorLockCount != 0); - SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);) - if (changed) - this->inval16BitCache(); -} - -void SkColorTable::inval16BitCache() -{ - SkASSERT(f16BitCacheLockCount == 0); - if (f16BitCache) - { - sk_free(f16BitCache); - f16BitCache = NULL; - } -} - -#include "SkColorPriv.h" - -static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count) -{ - while (--count >= 0) - *dst++ = SkPixel32ToPixel16_ToU16(*src++); -} - -const uint16_t* SkColorTable::lock16BitCache() -{ - if (fFlags & kColorsAreOpaque_Flag) - { - if (f16BitCache == NULL) // build the cache - { - f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); - build_16bitcache(f16BitCache, fColors, fCount); - } - } - else // our colors have alpha, so no cache - { - this->inval16BitCache(); - if (f16BitCache) - { - sk_free(f16BitCache); - f16BitCache = NULL; - } - } - - SkDEBUGCODE(f16BitCacheLockCount += 1); - return f16BitCache; -} - -void SkColorTable::setIsOpaque(bool isOpaque) { - if (isOpaque) { - fFlags |= kColorsAreOpaque_Flag; - } else { - fFlags &= ~kColorsAreOpaque_Flag; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) { - f16BitCache = NULL; - SkDEBUGCODE(fColorLockCount = 0;) - SkDEBUGCODE(f16BitCacheLockCount = 0;) - - fFlags = buffer.readUInt(); - fCount = buffer.getArrayCount(); - fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor)); - SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors); -#ifdef SK_DEBUG - SkASSERT((unsigned)fCount <= 256); - SkASSERT(countRead == fCount); -#endif -} - -void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeUInt(fFlags); - buffer.writeColorArray(fColors, fCount); -} diff --git a/gfx/skia/src/core/SkData.cpp b/gfx/skia/src/core/SkData.cpp deleted file mode 100644 index 8c222002ca83..000000000000 --- a/gfx/skia/src/core/SkData.cpp +++ /dev/null @@ -1,323 +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 "SkData.h" -#include "SkFlattenableBuffers.h" - -#if SK_MMAP_SUPPORT - #include - #include - #include - #include -#endif - -SK_DEFINE_INST_COUNT(SkData) - -SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { - fPtr = ptr; - fSize = size; - fReleaseProc = proc; - fReleaseProcContext = context; -} - -SkData::~SkData() { - if (fReleaseProc) { - fReleaseProc(fPtr, fSize, fReleaseProcContext); - } -} - -bool SkData::equals(const SkData* other) const { - if (NULL == other) { - return false; - } - - return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); -} - -size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { - size_t available = fSize; - if (offset >= available || 0 == length) { - return 0; - } - available -= offset; - if (length > available) { - length = available; - } - SkASSERT(length > 0); - - memcpy(buffer, this->bytes() + offset, length); - return length; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkData* SkData::NewEmpty() { - static SkData* gEmptyRef; - if (NULL == gEmptyRef) { - gEmptyRef = new SkData(NULL, 0, NULL, NULL); - } - gEmptyRef->ref(); - return gEmptyRef; -} - -// assumes fPtr was allocated via sk_malloc -static void sk_free_releaseproc(const void* ptr, size_t, void*) { - sk_free((void*)ptr); -} - -SkData* SkData::NewFromMalloc(const void* data, size_t length) { - return new SkData(data, length, sk_free_releaseproc, NULL); -} - -SkData* SkData::NewWithCopy(const void* data, size_t length) { - if (0 == length) { - return SkData::NewEmpty(); - } - - void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc - memcpy(copy, data, length); - return new SkData(copy, length, sk_free_releaseproc, NULL); -} - -SkData* SkData::NewWithProc(const void* data, size_t length, - ReleaseProc proc, void* context) { - return new SkData(data, length, proc, context); -} - -// assumes context is a SkData -static void sk_dataref_releaseproc(const void*, size_t, void* context) { - SkData* src = reinterpret_cast(context); - src->unref(); -} - -SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { - /* - We could, if we wanted/need to, just make a deep copy of src's data, - rather than referencing it. This would duplicate the storage (of the - subset amount) but would possibly allow src to go out of scope sooner. - */ - - size_t available = src->size(); - if (offset >= available || 0 == length) { - return SkData::NewEmpty(); - } - available -= offset; - if (length > available) { - length = available; - } - SkASSERT(length > 0); - - src->ref(); // this will be balanced in sk_dataref_releaseproc - return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, - const_cast(src)); -} - -SkData* SkData::NewWithCString(const char cstr[]) { - size_t size; - if (NULL == cstr) { - cstr = ""; - size = 1; - } else { - size = strlen(cstr) + 1; - } - return NewWithCopy(cstr, size); -} - -#if SK_MMAP_SUPPORT -static void sk_munmap_releaseproc(const void* addr, size_t length, void*) { - munmap(const_cast(addr), length); -} - -SkData* SkData::NewFromMMap(const void* addr, size_t length) { - return SkNEW_ARGS(SkData, (addr, length, sk_munmap_releaseproc, NULL)); -} -#else -SkData* SkData::NewFromMMap(const void* addr, size_t length) { - return NULL; -} -#endif - -/////////////////////////////////////////////////////////////////////////////// - -void SkData::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeByteArray(fPtr, fSize); -} - -SkData::SkData(SkFlattenableReadBuffer& buffer) { - fSize = buffer.getArrayCount(); - fReleaseProcContext = NULL; - - if (fSize > 0) { - fPtr = sk_malloc_throw(fSize); - fReleaseProc = sk_free_releaseproc; - } else { - fPtr = NULL; - fReleaseProc = NULL; - } - - buffer.readByteArray(const_cast(fPtr)); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -#include "SkDataSet.h" -#include "SkFlattenable.h" -#include "SkStream.h" - -static SkData* dupdata(SkData* data) { - if (data) { - data->ref(); - } else { - data = SkData::NewEmpty(); - } - return data; -} - -static SkData* findValue(const char key[], const SkDataSet::Pair array[], int n) { - for (int i = 0; i < n; ++i) { - if (!strcmp(key, array[i].fKey)) { - return array[i].fValue; - } - } - return NULL; -} - -static SkDataSet::Pair* allocatePairStorage(int count, size_t storage) { - size_t size = count * sizeof(SkDataSet::Pair) + storage; - return (SkDataSet::Pair*)sk_malloc_throw(size); -} - -SkDataSet::SkDataSet(const char key[], SkData* value) { - size_t keyLen = strlen(key); - - fCount = 1; - fKeySize = keyLen + 1; - fPairs = allocatePairStorage(1, keyLen + 1); - - fPairs[0].fKey = (char*)(fPairs + 1); - memcpy(const_cast(fPairs[0].fKey), key, keyLen + 1); - - fPairs[0].fValue = dupdata(value); -} - -SkDataSet::SkDataSet(const Pair array[], int count) { - if (count < 1) { - fCount = 0; - fKeySize = 0; - fPairs = NULL; - return; - } - - int i; - size_t keySize = 0; - for (i = 0; i < count; ++i) { - keySize += strlen(array[i].fKey) + 1; - } - - Pair* pairs = fPairs = allocatePairStorage(count, keySize); - char* keyStorage = (char*)(pairs + count); - - keySize = 0; // reset this, so we can compute the size for unique keys - int uniqueCount = 0; - for (int i = 0; i < count; ++i) { - if (!findValue(array[i].fKey, pairs, uniqueCount)) { - size_t len = strlen(array[i].fKey); - memcpy(keyStorage, array[i].fKey, len + 1); - pairs[uniqueCount].fKey = keyStorage; - keyStorage += len + 1; - keySize += len + 1; - - pairs[uniqueCount].fValue = dupdata(array[i].fValue); - uniqueCount += 1; - } - } - fCount = uniqueCount; - fKeySize = keySize; -} - -SkDataSet::~SkDataSet() { - for (int i = 0; i < fCount; ++i) { - fPairs[i].fValue->unref(); - } - sk_free(fPairs); // this also frees the key storage -} - -SkData* SkDataSet::find(const char key[]) const { - return findValue(key, fPairs, fCount); -} - -void SkDataSet::writeToStream(SkWStream* stream) const { - stream->write32(fCount); - if (fCount > 0) { - stream->write32(fKeySize); - // our first key points to all the key storage - stream->write(fPairs[0].fKey, fKeySize); - for (int i = 0; i < fCount; ++i) { - stream->writeData(fPairs[i].fValue); - } - } -} - -void SkDataSet::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeInt(fCount); - if (fCount > 0) { - buffer.writeByteArray(fPairs[0].fKey, fKeySize); - for (int i = 0; i < fCount; ++i) { - buffer.writeFlattenable(fPairs[i].fValue); - } - } -} - -SkDataSet::SkDataSet(SkStream* stream) { - fCount = stream->readU32(); - if (fCount > 0) { - fKeySize = stream->readU32(); - fPairs = allocatePairStorage(fCount, fKeySize); - char* keyStorage = (char*)(fPairs + fCount); - - stream->read(keyStorage, fKeySize); - - for (int i = 0; i < fCount; ++i) { - fPairs[i].fKey = keyStorage; - keyStorage += strlen(keyStorage) + 1; - fPairs[i].fValue = stream->readData(); - } - } else { - fKeySize = 0; - fPairs = NULL; - } -} - -SkDataSet::SkDataSet(SkFlattenableReadBuffer& buffer) { - fCount = buffer.readInt(); - if (fCount > 0) { - fKeySize = buffer.getArrayCount(); - fPairs = allocatePairStorage(fCount, fKeySize); - char* keyStorage = (char*)(fPairs + fCount); - - buffer.readByteArray(keyStorage); - - for (int i = 0; i < fCount; ++i) { - fPairs[i].fKey = keyStorage; - keyStorage += strlen(keyStorage) + 1; - fPairs[i].fValue = buffer.readFlattenableT(); - } - } else { - fKeySize = 0; - fPairs = NULL; - } -} - -SkDataSet* SkDataSet::NewEmpty() { - static SkDataSet* gEmptySet; - if (NULL == gEmptySet) { - gEmptySet = SkNEW_ARGS(SkDataSet, (NULL, 0)); - } - gEmptySet->ref(); - return gEmptySet; -} diff --git a/gfx/skia/src/core/SkDevice.cpp b/gfx/skia/src/core/SkDevice.cpp deleted file mode 100644 index 90d41862deb4..000000000000 --- a/gfx/skia/src/core/SkDevice.cpp +++ /dev/null @@ -1,546 +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 "SkDevice.h" -#include "SkDeviceProperties.h" -#include "SkDraw.h" -#include "SkImageFilter.h" -#include "SkMetaData.h" -#include "SkRasterClip.h" -#include "SkRect.h" -#include "SkShader.h" - -SK_DEFINE_INST_COUNT(SkDevice) - -/////////////////////////////////////////////////////////////////////////////// - -#define CHECK_FOR_NODRAW_ANNOTATION(paint) \ - do { if (paint.isNoDrawAnnotation()) { return; } } while (0) - -/////////////////////////////////////////////////////////////////////////////// - -SkDevice::SkDevice(const SkBitmap& bitmap) - : fBitmap(bitmap), fLeakyProperties(SkDeviceProperties::MakeDefault()) -#ifdef SK_DEBUG - , fAttachedToCanvas(false) -#endif -{ - fOrigin.setZero(); - fMetaData = NULL; -} - -SkDevice::SkDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties) - : fBitmap(bitmap), fLeakyProperties(deviceProperties) -#ifdef SK_DEBUG - , fAttachedToCanvas(false) -#endif -{ - fOrigin.setZero(); - fMetaData = NULL; -} - -SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) - : fLeakyProperties(SkDeviceProperties::MakeDefault()) -#ifdef SK_DEBUG - , fAttachedToCanvas(false) -#endif -{ - fOrigin.setZero(); - fMetaData = NULL; - - fBitmap.setConfig(config, width, height); - fBitmap.allocPixels(); - fBitmap.setIsOpaque(isOpaque); - if (!isOpaque) { - fBitmap.eraseColor(SK_ColorTRANSPARENT); - } -} - -SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque, - const SkDeviceProperties& deviceProperties) - : fLeakyProperties(deviceProperties) -#ifdef SK_DEBUG - , fAttachedToCanvas(false) -#endif -{ - fOrigin.setZero(); - fMetaData = NULL; - - fBitmap.setConfig(config, width, height); - fBitmap.allocPixels(); - fBitmap.setIsOpaque(isOpaque); - if (!isOpaque) { - fBitmap.eraseColor(SK_ColorTRANSPARENT); - } -} - -SkDevice::~SkDevice() { - delete fMetaData; -} - -void SkDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { - SkASSERT(bm.width() == fBitmap.width()); - SkASSERT(bm.height() == fBitmap.height()); - fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config) - fBitmap.lockPixels(); -} - -SkDevice* SkDevice::createCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque) { - return this->onCreateCompatibleDevice(config, width, height, - isOpaque, kGeneral_Usage); -} - -SkDevice* SkDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config, - int width, int height, - bool isOpaque) { - return this->onCreateCompatibleDevice(config, width, height, - isOpaque, kSaveLayer_Usage); -} - -SkDevice* SkDevice::onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque, - Usage usage) { - return SkNEW_ARGS(SkDevice,(config, width, height, isOpaque, fLeakyProperties)); -} - -SkMetaData& SkDevice::getMetaData() { - // metadata users are rare, so we lazily allocate it. If that changes we - // can decide to just make it a field in the device (rather than a ptr) - if (NULL == fMetaData) { - fMetaData = new SkMetaData; - } - return *fMetaData; -} - -void SkDevice::lockPixels() { - if (fBitmap.lockPixelsAreWritable()) { - fBitmap.lockPixels(); - } -} - -void SkDevice::unlockPixels() { - if (fBitmap.lockPixelsAreWritable()) { - fBitmap.unlockPixels(); - } -} - -const SkBitmap& SkDevice::accessBitmap(bool changePixels) { - const SkBitmap& bitmap = this->onAccessBitmap(&fBitmap); - if (changePixels) { - bitmap.notifyPixelsChanged(); - } - return bitmap; -} - -void SkDevice::getGlobalBounds(SkIRect* bounds) const { - if (bounds) { - bounds->setXYWH(fOrigin.x(), fOrigin.y(), - fBitmap.width(), fBitmap.height()); - } -} - -void SkDevice::clear(SkColor color) { - fBitmap.eraseColor(color); -} - -const SkBitmap& SkDevice::onAccessBitmap(SkBitmap* bitmap) {return *bitmap;} - -void SkDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& region, - const SkClipStack& clipStack) { -} - -bool SkDevice::canHandleImageFilter(SkImageFilter*) { - return false; -} - -bool SkDevice::filterImage(SkImageFilter* filter, const SkBitmap& src, - const SkMatrix& ctm, SkBitmap* result, - SkIPoint* offset) { - return false; -} - -bool SkDevice::allowImageFilter(SkImageFilter*) { - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y, - SkCanvas::Config8888 config8888) { - if (SkBitmap::kARGB_8888_Config != bitmap->config() || - NULL != bitmap->getTexture()) { - return false; - } - - const SkBitmap& src = this->accessBitmap(false); - - SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(), - bitmap->height()); - SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height()); - if (!srcRect.intersect(devbounds)) { - return false; - } - - 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; - } - - 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); - } - return result; -} - -#ifdef SK_CPU_LENDIAN - #if 24 == SK_A32_SHIFT && 16 == SK_R32_SHIFT && \ - 8 == SK_G32_SHIFT && 0 == SK_B32_SHIFT - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - SkCanvas::kBGRA_Premul_Config8888; - #elif 24 == SK_A32_SHIFT && 0 == SK_R32_SHIFT && \ - 8 == SK_G32_SHIFT && 16 == SK_B32_SHIFT - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - SkCanvas::kRGBA_Premul_Config8888; - #else - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - (SkCanvas::Config8888) -1; - #endif -#else - #if 0 == SK_A32_SHIFT && 8 == SK_R32_SHIFT && \ - 16 == SK_G32_SHIFT && 24 == SK_B32_SHIFT - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - SkCanvas::kBGRA_Premul_Config8888; - #elif 0 == SK_A32_SHIFT && 24 == SK_R32_SHIFT && \ - 16 == SK_G32_SHIFT && 8 == SK_B32_SHIFT - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - SkCanvas::kRGBA_Premul_Config8888; - #else - const SkCanvas::Config8888 SkDevice::kPMColorAlias = - (SkCanvas::Config8888) -1; - #endif -#endif - -#include - -bool SkDevice::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()))); - - SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), - bitmap.height()); - const SkBitmap& src = this->accessBitmap(false); - - SkBitmap subset; - if (!src.extractSubset(&subset, srcRect)) { - 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); - } - SkAutoLockPixels alp(bitmap); - uint32_t* bmpPixels = reinterpret_cast(bitmap.getPixels()); - SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset); - return true; -} - -void SkDevice::writePixels(const SkBitmap& bitmap, - int x, int y, - SkCanvas::Config8888 config8888) { - if (bitmap.isNull() || bitmap.getTexture()) { - return; - } - 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; - } - - // 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; - } - } - - 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); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { - draw.drawPaint(paint); -} - -void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, - const SkPoint pts[], const SkPaint& paint) { - CHECK_FOR_NODRAW_ANNOTATION(paint); - draw.drawPoints(mode, count, pts, paint); -} - -void SkDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { - CHECK_FOR_NODRAW_ANNOTATION(paint); - draw.drawRect(r, paint); -} - -void SkDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { - CHECK_FOR_NODRAW_ANNOTATION(paint); - - SkPath path; - path.addOval(oval); - // call the VIRTUAL version, so any subclasses who do handle drawPath aren't - // required to override drawOval. - this->drawPath(draw, path, paint, NULL, true); -} - -void SkDevice::drawPath(const SkDraw& draw, const SkPath& path, - const SkPaint& paint, const SkMatrix* prePathMatrix, - bool pathIsMutable) { - CHECK_FOR_NODRAW_ANNOTATION(paint); - draw.drawPath(path, paint, prePathMatrix, pathIsMutable); -} - -void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, - const SkIRect* srcRect, - const SkMatrix& matrix, const SkPaint& paint) { - SkBitmap tmp; // storage if we need a subset of bitmap - const SkBitmap* bitmapPtr = &bitmap; - - if (srcRect) { - if (!bitmap.extractSubset(&tmp, *srcRect)) { - return; // extraction failed - } - bitmapPtr = &tmp; - } - draw.drawBitmap(*bitmapPtr, matrix, paint); -} - -void SkDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, - const SkRect* src, const SkRect& dst, - const SkPaint& paint) { - SkMatrix matrix; - SkRect bitmapBounds, tmpSrc, tmpDst; - SkBitmap tmpBitmap; - - bitmapBounds.isetWH(bitmap.width(), bitmap.height()); - - // Compute matrix from the two rectangles - if (src) { - tmpSrc = *src; - } else { - tmpSrc = bitmapBounds; - } - matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); - - const SkRect* dstPtr = &dst; - const SkBitmap* bitmapPtr = &bitmap; - - // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if - // needed (if the src was clipped). No check needed if src==null. - if (src) { - if (!bitmapBounds.contains(*src)) { - if (!tmpSrc.intersect(bitmapBounds)) { - return; // nothing to draw - } - // recompute dst, based on the smaller tmpSrc - matrix.mapRect(&tmpDst, tmpSrc); - dstPtr = &tmpDst; - } - - // since we may need to clamp to the borders of the src rect within - // the bitmap, we extract a subset. - SkIRect srcIR; - tmpSrc.roundOut(&srcIR); - if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { - return; - } - bitmapPtr = &tmpBitmap; - - // Since we did an extract, we need to adjust the matrix accordingly - SkScalar dx = 0, dy = 0; - if (srcIR.fLeft > 0) { - dx = SkIntToScalar(srcIR.fLeft); - } - if (srcIR.fTop > 0) { - dy = SkIntToScalar(srcIR.fTop); - } - if (dx || dy) { - matrix.preTranslate(dx, dy); - } - - SkRect extractedBitmapBounds; - extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height()); - if (extractedBitmapBounds == tmpSrc) { - // no fractional part in src, we can just call drawBitmap - goto USE_DRAWBITMAP; - } - } else { - USE_DRAWBITMAP: - // We can go faster by just calling drawBitmap, which will concat the - // matrix with the CTM, and try to call drawSprite if it can. If not, - // it will make a shader and call drawRect, as we do below. - this->drawBitmap(draw, *bitmapPtr, NULL, matrix, paint); - return; - } - - // construct a shader, so we can call drawRect with the dst - SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr, - SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode); - if (NULL == s) { - return; - } - s->setLocalMatrix(matrix); - - SkPaint paintWithShader(paint); - paintWithShader.setStyle(SkPaint::kFill_Style); - paintWithShader.setShader(s)->unref(); - - // Call ourself, in case the subclass wanted to share this setup code - // but handle the drawRect code themselves. - this->drawRect(draw, *dstPtr, paintWithShader); -} - -void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint) { - draw.drawSprite(bitmap, x, y, paint); -} - -void SkDevice::drawText(const SkDraw& draw, const void* text, size_t len, - SkScalar x, SkScalar y, const SkPaint& paint) { - draw.drawText((const char*)text, len, x, y, paint); -} - -void SkDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, - const SkScalar xpos[], SkScalar y, - int scalarsPerPos, const SkPaint& paint) { - draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint); -} - -void SkDevice::drawTextOnPath(const SkDraw& draw, const void* text, - size_t len, const SkPath& path, - const SkMatrix* matrix, - const SkPaint& paint) { - draw.drawTextOnPath((const char*)text, len, path, matrix, paint); -} - -#ifdef SK_BUILD_FOR_ANDROID -void SkDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix) { - draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix); -} -#endif - -void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, - int vertexCount, - const SkPoint verts[], const SkPoint textures[], - const SkColor colors[], SkXfermode* xmode, - const uint16_t indices[], int indexCount, - const SkPaint& paint) { - draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode, - indices, indexCount, paint); -} - -void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device, - int x, int y, const SkPaint& paint) { - const SkBitmap& src = device->accessBitmap(false); - draw.drawSprite(src, x, y, paint); -} - -/////////////////////////////////////////////////////////////////////////////// - -bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { - if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { - // we're cool with the paint as is - return false; - } - - if (SkBitmap::kARGB_8888_Config != fBitmap.config() || - paint.getRasterizer() || - paint.getPathEffect() || - paint.isFakeBoldText() || - paint.getStyle() != SkPaint::kFill_Style || - !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { - // turn off lcd - flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag; - flags->fHinting = paint.getHinting(); - return true; - } - // we're cool with the paint as is - return false; -} diff --git a/gfx/skia/src/core/SkFDStream.cpp b/gfx/skia/src/core/SkFDStream.cpp deleted file mode 100644 index ed94229ed1e5..000000000000 --- a/gfx/skia/src/core/SkFDStream.cpp +++ /dev/null @@ -1,104 +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 "SkStream.h" - -#ifdef SK_BUILD_FOR_WIN - -// -1 means isValid() will return false -SkFDStream::SkFDStream(int, bool) : fFD(-1), fCloseWhenDone(false) {} -SkFDStream::~SkFDStream() {} -bool SkFDStream::rewind() { return false; } -size_t SkFDStream::read(void*, size_t) { return 0; } - -#else - -#include - -//#define TRACE_FDSTREAM - -SkFDStream::SkFDStream(int fileDesc, bool closeWhenDone) - : fFD(fileDesc), fCloseWhenDone(closeWhenDone) { -} - -SkFDStream::~SkFDStream() { - if (fFD >= 0 && fCloseWhenDone) { - ::close(fFD); - } -} - -bool SkFDStream::rewind() { - if (fFD >= 0) { - off_t value = ::lseek(fFD, 0, SEEK_SET); -#ifdef TRACE_FDSTREAM - if (value) { - SkDebugf("xxxxxxxxxxxxxx rewind failed %d\n", value); - } -#endif - return value == 0; - } - return false; -} - -size_t SkFDStream::read(void* buffer, size_t size) { - if (fFD >= 0) { - if (buffer == NULL && size == 0) { // request total size - off_t curr = ::lseek(fFD, 0, SEEK_CUR); - if (curr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed 0 CURR\n"); -#endif - return 0; // error - } - off_t size = ::lseek(fFD, 0, SEEK_END); - if (size < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed 0 END\n"); -#endif - size = 0; // error - } - if (::lseek(fFD, curr, SEEK_SET) != curr) { - // can't restore, error -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed %d SET\n", curr); -#endif - return 0; - } - return (size_t) size; - } else if (NULL == buffer) { // skip - off_t oldCurr = ::lseek(fFD, 0, SEEK_CUR); - if (oldCurr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek1 failed %d CUR\n", oldCurr); -#endif - return 0; // error; - } - off_t newCurr = ::lseek(fFD, size, SEEK_CUR); - if (newCurr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek2 failed %d CUR\n", newCurr); -#endif - return 0; // error; - } - // return the actual amount we skipped - return (size_t) (newCurr - oldCurr); - } else { // read - ssize_t actual = ::read(fFD, buffer, size); - // our API can't return an error, so we return 0 - if (actual < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx read failed %d actual %d\n", size, actual); -#endif - actual = 0; - } - return actual; - } - } - return 0; -} - -#endif diff --git a/gfx/skia/src/core/SkFlattenableBuffers.cpp b/gfx/skia/src/core/SkFlattenableBuffers.cpp deleted file mode 100644 index 50a47d5c47c2..000000000000 --- a/gfx/skia/src/core/SkFlattenableBuffers.cpp +++ /dev/null @@ -1,56 +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" - -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); - return proc; -} - -void SkFlattenableReadBuffer::readPaint(SkPaint* paint) { - paint->unflatten(*this); -} - -/////////////////////////////////////////////////////////////////////////////// - -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(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer) { - obj->flatten(buffer); -} diff --git a/gfx/skia/src/core/SkFontHost.cpp b/gfx/skia/src/core/SkFontHost.cpp deleted file mode 100644 index a3df04d79bbe..000000000000 --- a/gfx/skia/src/core/SkFontHost.cpp +++ /dev/null @@ -1,175 +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 "SkFontLCDConfig.h" - -static SkFontLCDConfig::LCDOrientation gLCDOrientation = SkFontLCDConfig::kHorizontal_LCDOrientation; -static SkFontLCDConfig::LCDOrder gLCDOrder = SkFontLCDConfig::kRGB_LCDOrder; - -SkFontLCDConfig::LCDOrientation SkFontLCDConfig::GetSubpixelOrientation() { - return gLCDOrientation; -} - -void SkFontLCDConfig::SetSubpixelOrientation(LCDOrientation orientation) { - gLCDOrientation = orientation; -} - -SkFontLCDConfig::LCDOrder SkFontLCDConfig::GetSubpixelOrder() { - return gLCDOrder; -} - -void SkFontLCDConfig::SetSubpixelOrder(LCDOrder order) { - gLCDOrder = order; -} - -/////////////////////////////////////////////////////////////////////////////// -// Legacy wrappers : remove from SkFontHost when webkit switches to new API - -#include "SkFontHost.h" - -SkFontHost::LCDOrientation SkFontHost::GetSubpixelOrientation() { - return (SkFontHost::LCDOrientation)SkFontLCDConfig::GetSubpixelOrientation(); -} - -void SkFontHost::SetSubpixelOrientation(LCDOrientation orientation) { - SkFontLCDConfig::SetSubpixelOrientation((SkFontLCDConfig::LCDOrientation)orientation); -} - -SkFontHost::LCDOrder SkFontHost::GetSubpixelOrder() { - return (SkFontHost::LCDOrder)SkFontLCDConfig::GetSubpixelOrder(); -} - -void SkFontHost::SetSubpixelOrder(LCDOrder order) { - SkFontLCDConfig::SetSubpixelOrder((SkFontLCDConfig::LCDOrder)order); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -#include "SkFontStyle.h" - -SkFontStyle::SkFontStyle() { - fUnion.fU32 = 0; - fUnion.fR.fWeight = kNormal_Weight; - fUnion.fR.fWidth = kNormal_Width; - fUnion.fR.fSlant = kUpright_Slant; -} - -SkFontStyle::SkFontStyle(int weight, int width, Slant slant) { - fUnion.fU32 = 0; - fUnion.fR.fWeight = SkPin32(weight, kThin_Weight, kBlack_Weight); - fUnion.fR.fWidth = SkPin32(width, kUltraCondensed_Width, kUltaExpanded_Width); - fUnion.fR.fSlant = SkPin32(slant, kUpright_Slant, kItalic_Slant); -} - -#include "SkFontMgr.h" - -class SkEmptyFontStyleSet : public SkFontStyleSet { -public: - virtual int count() SK_OVERRIDE { return 0; } - virtual void getStyle(int, SkFontStyle*, SkString*) SK_OVERRIDE { - SkASSERT(!"SkFontStyleSet::getStyle called on empty set"); - } - virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { - SkASSERT(!"SkFontStyleSet::createTypeface called on empty set"); - return NULL; - } - virtual SkTypeface* matchStyle(const SkFontStyle&) SK_OVERRIDE { - return NULL; - } -}; - -SkFontStyleSet* SkFontStyleSet::CreateEmpty() { - return SkNEW(SkEmptyFontStyleSet); -} - -/////////////////////////////////////////////////////////////////////////////// - -class SkEmptyFontMgr : public SkFontMgr { -protected: - virtual int onCountFamilies() SK_OVERRIDE { - return 0; - } - virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE { - SkASSERT(!"onGetFamilyName called with bad index"); - } - virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE { - SkASSERT(!"onCreateStyleSet called with bad index"); - return NULL; - } - virtual SkFontStyleSet* onMatchFamily(const char[]) SK_OVERRIDE { - return SkFontStyleSet::CreateEmpty(); - } - - virtual SkTypeface* onMatchFamilyStyle(const char[], - const SkFontStyle&) SK_OVERRIDE { - return NULL; - } - virtual SkTypeface* onMatchFaceStyle(const SkTypeface*, - const SkFontStyle&) SK_OVERRIDE { - return NULL; - } - virtual SkTypeface* onCreateFromData(SkData*, int) SK_OVERRIDE { - return NULL; - } - virtual SkTypeface* onCreateFromStream(SkStream*, int) SK_OVERRIDE { - return NULL; - } - virtual SkTypeface* onCreateFromFile(const char[], int) SK_OVERRIDE { - return NULL; - } -}; - -int SkFontMgr::countFamilies() { - return this->onCountFamilies(); -} - -void SkFontMgr::getFamilyName(int index, SkString* familyName) { - this->onGetFamilyName(index, familyName); -} - -SkFontStyleSet* SkFontMgr::createStyleSet(int index) { - return this->onCreateStyleSet(index); -} - -SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) { - return this->onMatchFamily(familyName); -} - -SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[], - const SkFontStyle& fs) { - return this->onMatchFamilyStyle(familyName, fs); -} - -SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face, - const SkFontStyle& fs) { - return this->onMatchFaceStyle(face, fs); -} - -SkTypeface* SkFontMgr::createFromData(SkData* data, int ttcIndex) { - return this->onCreateFromData(data, ttcIndex); -} - -SkTypeface* SkFontMgr::createFromStream(SkStream* stream, int ttcIndex) { - return this->onCreateFromStream(stream, ttcIndex); -} - -SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) { - return this->onCreateFromFile(path, ttcIndex); -} - -SkFontMgr* SkFontMgr::RefDefault() { - static SkFontMgr* gFM; - if (NULL == gFM) { - gFM = SkFontMgr::Factory(); - // we never want to return NULL - if (NULL == gFM) { - gFM = SkNEW(SkEmptyFontMgr); - } - } - return SkRef(gFM); -} diff --git a/gfx/skia/src/core/SkImageFilter.cpp b/gfx/skia/src/core/SkImageFilter.cpp deleted file mode 100644 index 56fb1ae47e35..000000000000 --- a/gfx/skia/src/core/SkImageFilter.cpp +++ /dev/null @@ -1,127 +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. - */ - -#include "SkImageFilter.h" - -#include "SkBitmap.h" -#include "SkFlattenableBuffers.h" -#include "SkRect.h" - -SK_DEFINE_INST_COUNT(SkImageFilter) - -SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs) - : fInputCount(inputCount), fInputs(new SkImageFilter*[inputCount]) { - for (int i = 0; i < inputCount; ++i) { - fInputs[i] = inputs[i]; - SkSafeRef(fInputs[i]); - } -} - -SkImageFilter::SkImageFilter(SkImageFilter* input) - : fInputCount(1), fInputs(new SkImageFilter*[1]) { - fInputs[0] = input; - SkSafeRef(fInputs[0]); -} - -SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2) - : fInputCount(2), fInputs(new SkImageFilter*[2]) { - fInputs[0] = input1; - fInputs[1] = input2; - SkSafeRef(fInputs[0]); - SkSafeRef(fInputs[1]); -} - -SkImageFilter::~SkImageFilter() { - for (int i = 0; i < fInputCount; i++) { - SkSafeUnref(fInputs[i]); - } - delete[] fInputs; -} - -SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer) - : fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) { - for (int i = 0; i < fInputCount; i++) { - if (buffer.readBool()) { - fInputs[i] = static_cast(buffer.readFlattenable()); - } else { - fInputs[i] = NULL; - } - } -} - -void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeInt(fInputCount); - for (int i = 0; i < fInputCount; i++) { - SkImageFilter* input = getInput(i); - buffer.writeBool(input != NULL); - if (input != NULL) { - buffer.writeFlattenable(input); - } - } -} - -SkBitmap SkImageFilter::getInputResult(int index, Proxy* proxy, - const SkBitmap& src, const SkMatrix& ctm, - SkIPoint* loc) { - SkASSERT(index < fInputCount); - SkImageFilter* input = getInput(index); - SkBitmap result; - if (input && input->filterImage(proxy, src, ctm, &result, loc)) { - return result; - } else { - return src; - } -} - - -bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, - const SkMatrix& ctm, - SkBitmap* result, SkIPoint* loc) { - SkASSERT(result); - SkASSERT(loc); - /* - * 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); -} - -bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, - SkIRect* dst) { - SkASSERT(&src); - SkASSERT(dst); - return this->onFilterBounds(src, ctm, dst); -} - -bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, - SkBitmap*, SkIPoint*) { - return false; -} - -bool SkImageFilter::canFilterImageGPU() const { - return false; -} - -bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) { - SkASSERT(false); // Should never be called, since canFilterImageGPU() returned false. - return false; -} - -bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, - SkIRect* dst) { - *dst = src; - return true; -} - -bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*) const { - return false; -} - -bool SkImageFilter::asColorFilter(SkColorFilter**) const { - return false; -} diff --git a/gfx/skia/src/core/SkMallocPixelRef.cpp b/gfx/skia/src/core/SkMallocPixelRef.cpp deleted file mode 100644 index d70098396161..000000000000 --- a/gfx/skia/src/core/SkMallocPixelRef.cpp +++ /dev/null @@ -1,66 +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 "SkMallocPixelRef.h" -#include "SkBitmap.h" -#include "SkFlattenableBuffers.h" - -SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size, - SkColorTable* ctable, bool ownPixels) { - if (NULL == storage) { - SkASSERT(ownPixels); - storage = sk_malloc_throw(size); - } - fStorage = storage; - fSize = size; - fCTable = ctable; - SkSafeRef(ctable); - fOwnPixels = ownPixels; - - this->setPreLocked(fStorage, fCTable); -} - -SkMallocPixelRef::~SkMallocPixelRef() { - SkSafeUnref(fCTable); - if (fOwnPixels) { - sk_free(fStorage); - } -} - -void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) { - *ct = fCTable; - return fStorage; -} - -void SkMallocPixelRef::onUnlockPixels() { - // nothing to do -} - -void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - - buffer.writeByteArray(fStorage, fSize); - buffer.writeBool(fCTable != NULL); - if (fCTable) { - buffer.writeFlattenable(fCTable); - } -} - -SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer, NULL) { - fSize = buffer.getArrayCount(); - fStorage = sk_malloc_throw(fSize); - buffer.readByteArray(fStorage); - if (buffer.readBool()) { - fCTable = buffer.readFlattenableT(); - } else { - fCTable = NULL; - } - fOwnPixels = true; - - this->setPreLocked(fStorage, fCTable); -} diff --git a/gfx/skia/src/core/SkMemory_stdlib.cpp b/gfx/skia/src/core/SkMemory_stdlib.cpp deleted file mode 100644 index fa13e9cb7bc2..000000000000 --- a/gfx/skia/src/core/SkMemory_stdlib.cpp +++ /dev/null @@ -1,267 +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 "SkTypes.h" -#include -#include - -#ifdef SK_DEBUG - #define SK_TAG_BLOCKS - // #define SK_TRACK_ALLOC // enable to see a printf for every alloc/free - // #define SK_CHECK_TAGS // enable to double-check debugging link list -#endif - -#ifdef SK_TAG_BLOCKS - -#include "SkThread.h" - -// size this (as a multiple of 4) so that the total offset to the internal data -// is at least a multiple of 8 (since some clients of our malloc may require -// that. -static const char kBlockHeaderTag[] = { 's', 'k', 'i', 'a', '1', '2', '3', '4' }; -static const char kBlockTrailerTag[] = { 'a', 'i', 'k', 's' }; -#define kByteFill 0xCD -#define kDeleteFill 0xEF - -static SkBaseMutex& get_block_mutex() { - static SkMutex* gBlockMutex; - if (NULL == gBlockMutex) { - gBlockMutex = new SkMutex; - } - return *gBlockMutex; -} - -static struct SkBlockHeader* gHeader; - -struct SkBlockHeader { - SkBlockHeader* fNext; -#ifdef SK_CHECK_TAGS - SkBlockHeader** fTop; // set to verify in debugger that block was alloc'd / freed with same gHeader - SkBlockHeader* fPrevious; // set to see in debugger previous block when corruption happens -#endif - size_t fSize; - char fHeader[sizeof(kBlockHeaderTag)]; - // data goes here. The offset to this point must be a multiple of 8 - char fTrailer[sizeof(kBlockTrailerTag)]; - - void* add(size_t realSize) - { - SkAutoMutexAcquire ac(get_block_mutex()); - InMutexValidate(); - fNext = gHeader; -#ifdef SK_CHECK_TAGS - fTop = &gHeader; - fPrevious = NULL; - if (fNext != NULL) - fNext->fPrevious = this; -#endif - gHeader = this; - fSize = realSize; - memcpy(fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag)); - void* result = fTrailer; - void* trailer = (char*)result + realSize; - memcpy(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag)); - return result; - } - - static void Dump() - { - SkAutoMutexAcquire ac(get_block_mutex()); - InMutexValidate(); - SkBlockHeader* header = gHeader; - int count = 0; - size_t size = 0; - while (header != NULL) { - char scratch[256]; - char* pos = scratch; - size_t size = header->fSize; - int* data = (int*)(void*)header->fTrailer; - pos += sprintf(pos, "%p 0x%08zx (%7zd) ", - data, size, size); - size >>= 2; - size_t ints = size > 4 ? 4 : size; - size_t index; - for (index = 0; index < ints; index++) - pos += sprintf(pos, "0x%08x ", data[index]); - pos += sprintf(pos, " ("); - for (index = 0; index < ints; index++) - pos += sprintf(pos, "%g ", data[index] / 65536.0f); - if (ints > 0) - --pos; - pos += sprintf(pos, ") \""); - size_t chars = size > 16 ? 16 : size; - char* chPtr = (char*) data; - for (index = 0; index < chars; index++) { - char ch = chPtr[index]; - pos += sprintf(pos, "%c", ch >= ' ' && ch < 0x7f ? ch : '?'); - } - pos += sprintf(pos, "\""); - SkDebugf("%s\n", scratch); - count++; - size += header->fSize; - header = header->fNext; - } - SkDebugf("--- count %d size 0x%08x (%zd) ---\n", count, size, size); - } - - void remove() const - { - SkAutoMutexAcquire ac(get_block_mutex()); - SkBlockHeader** findPtr = &gHeader; - do { - SkBlockHeader* find = *findPtr; - SkASSERT(find != NULL); - if (find == this) { - *findPtr = fNext; - break; - } - findPtr = &find->fNext; - } while (true); - InMutexValidate(); - SkASSERT(memcmp(fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag)) == 0); - const char* trailer = fTrailer + fSize; - SkASSERT(memcmp(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag)) == 0); - } - - static void Validate() - { - SkAutoMutexAcquire ac(get_block_mutex()); - InMutexValidate(); - } - -private: - static void InMutexValidate() - { - SkBlockHeader* header = gHeader; - while (header != NULL) { - SkASSERT(memcmp(header->fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag)) == 0); - char* trailer = header->fTrailer + header->fSize; - SkASSERT(memcmp(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag)) == 0); - header = header->fNext; - } - } -}; - -void ValidateHeap(); -void ValidateHeap() -{ - SkBlockHeader::Validate(); -} -#else -void ValidateHeap() {} -#endif - -void sk_throw() -{ - SkDEBUGFAIL("sk_throw"); - abort(); -} - -void sk_out_of_memory(void) -{ - SkDEBUGFAIL("sk_out_of_memory"); - abort(); -} - -void* sk_malloc_throw(size_t size) -{ - return sk_malloc_flags(size, SK_MALLOC_THROW); -} - -void* sk_realloc_throw(void* addr, size_t size) -{ -#ifdef SK_TAG_BLOCKS - ValidateHeap(); - if (addr != NULL) { - SkBlockHeader* header = (SkBlockHeader*) - ((char*)addr - SK_OFFSETOF(SkBlockHeader, fTrailer)); - header->remove(); -#ifdef SK_TRACK_ALLOC - printf("sk_realloc_throw %p oldSize=%zd\n", addr, header->fSize); -#endif - addr = header; - } - size_t realSize = size; - if (size) - size += sizeof(SkBlockHeader); -#endif - - void* p = realloc(addr, size); - if (size == 0) - { - ValidateHeap(); - return p; - } - - if (p == NULL) - sk_throw(); -#ifdef SK_TAG_BLOCKS - else - { - SkBlockHeader* header = (SkBlockHeader*) p; - p = header->add(realSize); -#ifdef SK_TRACK_ALLOC - printf("sk_realloc_throw %p size=%zd\n", p, realSize); -#endif - } -#endif - ValidateHeap(); - return p; -} - -void sk_free(void* p) -{ - if (p) - { - ValidateHeap(); -#ifdef SK_TAG_BLOCKS - SkBlockHeader* header = (SkBlockHeader*) - ((char*)p - SK_OFFSETOF(SkBlockHeader, fTrailer)); - header->remove(); -#ifdef SK_TRACK_ALLOC - printf("sk_free %p size=%zd\n", p, header->fSize); -#endif - size_t size = header->fSize + sizeof(SkBlockHeader); - memset(header, kDeleteFill, size); - p = header; -#endif - ValidateHeap(); - free(p); - ValidateHeap(); - } -} - -void* sk_malloc_flags(size_t size, unsigned flags) -{ - ValidateHeap(); -#ifdef SK_TAG_BLOCKS - size_t realSize = size; - size += sizeof(SkBlockHeader); -#endif - - void* p = malloc(size); - if (p == NULL) - { - if (flags & SK_MALLOC_THROW) - sk_throw(); - } -#ifdef SK_TAG_BLOCKS - else - { - SkBlockHeader* header = (SkBlockHeader*) p; - p = header->add(realSize); - memset(p, kByteFill, realSize); -#ifdef SK_TRACK_ALLOC - printf("sk_malloc_flags %p size=%zd\n", p, realSize); -#endif - } -#endif - ValidateHeap(); - return p; -} diff --git a/gfx/skia/src/core/SkOrderedReadBuffer.cpp b/gfx/skia/src/core/SkOrderedReadBuffer.cpp deleted file mode 100644 index 2c83ce0ac56d..000000000000 --- a/gfx/skia/src/core/SkOrderedReadBuffer.cpp +++ /dev/null @@ -1,256 +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 "SkBitmap.h" -#include "SkOrderedReadBuffer.h" -#include "SkStream.h" -#include "SkTypeface.h" - -SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() { - fMemoryPtr = NULL; - - fBitmapStorage = NULL; - fTFArray = NULL; - fTFCount = 0; - - fFactoryTDArray = NULL; - fFactoryArray = NULL; - fFactoryCount = 0; - fBitmapDecoder = NULL; -} - -SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() { - fReader.setMemory(data, size); - fMemoryPtr = NULL; - - fBitmapStorage = NULL; - fTFArray = NULL; - fTFCount = 0; - - fFactoryTDArray = NULL; - fFactoryArray = NULL; - fFactoryCount = 0; - fBitmapDecoder = NULL; -} - -SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) { - const size_t length = stream->getLength(); - fMemoryPtr = sk_malloc_throw(length); - stream->read(fMemoryPtr, length); - fReader.setMemory(fMemoryPtr, length); - - fBitmapStorage = NULL; - fTFArray = NULL; - fTFCount = 0; - - fFactoryTDArray = NULL; - fFactoryArray = NULL; - fFactoryCount = 0; - fBitmapDecoder = NULL; -} - -SkOrderedReadBuffer::~SkOrderedReadBuffer() { - sk_free(fMemoryPtr); - SkSafeUnref(fBitmapStorage); -} - -bool SkOrderedReadBuffer::readBool() { - return fReader.readBool(); -} - -SkColor SkOrderedReadBuffer::readColor() { - return fReader.readInt(); -} - -SkFixed SkOrderedReadBuffer::readFixed() { - return fReader.readS32(); -} - -int32_t SkOrderedReadBuffer::readInt() { - return fReader.readInt(); -} - -SkScalar SkOrderedReadBuffer::readScalar() { - return fReader.readScalar(); -} - -uint32_t SkOrderedReadBuffer::readUInt() { - return fReader.readU32(); -} - -int32_t SkOrderedReadBuffer::read32() { - return fReader.readInt(); -} - -char* SkOrderedReadBuffer::readString() { - const char* string = fReader.readString(); - const size_t length = strlen(string); - char* value = (char*)sk_malloc_throw(length + 1); - strcpy(value, string); - return value; -} - -void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) { - SkDEBUGCODE(int32_t encodingType = ) fReader.readInt(); - SkASSERT(encodingType == encoding); - *length = fReader.readInt(); - void* data = sk_malloc_throw(*length); - memcpy(data, fReader.skip(SkAlign4(*length)), *length); - return data; -} - -void SkOrderedReadBuffer::readPoint(SkPoint* point) { - point->fX = fReader.readScalar(); - point->fY = fReader.readScalar(); -} - -void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) { - fReader.readMatrix(matrix); -} - -void SkOrderedReadBuffer::readIRect(SkIRect* rect) { - memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect)); -} - -void SkOrderedReadBuffer::readRect(SkRect* rect) { - memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect)); -} - -void SkOrderedReadBuffer::readRegion(SkRegion* region) { - fReader.readRegion(region); -} - -void SkOrderedReadBuffer::readPath(SkPath* path) { - fReader.readPath(path); -} - -uint32_t SkOrderedReadBuffer::readByteArray(void* value) { - const uint32_t length = fReader.readU32(); - memcpy(value, fReader.skip(SkAlign4(length)), length); - return length; -} - -uint32_t SkOrderedReadBuffer::readColorArray(SkColor* colors) { - const uint32_t count = fReader.readU32(); - const uint32_t byteLength = count * sizeof(SkColor); - memcpy(colors, fReader.skip(SkAlign4(byteLength)), byteLength); - return count; -} - -uint32_t SkOrderedReadBuffer::readIntArray(int32_t* values) { - const uint32_t count = fReader.readU32(); - const uint32_t byteLength = count * sizeof(int32_t); - memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength); - return count; -} - -uint32_t SkOrderedReadBuffer::readPointArray(SkPoint* points) { - const uint32_t count = fReader.readU32(); - const uint32_t byteLength = count * sizeof(SkPoint); - memcpy(points, fReader.skip(SkAlign4(byteLength)), byteLength); - return count; -} - -uint32_t SkOrderedReadBuffer::readScalarArray(SkScalar* values) { - const uint32_t count = fReader.readU32(); - const uint32_t byteLength = count * sizeof(SkScalar); - memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength); - return count; -} - -uint32_t SkOrderedReadBuffer::getArrayCount() { - return *(uint32_t*)fReader.peek(); -} - -void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) { - const size_t length = this->readUInt(); - if (length > 0) { - // Bitmap was encoded. - const void* data = this->skip(length); - const int width = this->readInt(); - const int height = this->readInt(); - if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) { - SkASSERT(bitmap->width() == width && bitmap->height() == height); - } else { - // This bitmap was encoded when written, but we are unable to decode, possibly due to - // not having a decoder. Use a placeholder bitmap. - SkDebugf("Could not decode bitmap. Resulting bitmap will be red.\n"); - bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap->allocPixels(); - bitmap->eraseColor(SK_ColorRED); - } - } else { - if (fBitmapStorage) { - const uint32_t index = fReader.readU32(); - fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap) - *bitmap = *fBitmapStorage->getBitmap(index); - fBitmapStorage->releaseRef(index); - } else { - bitmap->unflatten(*this); - } - } -} - -SkTypeface* SkOrderedReadBuffer::readTypeface() { - - uint32_t index = fReader.readU32(); - if (0 == index || index > (unsigned)fTFCount) { - if (index) { - SkDebugf("====== typeface index %d\n", index); - } - return NULL; - } else { - SkASSERT(fTFArray); - return fTFArray[index - 1]; - } -} - -SkFlattenable* SkOrderedReadBuffer::readFlattenable() { - SkFlattenable::Factory factory = NULL; - - if (fFactoryCount > 0) { - int32_t index = fReader.readU32(); - if (0 == index) { - return NULL; // writer failed to give us the flattenable - } - index -= 1; // we stored the index-base-1 - SkASSERT(index < fFactoryCount); - factory = fFactoryArray[index]; - } else if (fFactoryTDArray) { - int32_t index = fReader.readU32(); - if (0 == index) { - return NULL; // writer failed to give us the flattenable - } - index -= 1; // we stored the index-base-1 - factory = (*fFactoryTDArray)[index]; - } else { - factory = (SkFlattenable::Factory)readFunctionPtr(); - if (NULL == factory) { - return NULL; // writer failed to give us the flattenable - } - } - - // if we get here, factory may still be null, but if that is the case, the - // failure was ours, not the writer. - SkFlattenable* obj = NULL; - uint32_t sizeRecorded = fReader.readU32(); - if (factory) { - uint32_t offset = fReader.offset(); - obj = (*factory)(*this); - // check that we read the amount we expected - uint32_t sizeRead = fReader.offset() - offset; - if (sizeRecorded != sizeRead) { - // we could try to fix up the offset... - sk_throw(); - } - } else { - // we must skip the remaining data - fReader.skip(sizeRecorded); - } - return obj; -} diff --git a/gfx/skia/src/core/SkOrderedReadBuffer.h b/gfx/skia/src/core/SkOrderedReadBuffer.h deleted file mode 100644 index c609ec8be267..000000000000 --- a/gfx/skia/src/core/SkOrderedReadBuffer.h +++ /dev/null @@ -1,128 +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 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; - -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 char* readString() SK_OVERRIDE; - virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE; - - // common data structures - virtual SkFlattenable* readFlattenable() 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 uint32_t readByteArray(void* value) SK_OVERRIDE; - virtual uint32_t readColorArray(SkColor* colors) SK_OVERRIDE; - virtual uint32_t readIntArray(int32_t* values) SK_OVERRIDE; - virtual uint32_t readPointArray(SkPoint* points) SK_OVERRIDE; - virtual uint32_t readScalarArray(SkScalar* values) 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* 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: - SkReader32 fReader; - void* fMemoryPtr; - - SkBitmapHeapReader* fBitmapStorage; - SkTypeface** fTFArray; - int fTFCount; - - SkTDArray* fFactoryTDArray; - SkFlattenable::Factory* fFactoryArray; - int fFactoryCount; - - SkPicture::InstallPixelRefProc fBitmapDecoder; - - typedef SkFlattenableReadBuffer INHERITED; -}; - -#endif // SkOrderedReadBuffer_DEFINED diff --git a/gfx/skia/src/core/SkPathRef.h b/gfx/skia/src/core/SkPathRef.h deleted file mode 100644 index 5f85b7b896ad..000000000000 --- a/gfx/skia/src/core/SkPathRef.h +++ /dev/null @@ -1,606 +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 SkPathRef_DEFINED -#define SkPathRef_DEFINED - -#include "SkRefCnt.h" -#include // ptrdiff_t - -// When we're ready to break the picture format. Changes: -// * Write genID. -// * SkPathRef read/write counts (which will change the field order) -// * SkPathRef reads/writes verbs backwards. -#define NEW_PICTURE_FORMAT 0 - -/** - * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods - * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an - * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs - * copy-on-write if the SkPathRef is shared by multipls SkPaths. The caller passes the Editor's - * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef after the editor's - * constructor returns. - * - * The points and verbs are stored in a single allocation. The points are at the begining of the - * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points - * and verbs both grow into the middle of the allocation until the meet. To access verb i in the - * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first - * logical verb or the last verb in memory). - */ - -class SkPathRef; - -// This path ref should never be deleted once it is created. It should not be global but was made -// so for checks when SK_DEBUG_PATH_REF is enabled. It we be re-hidden when the debugging code is -// reverted. -SkPathRef* gEmptyPathRef; - -// Temporary hackery to try to nail down http://code.google.com/p/chromium/issues/detail?id=148637 -#if SK_DEBUG_PATH_REF - #define PR_CONTAINER SkPath::PathRefDebugRef - #define SkDEBUGCODE_X(code) code - #define SkASSERT_X(cond) SK_DEBUGBREAK(cond) - // We put the mutex in a factory function to protect against static-initializion order - // fiasco when SkPaths are created before main(). - static SkMutex* owners_mutex() { - static SkMutex* gOwnersMutex; - if (!gOwnersMutex) { - gOwnersMutex = new SkMutex(); // leak! - } - return gOwnersMutex; - } - // We have a static initializer that calls owners_mutex before main() so that - // hopefully that we only wind up with one mutex (assuming no threads created - // before static initialization is finished.) - static const SkMutex* gOwnersMutexForce = owners_mutex(); -#else - #define PR_CONTAINER SkAutoTUnref - #define SkDEBUGCODE_X(code) SkDEBUGCODE(code) - #define SkASSERT_X(cond) SkASSERT(cond) -#endif - -class SkPathRef : public ::SkRefCnt { -public: - SK_DECLARE_INST_COUNT(SkPathRef); - - class Editor { - public: - Editor(PR_CONTAINER* pathRef, - int incReserveVerbs = 0, - int incReservePoints = 0) { - if (pathRef->get()->getRefCnt() > 1) { - SkPathRef* copy = SkNEW(SkPathRef); - copy->copy(*pathRef->get(), incReserveVerbs, incReservePoints); - pathRef->reset(copy); - } else { - (*pathRef)->incReserve(incReserveVerbs, incReservePoints); - } - fPathRef = pathRef->get(); - fPathRef->fGenerationID = 0; - SkDEBUGCODE_X(sk_atomic_inc(&fPathRef->fEditorsAttached);) - } - - ~Editor() { SkDEBUGCODE_X(sk_atomic_dec(&fPathRef->fEditorsAttached);) } - - /** - * Returns the array of points. - */ - SkPoint* points() { return fPathRef->fPoints; } - - /** - * Gets the ith point. Shortcut for this->points() + i - */ - SkPoint* atPoint(int i) { - SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); - return this->points() + i; - }; - - /** - * Adds the verb and allocates space for the number of points indicated by the verb. The - * return value is a pointer to where the points for the verb should be written. - */ - SkPoint* growForVerb(SkPath::Verb verb) { - fPathRef->validate(); - return fPathRef->growForVerb(verb); - } - - /** - * Allocates space for additional verbs and points and returns pointers to the new verbs and - * points. verbs will point one beyond the first new verb (index it using [~]). pts points - * at the first new point (indexed normally []). - */ - void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) { - SkASSERT(NULL != verbs); - SkASSERT(NULL != pts); - fPathRef->validate(); - int oldVerbCnt = fPathRef->fVerbCnt; - int oldPointCnt = fPathRef->fPointCnt; - SkASSERT(verbs && pts); - fPathRef->grow(newVerbs, newPts); - *verbs = fPathRef->fVerbs - oldVerbCnt; - *pts = fPathRef->fPoints + oldPointCnt; - fPathRef->validate(); - } - - /** - * Resets the path ref to a new verb and point count. The new verbs and points are - * uninitialized. - */ - void resetToSize(int newVerbCnt, int newPointCnt) { - fPathRef->resetToSize(newVerbCnt, newPointCnt); - } - /** - * Gets the path ref that is wrapped in the Editor. - */ - SkPathRef* pathRef() { return fPathRef; } - - private: - SkPathRef* fPathRef; - }; - -public: -#if SK_DEBUG_PATH_REF - void addOwner(SkPath* owner) { - SkAutoMutexAcquire ac(owners_mutex()); - for (int i = 0; i < fOwners.count(); ++i) { - SkASSERT_X(fOwners[i] != owner); - } - *fOwners.append() = owner; - SkASSERT_X((this->getRefCnt() == fOwners.count()) || - (this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1)); - } - - void removeOwner(SkPath* owner) { - SkAutoMutexAcquire ac(owners_mutex()); - SkASSERT_X((this->getRefCnt() == fOwners.count()) || - (this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1)); - bool found = false; - for (int i = 0; !found && i < fOwners.count(); ++i) { - found = (owner == fOwners[i]); - if (found) { - fOwners.remove(i); - } - } - SkASSERT_X(found); - } -#endif - - /** - * Gets a path ref with no verbs or points. - */ - static SkPathRef* CreateEmpty() { - if (!gEmptyPathRef) { - gEmptyPathRef = SkNEW(SkPathRef); // leak! - } - return SkRef(gEmptyPathRef); - } - - /** - * Transforms a path ref by a matrix, allocating a new one only if necessary. - */ - static void CreateTransformedCopy(PR_CONTAINER* dst, - const SkPathRef& src, - const SkMatrix& matrix) { - src.validate(); - if (matrix.isIdentity()) { - if (dst->get() != &src) { - src.ref(); - dst->reset(const_cast(&src)); - (*dst)->validate(); - } - return; - } - int32_t rcnt = dst->get()->getRefCnt(); - if (&src == dst->get() && 1 == rcnt) { - matrix.mapPoints((*dst)->fPoints, (*dst)->fPointCnt); - return; - } else if (rcnt > 1) { - dst->reset(SkNEW(SkPathRef)); - } - (*dst)->resetToSize(src.fVerbCnt, src.fPointCnt); - memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), src.fVerbCnt * sizeof(uint8_t)); - matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt); - (*dst)->validate(); - } - -#if NEW_PICTURE_FORMAT - static SkPathRef* CreateFromBuffer(SkRBuffer* buffer) { - SkPathRef* ref = SkNEW(SkPathRef); - ref->fGenerationID = buffer->readU32(); - int32_t verbCount = buffer->readS32(); - int32_t pointCount = buffer->readS32(); - ref->resetToSize(verbCount, pointCount); - - SkASSERT(verbCount == ref->countVerbs()); - SkASSERT(pointCount == ref->countPoints()); - buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t)); - buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)); - return ref; - } -#else - static SkPathRef* CreateFromBuffer(int verbCount, int pointCount, SkRBuffer* buffer) { - SkPathRef* ref = SkNEW(SkPathRef); - - ref->resetToSize(verbCount, pointCount); - SkASSERT(verbCount == ref->countVerbs()); - SkASSERT(pointCount == ref->countPoints()); - buffer->read(ref->fPoints, pointCount * sizeof(SkPoint)); - for (int i = 0; i < verbCount; ++i) { - ref->fVerbs[~i] = buffer->readU8(); - } - return ref; - } -#endif - - /** - * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be - * repopulated with approximately the same number of verbs and points. A new path ref is created - * only if necessary. - */ - static void Rewind(PR_CONTAINER* pathRef) { - if (1 == (*pathRef)->getRefCnt()) { - (*pathRef)->validate(); - (*pathRef)->fVerbCnt = 0; - (*pathRef)->fPointCnt = 0; - (*pathRef)->fFreeSpace = (*pathRef)->currSize(); - (*pathRef)->fGenerationID = 0; - (*pathRef)->validate(); - } else { - int oldVCnt = (*pathRef)->countVerbs(); - int oldPCnt = (*pathRef)->countPoints(); - pathRef->reset(SkNEW(SkPathRef)); - (*pathRef)->resetToSize(0, 0, oldVCnt, oldPCnt); - } - } - - virtual ~SkPathRef() { - SkASSERT_X(this != gEmptyPathRef); -#if SK_DEBUG_PATH_REF - SkASSERT_X(!fOwners.count()); -#endif - - this->validate(); - sk_free(fPoints); - - SkDEBUGCODE_X(fPoints = NULL;) - SkDEBUGCODE_X(fVerbs = NULL;) - SkDEBUGCODE_X(fVerbCnt = 0x9999999;) - SkDEBUGCODE_X(fPointCnt = 0xAAAAAAA;) - SkDEBUGCODE_X(fPointCnt = 0xBBBBBBB;) - SkDEBUGCODE_X(fGenerationID = 0xEEEEEEEE;) - SkDEBUGCODE_X(fEditorsAttached = 0x7777777;) - } - - int countPoints() const { this->validate(); return fPointCnt; } - int countVerbs() const { this->validate(); return fVerbCnt; } - - /** - * Returns a pointer one beyond the first logical verb (last verb in memory order). - */ - const uint8_t* verbs() const { this->validate(); return fVerbs; } - - /** - * Returns a const pointer to the first verb in memory (which is the last logical verb). - */ - const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; } - - /** - * Returns a const pointer to the first point. - */ - const SkPoint* points() const { this->validate(); return fPoints; } - - /** - * Shortcut for this->points() + this->countPoints() - */ - const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); } - - /** - * Convenience methods for getting to a verb or point by index. - */ - uint8_t atVerb(int index) { - SkASSERT((unsigned) index < (unsigned) fVerbCnt); - return this->verbs()[~index]; - } - const SkPoint& atPoint(int index) const { - SkASSERT((unsigned) index < (unsigned) fPointCnt); - return this->points()[index]; - } - - bool operator== (const SkPathRef& ref) const { - this->validate(); - ref.validate(); - bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID; -#ifdef SK_RELEASE - if (genIDMatch) { - return true; - } -#endif - if (fPointCnt != ref.fPointCnt || - fVerbCnt != ref.fVerbCnt) { - SkASSERT(!genIDMatch); - return false; - } - if (0 != memcmp(this->verbsMemBegin(), - ref.verbsMemBegin(), - ref.fVerbCnt * sizeof(uint8_t))) { - SkASSERT(!genIDMatch); - return false; - } - if (0 != memcmp(this->points(), - ref.points(), - ref.fPointCnt * sizeof(SkPoint))) { - SkASSERT(!genIDMatch); - return false; - } - // We've done the work to determine that these are equal. If either has a zero genID, copy - // the other's. If both are 0 then genID() will compute the next ID. - if (0 == fGenerationID) { - fGenerationID = ref.genID(); - } else if (0 == ref.fGenerationID) { - ref.fGenerationID = this->genID(); - } - return true; - } - - /** - * Writes the path points and verbs to a buffer. - */ -#if NEW_PICTURE_FORMAT - void writeToBuffer(SkWBuffer* buffer) { - this->validate(); - SkDEBUGCODE_X(size_t beforePos = buffer->pos();) - - // TODO: write gen ID here. Problem: We don't know if we're cross process or not from - // SkWBuffer. Until this is fixed we write 0. - buffer->write32(0); - buffer->write32(this->fVerbCnt); - buffer->write32(this->fPointCnt); - buffer->write(this->verbsMemBegin(), fVerbCnt * sizeof(uint8_t)); - buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); - - SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize()); - } - - /** - * Gets the number of bytes that would be written in writeBuffer() - */ - uint32_t writeSize() { - return 3 * sizeof(uint32_t) + fVerbCnt * sizeof(uint8_t) + fPointCnt * sizeof(SkPoint); - } -#else - void writeToBuffer(SkWBuffer* buffer) { - this->validate(); - buffer->write(fPoints, fPointCnt * sizeof(SkPoint)); - for (int i = 0; i < fVerbCnt; ++i) { - buffer->write8(fVerbs[~i]); - } - } -#endif - -private: - SkPathRef() { - fPointCnt = 0; - fVerbCnt = 0; - fVerbs = NULL; - fPoints = NULL; - fFreeSpace = 0; - fGenerationID = kEmptyGenID; - SkDEBUGCODE_X(fEditorsAttached = 0;) - this->validate(); - } - - void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints) { - this->validate(); - this->resetToSize(ref.fVerbCnt, ref.fPointCnt, - additionalReserveVerbs, additionalReservePoints); - memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(uint8_t)); - memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint)); - // We could call genID() here to force a real ID (instead of 0). However, if we're making - // a copy then presumably we intend to make a modification immediately afterwards. - fGenerationID = ref.fGenerationID; - this->validate(); - } - - /** Makes additional room but does not change the counts or change the genID */ - void incReserve(int additionalVerbs, int additionalPoints) { - this->validate(); - size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint); - this->makeSpace(space); - this->validate(); - } - - /** Resets the path ref with verbCount verbs and pointCount points, all unitialized. Also - * allocates space for reserveVerb additional verbs and reservePoints additional points.*/ - void resetToSize(int verbCount, int pointCount, int reserveVerbs = 0, int reservePoints = 0) { - this->validate(); - fGenerationID = 0; - - size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount; - size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints; - size_t minSize = newSize + newReserve; - - ptrdiff_t sizeDelta = this->currSize() - minSize; - - if (sizeDelta < 0 || static_cast(sizeDelta) >= 3 * minSize) { - sk_free(fPoints); - fPoints = NULL; - fVerbs = NULL; - fFreeSpace = 0; - fVerbCnt = 0; - fPointCnt = 0; - this->makeSpace(minSize); - fVerbCnt = verbCount; - fPointCnt = pointCount; - fFreeSpace -= newSize; - } else { - fPointCnt = pointCount; - fVerbCnt = verbCount; - fFreeSpace = this->currSize() - minSize; - } - this->validate(); - } - - /** - * Increases the verb count by newVerbs and the point count be newPoints. New verbs and points - * are uninitialized. - */ - void grow(int newVerbs, int newPoints) { - this->validate(); - size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint); - this->makeSpace(space); - fVerbCnt += newVerbs; - fPointCnt += newPoints; - fFreeSpace -= space; - this->validate(); - } - - /** - * Increases the verb count 1, records the new verb, and creates room for the requisite number - * of additional points. A pointer to the first point is returned. Any new points are - * uninitialized. - */ - SkPoint* growForVerb(SkPath::Verb verb) { - this->validate(); - int pCnt; - switch (verb) { - case SkPath::kMove_Verb: - pCnt = 1; - break; - case SkPath::kLine_Verb: - pCnt = 1; - break; - case SkPath::kQuad_Verb: - pCnt = 2; - break; - case SkPath::kCubic_Verb: - pCnt = 3; - break; - default: - pCnt = 0; - } - size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint); - this->makeSpace(space); - this->fVerbs[~fVerbCnt] = verb; - SkPoint* ret = fPoints + fPointCnt; - fVerbCnt += 1; - fPointCnt += pCnt; - fFreeSpace -= space; - this->validate(); - return ret; - } - - /** - * Ensures that the free space available in the path ref is >= size. The verb and point counts - * are not changed. - */ - void makeSpace(size_t size) { - this->validate(); - ptrdiff_t growSize = size - fFreeSpace; - if (growSize <= 0) { - return; - } - size_t oldSize = this->currSize(); - // round to next multiple of 8 bytes - growSize = (growSize + 7) & ~static_cast(7); - // we always at least double the allocation - if (static_cast(growSize) < oldSize) { - growSize = oldSize; - } - if (growSize < kMinSize) { - growSize = kMinSize; - } - size_t newSize = oldSize + growSize; - // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO: - // encapsulate this. - fPoints = reinterpret_cast(sk_realloc_throw(fPoints, newSize)); - size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); - void* newVerbsDst = reinterpret_cast( - reinterpret_cast(fPoints) + newSize - oldVerbSize); - void* oldVerbsSrc = reinterpret_cast( - reinterpret_cast(fPoints) + oldSize - oldVerbSize); - memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); - fVerbs = reinterpret_cast(reinterpret_cast(fPoints) + newSize); - fFreeSpace += growSize; - this->validate(); - } - - /** - * Private, non-const-ptr version of the public function verbsMemBegin(). - */ - uint8_t* verbsMemWritable() { - this->validate(); - return fVerbs - fVerbCnt; - } - - /** - * Gets the total amount of space allocated for verbs, points, and reserve. - */ - size_t currSize() const { - return reinterpret_cast(fVerbs) - reinterpret_cast(fPoints); - } - - /** - * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the - * same ID then they have the same verbs and points. However, two path refs may have the same - * contents but different genIDs. Zero is reserved and means an ID has not yet been determined - * for the path ref. - */ - int32_t genID() const { - SkASSERT_X(!fEditorsAttached); - if (!fGenerationID) { - if (0 == fPointCnt && 0 == fVerbCnt) { - fGenerationID = kEmptyGenID; - } else { - static int32_t gPathRefGenerationID; - // do a loop in case our global wraps around, as we never want to return a 0 or the - // empty ID - do { - fGenerationID = sk_atomic_inc(&gPathRefGenerationID) + 1; - } while (fGenerationID <= kEmptyGenID); - } - } - return fGenerationID; - } - - void validate() const { - SkASSERT(static_cast(fFreeSpace) >= 0); - SkASSERT(reinterpret_cast(fVerbs) - reinterpret_cast(fPoints) >= 0); - SkASSERT((NULL == fPoints) == (NULL == fVerbs)); - SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); - SkASSERT(!(NULL == fPoints && 0 != fFreeSpace)); - SkASSERT(!(NULL == fPoints && fPointCnt)); - SkASSERT(!(NULL == fVerbs && fVerbCnt)); - SkASSERT(this->currSize() == - fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt); - } - - enum { - kMinSize = 256, - }; - - SkPoint* fPoints; // points to begining of the allocation - uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards) - int fVerbCnt; - int fPointCnt; - size_t fFreeSpace; // redundant but saves computation - enum { - kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs. - }; - mutable int32_t fGenerationID; - SkDEBUGCODE_X(int32_t fEditorsAttached;) // assert that only one editor in use at any time. - -#if SK_DEBUG_PATH_REF - SkTDArray fOwners; -#endif - - typedef SkRefCnt INHERITED; -}; - -SK_DEFINE_INST_COUNT(SkPathRef); - -#endif diff --git a/gfx/skia/src/core/SkPictureFlat.h b/gfx/skia/src/core/SkPictureFlat.h deleted file mode 100644 index b0446bb93ed2..000000000000 --- a/gfx/skia/src/core/SkPictureFlat.h +++ /dev/null @@ -1,718 +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 SkPictureFlat_DEFINED -#define SkPictureFlat_DEFINED - -//#define SK_DEBUG_SIZE - -#include "SkChunkAlloc.h" -#include "SkBitmap.h" -#include "SkBitmapHeap.h" -#include "SkOrderedReadBuffer.h" -#include "SkOrderedWriteBuffer.h" -#include "SkPicture.h" -#include "SkPtrRecorder.h" -#include "SkMatrix.h" -#include "SkPaint.h" -#include "SkPath.h" -#include "SkRegion.h" -#include "SkTRefArray.h" -#include "SkTSearch.h" - -enum DrawType { - UNUSED, - CLIP_PATH, - CLIP_REGION, - CLIP_RECT, - CLIP_RRECT, - CONCAT, - DRAW_BITMAP, - DRAW_BITMAP_MATRIX, - DRAW_BITMAP_NINE, - DRAW_BITMAP_RECT_TO_RECT, - DRAW_CLEAR, - DRAW_DATA, - DRAW_OVAL, - DRAW_PAINT, - DRAW_PATH, - DRAW_PICTURE, - DRAW_POINTS, - DRAW_POS_TEXT, - DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT - DRAW_POS_TEXT_H, - DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H - DRAW_RECT, - DRAW_RRECT, - DRAW_SPRITE, - DRAW_TEXT, - DRAW_TEXT_ON_PATH, - DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT - DRAW_VERTICES, - RESTORE, - ROTATE, - SAVE, - SAVE_LAYER, - SCALE, - SET_MATRIX, - SKEW, - TRANSLATE, - NOOP, - - LAST_DRAWTYPE_ENUM = NOOP -}; - -// In the 'match' method, this constant will match any flavor of DRAW_BITMAP* -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 -}; - -/////////////////////////////////////////////////////////////////////////////// -// clipparams are packed in 5 bits -// doAA:1 | regionOp:4 - -static inline uint32_t ClipParams_pack(SkRegion::Op op, bool doAA) { - unsigned doAABit = doAA ? 1 : 0; - return (doAABit << 4) | op; -} - -static inline SkRegion::Op ClipParams_unpackRegionOp(uint32_t packed) { - return (SkRegion::Op)(packed & 0xF); -} - -static inline bool ClipParams_unpackDoAA(uint32_t packed) { - return SkToBool((packed >> 4) & 1); -} - -/////////////////////////////////////////////////////////////////////////////// - -class SkTypefacePlayback { -public: - SkTypefacePlayback(); - virtual ~SkTypefacePlayback(); - - int count() const { return fCount; } - - void reset(const SkRefCntSet*); - - void setCount(int count); - SkRefCnt* set(int index, SkRefCnt*); - - void setupBuffer(SkOrderedReadBuffer& buffer) const { - buffer.setTypefaceArray((SkTypeface**)fArray, fCount); - } - -protected: - int fCount; - SkRefCnt** fArray; -}; - -class SkFactoryPlayback { -public: - SkFactoryPlayback(int count) : fCount(count) { - fArray = SkNEW_ARRAY(SkFlattenable::Factory, count); - } - - ~SkFactoryPlayback() { - SkDELETE_ARRAY(fArray); - } - - SkFlattenable::Factory* base() const { return fArray; } - - void setupBuffer(SkOrderedReadBuffer& buffer) const { - buffer.setFactoryPlayback(fArray, fCount); - } - -private: - int fCount; - SkFlattenable::Factory* fArray; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// -// The following templated classes provide an efficient way to store and compare -// objects that have been flattened (i.e. serialized in an ordered binary -// format). -// -// 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 -// SkFlatDictionary: is an abstract templated dictionary that maintains a -// searchable set of SkFlataData 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. -// -// -/////////////////////////////////////////////////////////////////////////////// - -class SkFlatData; - -class SkFlatController : public SkRefCnt { -public: - SK_DECLARE_INST_COUNT(SkFlatController) - - SkFlatController(); - virtual ~SkFlatController(); - /** - * Provide a new block of memory for the SkFlatDictionary to use. - */ - virtual void* allocThrow(size_t bytes) = 0; - - /** - * Unallocate a previously allocated block, returned by allocThrow. - * Implementation should at least perform an unallocation if passed the last - * pointer returned by allocThrow. If findAndReplace() is intended to be - * used, unalloc should also be able to unallocate the SkFlatData that is - * provided. - */ - virtual void unalloc(void* ptr) = 0; - - /** - * Used during creation and unflattening of SkFlatData objects. If the - * objects being flattened contain bitmaps they are stored in this heap - * and the flattenable stores the index to the bitmap on the heap. - * This should be set by the protected setBitmapHeap. - */ - SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; } - - /** - * Used during creation of SkFlatData objects. If a typeface recorder is - * required to flatten the objects being flattened (i.e. for SkPaints), this - * should be set by the protected setTypefaceSet. - */ - SkRefCntSet* getTypefaceSet() { return fTypefaceSet; } - - /** - * Used during unflattening of the SkFlatData objects in the - * SkFlatDictionary. Needs to be set by the protected setTypefacePlayback - * and needs to be reset to the SkRefCntSet passed to setTypefaceSet. - */ - SkTypefacePlayback* getTypefacePlayback() { return fTypefacePlayback; } - - /** - * Optional factory recorder used during creation of SkFlatData objects. Set - * using the protected method setNamedFactorySet. - */ - SkNamedFactorySet* getNamedFactorySet() { return fFactorySet; } - - /** - * Flags to use during creation of SkFlatData objects. Defaults to zero. - */ - uint32_t getWriteBufferFlags() { return fWriteBufferFlags; } - -protected: - /** - * Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted. - */ - void setBitmapHeap(SkBitmapHeap*); - - /** - * Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref - * counted. - */ - void setTypefaceSet(SkRefCntSet*); - - /** - * Set an SkTypefacePlayback to be used to find references to SkTypefaces - * during unflattening. Should be reset to the set provided to - * setTypefaceSet. - */ - void setTypefacePlayback(SkTypefacePlayback*); - - /** - * Set an SkNamedFactorySet to be used to store Factorys and their - * corresponding names during flattening. Ref counted. Returns the same - * set as a convenience. - */ - 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; - - typedef SkRefCnt INHERITED; -}; - -class SkFlatData { -public: - /** - * Compare two SkFlatData ptrs, returning -1, 0, 1 to allow them to be - * sorted. - * - * Note: this assumes that a and b have different sentinel values, either - * InCache or AsCandidate, otherwise the loop will go beyond the end of - * the buffers. - * - * dataToCompare() returns 2 fields before the flattened data: - * - checksum - * - size - * This ensures that if we see two blocks of different length, we will - * notice that right away, and not read any further. It also ensures that - * we see the checksum right away, so that most of the time it is enough - * to short-circuit our comparison. - */ - static int Compare(const SkFlatData* a, const SkFlatData* b) { - const uint32_t* stop = a->dataStop(); - const uint32_t* a_ptr = a->dataToCompare() - 1; - const uint32_t* b_ptr = b->dataToCompare() - 1; - // We use -1 above, so we can pre-increment our pointers in the loop - while (*++a_ptr == *++b_ptr) {} - - if (a_ptr == stop) { // sentinel - SkASSERT(b->dataStop() == b_ptr); - return 0; - } - SkASSERT(a_ptr < a->dataStop()); - SkASSERT(b_ptr < b->dataStop()); - return (*a_ptr < *b_ptr) ? -1 : 1; - } - - int index() const { return fIndex; } - const void* data() const { return (const char*)this + sizeof(*this); } - void* data() { return (char*)this + sizeof(*this); } - // Our data is always 32bit aligned, so we can offer this accessor - uint32_t* data32() { return (uint32_t*)this->data(); } - // Returns the size of the flattened data. - size_t flatSize() const { return fFlatSize; } - - void setSentinelInCache() { - this->setSentinel(kInCache_Sentinel); - } - void setSentinelAsCandidate() { - this->setSentinel(kCandidate_Sentinel); - } - - uint32_t checksum() const { return fChecksum; } - -#ifdef SK_DEBUG_SIZE - // returns the logical size of our data. Does not return any sentinel or - // padding we might have. - size_t size() const { - return sizeof(SkFlatData) + fFlatSize; - } -#endif - - static SkFlatData* Create(SkFlatController* controller, const void* obj, int index, - void (*flattenProc)(SkOrderedWriteBuffer&, const void*)); - - void unflatten(void* result, - void (*unflattenProc)(SkOrderedReadBuffer&, void*), - SkBitmapHeap* bitmapHeap = NULL, - SkTypefacePlayback* facePlayback = NULL) const; - - // When we purge an entry, we want to reuse an old index for the new entry, - // so we expose this setter. - void setIndex(int index) { fIndex = index; } - - // for unittesting - friend bool operator==(const SkFlatData& a, const SkFlatData& b) { - size_t N = (const char*)a.dataStop() - (const char*)a.dataToCompare(); - return !memcmp(a.dataToCompare(), b.dataToCompare(), N); - } - - // returns true if fTopBot[] has been recorded - bool isTopBotWritten() const { - return !SkScalarIsNaN(fTopBot[0]); - } - - // Returns fTopBot array, so it can be passed to a routine to compute them. - // For efficiency, we assert that fTopBot have not been recorded yet. - SkScalar* writableTopBot() const { - SkASSERT(!this->isTopBotWritten()); - return fTopBot; - } - - // return the topbot[] after it has been recorded - const SkScalar* topBot() const { - SkASSERT(this->isTopBotWritten()); - return fTopBot; - } - -private: - // This is *not* part of the key for search/sort - int fIndex; - - // Cache of paint's FontMetrics fTop,fBottom - // initialied to [NaN,NaN] as a sentinel that they have not been recorded yet - // - // This is *not* part of the key for search/sort - mutable SkScalar fTopBot[2]; - - // marks fTopBot[] as unrecorded - void setTopBotUnwritten() { - this->fTopBot[0] = SK_ScalarNaN; // initial to sentinel values - } - - // From here down is the data we look at in the search/sort. We always begin - // with the checksum and then length. - uint32_t fChecksum; - int32_t fFlatSize; // size of flattened data - // uint32_t flattenedData[] - // uint32_t sentinelValue - - const uint32_t* dataToCompare() const { - return (const uint32_t*)&fChecksum; - } - const uint32_t* dataStop() const { - SkASSERT(SkIsAlign4(fFlatSize)); - return (const uint32_t*)((const char*)this->data() + fFlatSize); - } - - enum { - kInCache_Sentinel = 0, - kCandidate_Sentinel = ~0U, - }; - void setSentinel(uint32_t value) { - SkASSERT(SkIsAlign4(fFlatSize)); - this->data32()[fFlatSize >> 2] = value; - } -}; - -template -class SkFlatDictionary { -public: - SkFlatDictionary(SkFlatController* controller) - : fController(controller) { - fFlattenProc = NULL; - fUnflattenProc = NULL; - SkASSERT(controller); - fController->ref(); - // set to 1 since returning a zero from find() indicates failure - fNextIndex = 1; - sk_bzero(fHash, sizeof(fHash)); - // index 0 is always empty since it is used as a signal that find failed - fIndexedData.push(NULL); - } - - virtual ~SkFlatDictionary() { - fController->unref(); - } - - int count() const { - SkASSERT(fIndexedData.count() == fSortedData.count()+1); - return fSortedData.count(); - } - - const SkFlatData* operator[](int index) const { - SkASSERT(index >= 0 && index < fSortedData.count()); - return fSortedData[index]; - } - - /** - * Clears the dictionary of all entries. However, it does NOT free the - * memory that was allocated for each entry. - */ - void reset() { - fSortedData.reset(); - fIndexedData.rewind(); - // index 0 is always empty since it is used as a signal that find failed - fIndexedData.push(NULL); - fNextIndex = 1; - sk_bzero(fHash, sizeof(fHash)); - } - - /** - * Similar to find. Allows the caller to specify an SkFlatData to replace in - * the case of an add. Also tells the caller whether a new SkFlatData was - * added and whether the old one was replaced. The parameters added and - * replaced are required to be non-NULL. Rather than returning the index of - * the entry in the dictionary, it returns the actual SkFlatData. - */ - const SkFlatData* findAndReplace(const T& element, - const SkFlatData* toReplace, bool* added, - bool* replaced) { - SkASSERT(added != NULL && replaced != NULL); - int oldCount = fSortedData.count(); - const SkFlatData* flat = this->findAndReturnFlat(element); - *added = fSortedData.count() == oldCount + 1; - *replaced = false; - if (*added && toReplace != NULL) { - // First, find the index of the one to replace - int indexToReplace = fSortedData.find(toReplace); - if (indexToReplace >= 0) { - // findAndReturnFlat set the index to fNextIndex and increased - // fNextIndex by one. Reuse the index from the one being - // replaced and reset fNextIndex to the proper value. - int oldIndex = flat->index(); - const_cast(flat)->setIndex(toReplace->index()); - fIndexedData[toReplace->index()] = flat; - fNextIndex--; - // Remove from the arrays. - fSortedData.remove(indexToReplace); - fIndexedData.remove(oldIndex); - // Remove from the hash table. - int oldHash = ChecksumToHashIndex(toReplace->checksum()); - if (fHash[oldHash] == toReplace) { - fHash[oldHash] = NULL; - } - // Delete the actual object. - fController->unalloc((void*)toReplace); - *replaced = true; - SkASSERT(fIndexedData.count() == fSortedData.count()+1); - } - } - return flat; - } - - /** - * Given an element of type T return its 1-based index in the dictionary. If - * the element wasn't previously in the dictionary it is automatically - * added. - * - * To make the Compare function fast, we write a sentinel value at the end - * of each block. The blocks in our fSortedData[] all have a 0 sentinel. The - * newly created block we're comparing against has a -1 in the sentinel. - * - * This trick allows Compare to always loop until failure. If it fails on - * the sentinal value, we know the blocks are equal. - */ - int find(const T& element) { - return this->findAndReturnFlat(element)->index(); - } - - /** - * Unflatten the objects and return them in SkTRefArray, or return NULL - * if there no objects (instead of an empty array). - */ - SkTRefArray* unflattenToArray() const { - int count = fSortedData.count(); - SkTRefArray* array = NULL; - if (count > 0) { - array = SkTRefArray::Create(count); - this->unflattenIntoArray(&array->writableAt(0)); - } - return array; - } - - /** - * Unflatten the specific object at the given index - */ - T* unflatten(int index) const { - SkASSERT(fIndexedData.count() == fSortedData.count()+1); - const SkFlatData* element = fIndexedData[index]; - SkASSERT(index == element->index()); - - T* dst = new T; - this->unflatten(dst, element); - return dst; - } - - const SkFlatData* findAndReturnFlat(const T& element) { - SkFlatData* flat = SkFlatData::Create(fController, &element, fNextIndex, fFlattenProc); - - int hashIndex = ChecksumToHashIndex(flat->checksum()); - const SkFlatData* candidate = fHash[hashIndex]; - if (candidate && !SkFlatData::Compare(flat, candidate)) { - fController->unalloc(flat); - return candidate; - } - - int index = SkTSearch((const SkFlatData**) fSortedData.begin(), - fSortedData.count(), flat, sizeof(flat), - &SkFlatData::Compare); - if (index >= 0) { - fController->unalloc(flat); - fHash[hashIndex] = fSortedData[index]; - return fSortedData[index]; - } - - index = ~index; - *fSortedData.insert(index) = flat; - *fIndexedData.insert(flat->index()) = flat; - SkASSERT(fSortedData.count() == fNextIndex); - fNextIndex++; - flat->setSentinelInCache(); - fHash[hashIndex] = flat; - SkASSERT(fIndexedData.count() == fSortedData.count()+1); - return flat; - } - -protected: - void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*); - void (*fUnflattenProc)(SkOrderedReadBuffer&, void*); - -private: - void unflatten(T* dst, const SkFlatData* element) const { - element->unflatten(dst, fUnflattenProc, - fController->getBitmapHeap(), - fController->getTypefacePlayback()); - } - - void unflattenIntoArray(T* array) const { - const int count = fSortedData.count(); - SkASSERT(fIndexedData.count() == fSortedData.count()+1); - const SkFlatData* const* iter = fSortedData.begin(); - for (int i = 0; i < count; ++i) { - const SkFlatData* element = iter[i]; - int index = element->index() - 1; - SkASSERT((unsigned)index < (unsigned)count); - unflatten(&array[index], element); - } - } - - SkFlatController * const fController; - int fNextIndex; - - // SkFlatDictionary has two copies of the data one indexed by the - // SkFlatData's index and the other sorted. The sorted data is used - // for finding and uniquification while the indexed copy is used - // for standard array-style lookups based on the SkFlatData's index - // (as in 'unflatten'). - SkTDArray fIndexedData; - // fSortedData is sorted by checksum/size/data. - SkTDArray fSortedData; - - enum { - // Determined by trying diff values on picture-recording benchmarks - // (e.g. PictureRecordBench.cpp), choosing the smallest value that - // showed a big improvement. Even better would be to benchmark diff - // values on recording representative web-pages or other "real" content. - HASH_BITS = 7, - HASH_MASK = (1 << HASH_BITS) - 1, - HASH_COUNT = 1 << HASH_BITS - }; - const SkFlatData* fHash[HASH_COUNT]; - - static int ChecksumToHashIndex(uint32_t checksum) { - int n = checksum; - if (HASH_BITS < 32) { - n ^= n >> 16; - } - if (HASH_BITS < 16) { - n ^= n >> 8; - } - if (HASH_BITS < 8) { - n ^= n >> 4; - } - return n & HASH_MASK; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// Some common dictionaries are defined here for both reference and convenience -/////////////////////////////////////////////////////////////////////////////// - -template -static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) { - ((T*)obj)->flatten(buffer); -} - -template -static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) { - ((T*)obj)->unflatten(buffer); -} - -class SkChunkFlatController : public SkFlatController { -public: - SkChunkFlatController(size_t minSize) - : fHeap(minSize) - , fTypefaceSet(SkNEW(SkRefCntSet)) { - this->setTypefaceSet(fTypefaceSet); - this->setTypefacePlayback(&fTypefacePlayback); - } - - ~SkChunkFlatController() { - fTypefaceSet->unref(); - } - - virtual void* allocThrow(size_t bytes) SK_OVERRIDE { - return fHeap.allocThrow(bytes); - } - - virtual void unalloc(void* ptr) SK_OVERRIDE { - (void) fHeap.unalloc(ptr); - } - - void setupPlaybacks() const { - fTypefacePlayback.reset(fTypefaceSet); - } - - void setBitmapStorage(SkBitmapHeap* heap) { - this->setBitmapHeap(heap); - } - -private: - SkChunkAlloc fHeap; - SkRefCntSet* fTypefaceSet; - mutable SkTypefacePlayback fTypefacePlayback; -}; - -class SkBitmapDictionary : public SkFlatDictionary { -public: - SkBitmapDictionary(SkFlatController* controller) - : SkFlatDictionary(controller) { - fFlattenProc = &SkFlattenObjectProc; - fUnflattenProc = &SkUnflattenObjectProc; - } -}; - -class SkMatrixDictionary : public SkFlatDictionary { - public: - SkMatrixDictionary(SkFlatController* controller) - : SkFlatDictionary(controller) { - 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 { - public: - SkPaintDictionary(SkFlatController* controller) - : SkFlatDictionary(controller) { - fFlattenProc = &SkFlattenObjectProc; - fUnflattenProc = &SkUnflattenObjectProc; - } -}; - -class SkRegionDictionary : public SkFlatDictionary { - public: - SkRegionDictionary(SkFlatController* controller) - : SkFlatDictionary(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/gfx/skia/src/core/SkPixelRef.cpp b/gfx/skia/src/core/SkPixelRef.cpp deleted file mode 100644 index 4cf47e3a2e35..000000000000 --- a/gfx/skia/src/core/SkPixelRef.cpp +++ /dev/null @@ -1,187 +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 "SkPixelRef.h" -#include "SkFlattenableBuffers.h" -#include "SkThread.h" - -SK_DEFINE_INST_COUNT(SkPixelRef) - -// must be a power-of-2. undef to just use 1 mutex -#define PIXELREF_MUTEX_RING_COUNT 32 - -#ifdef PIXELREF_MUTEX_RING_COUNT - static int32_t gPixelRefMutexRingIndex; - static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT); -#else - SK_DECLARE_STATIC_MUTEX(gPixelRefMutex); -#endif - -static SkBaseMutex* get_default_mutex() { -#ifdef PIXELREF_MUTEX_RING_COUNT - // atomic_inc might be overkill here. It may be fine if once in a while - // we hit a race-condition and two subsequent calls get the same index... - int index = sk_atomic_inc(&gPixelRefMutexRingIndex); - return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)]; -#else - return &gPixelRefMutex; -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -int32_t SkNextPixelRefGenerationID(); - -int32_t SkNextPixelRefGenerationID() { - static int32_t gPixelRefGenerationID; - // 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(&gPixelRefGenerationID) + 1; - } while (0 == genID); - return genID; -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkPixelRef::setMutex(SkBaseMutex* mutex) { - if (NULL == mutex) { - mutex = get_default_mutex(); - } - fMutex = mutex; -} - -// just need a > 0 value, so pick a funny one to aid in debugging -#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789 - -SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) { - this->setMutex(mutex); - fPixels = NULL; - fColorTable = NULL; // we do not track ownership of this - fLockCount = 0; - fGenerationID = 0; // signal to rebuild - fIsImmutable = false; - fPreLocked = false; -} - -SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) - : INHERITED(buffer) { - this->setMutex(mutex); - fPixels = NULL; - fColorTable = NULL; // we do not track ownership of this - fLockCount = 0; - fIsImmutable = buffer.readBool(); - fGenerationID = buffer.readUInt(); - fPreLocked = false; -} - -void SkPixelRef::setPreLocked(void* pixels, 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; - fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT; - fPreLocked = true; -#endif -} - -void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeBool(fIsImmutable); - // We write the gen ID into the picture for within-process recording. This - // is safe since the same genID will never refer to two different sets of - // pixels (barring overflow). However, each process has its own "namespace" - // of genIDs. So for cross-process recording we write a zero which will - // trigger assignment of a new genID in playback. - if (buffer.isCrossProcess()) { - buffer.writeUInt(0); - } else { - buffer.writeUInt(fGenerationID); - } -} - -void SkPixelRef::lockPixels() { - SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); - - if (!fPreLocked) { - SkAutoMutexAcquire ac(*fMutex); - - if (1 == ++fLockCount) { - fPixels = this->onLockPixels(&fColorTable); - } - } -} - -void SkPixelRef::unlockPixels() { - SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount); - - if (!fPreLocked) { - SkAutoMutexAcquire ac(*fMutex); - - SkASSERT(fLockCount > 0); - if (0 == --fLockCount) { - this->onUnlockPixels(); - fPixels = NULL; - fColorTable = NULL; - } - } -} - -bool SkPixelRef::lockPixelsAreWritable() const { - return this->onLockPixelsAreWritable(); -} - -bool SkPixelRef::onLockPixelsAreWritable() const { - return true; -} - -uint32_t SkPixelRef::getGenerationID() const { - if (0 == fGenerationID) { - fGenerationID = SkNextPixelRefGenerationID(); - } - return fGenerationID; -} - -void SkPixelRef::notifyPixelsChanged() { -#ifdef SK_DEBUG - if (fIsImmutable) { - SkDebugf("========== notifyPixelsChanged called on immutable pixelref"); - } -#endif - // this signals us to recompute this next time around - fGenerationID = 0; -} - -void SkPixelRef::setImmutable() { - fIsImmutable = true; -} - -bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { - return this->onReadPixels(dst, subset); -} - -bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { - return false; -} - -SkData* SkPixelRef::onRefEncodedData() { - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -#ifdef SK_BUILD_FOR_ANDROID -void SkPixelRef::globalRef(void* data) { - this->ref(); -} - -void SkPixelRef::globalUnref() { - this->unref(); -} -#endif diff --git a/gfx/skia/src/core/SkPoint.cpp b/gfx/skia/src/core/SkPoint.cpp deleted file mode 100644 index ebbe3a4f1fef..000000000000 --- a/gfx/skia/src/core/SkPoint.cpp +++ /dev/null @@ -1,473 +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 "SkPoint.h" - -void SkIPoint::rotateCW(SkIPoint* dst) const { - SkASSERT(dst); - - // use a tmp in case this == dst - int32_t tmp = fX; - dst->fX = -fY; - dst->fY = tmp; -} - -void SkIPoint::rotateCCW(SkIPoint* dst) const { - SkASSERT(dst); - - // use a tmp in case this == dst - int32_t tmp = fX; - dst->fX = fY; - dst->fY = -tmp; -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkPoint::setIRectFan(int l, int t, int r, int b, size_t stride) { - SkASSERT(stride >= sizeof(SkPoint)); - - ((SkPoint*)((intptr_t)this + 0 * stride))->set(SkIntToScalar(l), - SkIntToScalar(t)); - ((SkPoint*)((intptr_t)this + 1 * stride))->set(SkIntToScalar(l), - SkIntToScalar(b)); - ((SkPoint*)((intptr_t)this + 2 * stride))->set(SkIntToScalar(r), - SkIntToScalar(b)); - ((SkPoint*)((intptr_t)this + 3 * stride))->set(SkIntToScalar(r), - SkIntToScalar(t)); -} - -void SkPoint::setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, - size_t stride) { - SkASSERT(stride >= sizeof(SkPoint)); - - ((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t); - ((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b); - ((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b); - ((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t); -} - -void SkPoint::rotateCW(SkPoint* dst) const { - SkASSERT(dst); - - // use a tmp in case this == dst - SkScalar tmp = fX; - dst->fX = -fY; - dst->fY = tmp; -} - -void SkPoint::rotateCCW(SkPoint* dst) const { - SkASSERT(dst); - - // use a tmp in case this == dst - SkScalar tmp = fX; - dst->fX = fY; - dst->fY = -tmp; -} - -void SkPoint::scale(SkScalar scale, SkPoint* dst) const { - SkASSERT(dst); - dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale)); -} - -bool SkPoint::normalize() { - return this->setLength(fX, fY, SK_Scalar1); -} - -bool SkPoint::setNormalize(SkScalar x, SkScalar y) { - return this->setLength(x, y, SK_Scalar1); -} - -bool SkPoint::setLength(SkScalar length) { - return this->setLength(fX, fY, length); -} - -#ifdef SK_SCALAR_IS_FLOAT - -// Returns the square of the Euclidian distance to (dx,dy). -static inline float getLengthSquared(float dx, float dy) { - return dx * dx + dy * dy; -} - -// Calculates the square of the Euclidian distance to (dx,dy) and stores it in -// *lengthSquared. Returns true if the distance is judged to be "nearly zero". -// -// This logic is encapsulated in a helper method to make it explicit that we -// always perform this check in the same manner, to avoid inconsistencies -// (see http://code.google.com/p/skia/issues/detail?id=560 ). -static inline bool isLengthNearlyZero(float dx, float dy, - float *lengthSquared) { - *lengthSquared = getLengthSquared(dx, dy); - return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero); -} - -SkScalar SkPoint::Normalize(SkPoint* pt) { - float mag2; - if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) { - float mag = sk_float_sqrt(mag2); - float scale = 1.0f / mag; - pt->fX = pt->fX * scale; - pt->fY = pt->fY * scale; - return mag; - } - return 0; -} - -SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) { - return sk_float_sqrt(getLengthSquared(dx, dy)); -} - -bool SkPoint::setLength(float x, float y, float length) { - float mag2; - if (!isLengthNearlyZero(x, y, &mag2)) { - float scale = length / sk_float_sqrt(mag2); - fX = x * scale; - fY = y * scale; - return true; - } - return false; -} - -#else - -#include "Sk64.h" - -// Returns the square of the Euclidian distance to (dx,dy) in *result. -static inline void getLengthSquared(SkScalar dx, SkScalar dy, Sk64 *result) { - Sk64 dySqr; - - result->setMul(dx, dx); - dySqr.setMul(dy, dy); - result->add(dySqr); -} - -// Calculates the square of the Euclidian distance to (dx,dy) and stores it in -// *lengthSquared. Returns true if the distance is judged to be "nearly zero". -// -// This logic is encapsulated in a helper method to make it explicit that we -// always perform this check in the same manner, to avoid inconsistencies -// (see http://code.google.com/p/skia/issues/detail?id=560 ). -static inline bool isLengthNearlyZero(SkScalar dx, SkScalar dy, - Sk64 *lengthSquared) { - Sk64 tolSqr; - getLengthSquared(dx, dy, lengthSquared); - - // we want nearlyzero^2, but to compute it fast we want to just do a - // 32bit multiply, so we require that it not exceed 31bits. That is true - // if nearlyzero is <= 0xB504, which should be trivial, since usually - // nearlyzero is a very small fixed-point value. - SkASSERT(SK_ScalarNearlyZero <= 0xB504); - - tolSqr.set(0, SK_ScalarNearlyZero * SK_ScalarNearlyZero); - return *lengthSquared <= tolSqr; -} - -SkScalar SkPoint::Normalize(SkPoint* pt) { - Sk64 mag2; - if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) { - SkScalar mag = mag2.getSqrt(); - SkScalar scale = SkScalarInvert(mag); - pt->fX = SkScalarMul(pt->fX, scale); - pt->fY = SkScalarMul(pt->fY, scale); - return mag; - } - return 0; -} - -bool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) { - Sk64 mag2_unused; - return !isLengthNearlyZero(dx, dy, &mag2_unused); -} - -SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) { - Sk64 tmp; - getLengthSquared(dx, dy, &tmp); - return tmp.getSqrt(); -} - -#ifdef SK_DEBUGx -static SkFixed fixlen(SkFixed x, SkFixed y) { - float fx = (float)x; - float fy = (float)y; - - return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f); -} -#endif - -static inline uint32_t squarefixed(unsigned x) { - x >>= 16; - return x*x; -} - -#if 1 // Newton iter for setLength - -static inline unsigned invsqrt_iter(unsigned V, unsigned U) { - unsigned x = V * U >> 14; - x = x * U >> 14; - x = (3 << 14) - x; - x = (U >> 1) * x >> 14; - return x; -} - -static const uint16_t gInvSqrt14GuessTable[] = { - 0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061, - 0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780, - 0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235, - 0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99, - 0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee, - 0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc, - 0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830, - 0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce -}; - -#define BUILD_INVSQRT_TABLEx -#ifdef BUILD_INVSQRT_TABLE -static void build_invsqrt14_guess_table() { - for (int i = 8; i <= 63; i++) { - unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25)); - printf("0x%x, ", x); - } - printf("\n"); -} -#endif - -static unsigned fast_invsqrt(uint32_t x) { -#ifdef BUILD_INVSQRT_TABLE - unsigned top2 = x >> 25; - SkASSERT(top2 >= 8 && top2 <= 63); - - static bool gOnce; - if (!gOnce) { - build_invsqrt14_guess_table(); - gOnce = true; - } -#endif - - unsigned V = x >> 14; // make V .14 - - unsigned top = x >> 25; - SkASSERT(top >= 8 && top <= 63); - SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable)); - unsigned U = gInvSqrt14GuessTable[top - 8]; - - U = invsqrt_iter(V, U); - return invsqrt_iter(V, U); -} - -/* We "normalize" x,y to be .14 values (so we can square them and stay 32bits. - Then we Newton-iterate this in .14 space to compute the invser-sqrt, and - scale by it at the end. The .14 space means we can execute our iterations - and stay in 32bits as well, making the multiplies much cheaper than calling - SkFixedMul. -*/ -bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) { - if (ox == 0) { - if (oy == 0) { - return false; - } - this->set(0, SkApplySign(length, SkExtractSign(oy))); - return true; - } - if (oy == 0) { - this->set(SkApplySign(length, SkExtractSign(ox)), 0); - return true; - } - - unsigned x = SkAbs32(ox); - unsigned y = SkAbs32(oy); - int zeros = SkCLZ(x | y); - - // make x,y 1.14 values so our fast sqr won't overflow - if (zeros > 17) { - x <<= zeros - 17; - y <<= zeros - 17; - } else { - x >>= 17 - zeros; - y >>= 17 - zeros; - } - SkASSERT((x | y) <= 0x7FFF); - - unsigned invrt = fast_invsqrt(x*x + y*y); - - x = x * invrt >> 12; - y = y * invrt >> 12; - - if (length != SK_Fixed1) { - x = SkFixedMul(x, length); - y = SkFixedMul(y, length); - } - this->set(SkApplySign(x, SkExtractSign(ox)), - SkApplySign(y, SkExtractSign(oy))); - return true; -} -#else -/* - Normalize x,y, and then scale them by length. - - The obvious way to do this would be the following: - S64 tmp1, tmp2; - tmp1.setMul(x,x); - tmp2.setMul(y,y); - tmp1.add(tmp2); - len = tmp1.getSqrt(); - x' = SkFixedDiv(x, len); - y' = SkFixedDiv(y, len); - This is fine, but slower than what we do below. - - The present technique does not compute the starting length, but - rather fiddles with x,y iteratively, all the while checking its - magnitude^2 (avoiding a sqrt). - - We normalize by first shifting x,y so that at least one of them - has bit 31 set (after taking the abs of them). - Then we loop, refining x,y by squaring them and comparing - against a very large 1.0 (1 << 28), and then adding or subtracting - a delta (which itself is reduced by half each time through the loop). - For speed we want the squaring to be with a simple integer mul. To keep - that from overflowing we shift our coordinates down until we are dealing - with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits) - When our square is close to 1.0, we shift x,y down into fixed range. -*/ -bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) { - if (ox == 0) { - if (oy == 0) - return false; - this->set(0, SkApplySign(length, SkExtractSign(oy))); - return true; - } - if (oy == 0) { - this->set(SkApplySign(length, SkExtractSign(ox)), 0); - return true; - } - - SkFixed x = SkAbs32(ox); - SkFixed y = SkAbs32(oy); - - // shift x,y so that the greater of them is 15bits (1.14 fixed point) - { - int shift = SkCLZ(x | y); - // make them .30 - x <<= shift - 1; - y <<= shift - 1; - } - - SkFixed dx = x; - SkFixed dy = y; - - for (int i = 0; i < 17; i++) { - dx >>= 1; - dy >>= 1; - - U32 len2 = squarefixed(x) + squarefixed(y); - if (len2 >> 28) { - x -= dx; - y -= dy; - } else { - x += dx; - y += dy; - } - } - x >>= 14; - y >>= 14; - -#ifdef SK_DEBUGx // measure how far we are from unit-length - { - static int gMaxError; - static int gMaxDiff; - - SkFixed len = fixlen(x, y); - int err = len - SK_Fixed1; - err = SkAbs32(err); - - if (err > gMaxError) { - gMaxError = err; - SkDebugf("gMaxError %d\n", err); - } - - float fx = SkAbs32(ox)/65536.0f; - float fy = SkAbs32(oy)/65536.0f; - float mag = sqrtf(fx*fx + fy*fy); - fx /= mag; - fy /= mag; - SkFixed xx = (int)floorf(fx * 65536 + 0.5f); - SkFixed yy = (int)floorf(fy * 65536 + 0.5f); - err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y)); - if (err > gMaxDiff) { - gMaxDiff = err; - SkDebugf("gMaxDiff %d\n", err); - } - } -#endif - - x = SkApplySign(x, SkExtractSign(ox)); - y = SkApplySign(y, SkExtractSign(oy)); - if (length != SK_Fixed1) { - x = SkFixedMul(x, length); - y = SkFixedMul(y, length); - } - - this->set(x, y); - return true; -} -#endif - -#endif - -/////////////////////////////////////////////////////////////////////////////// - -SkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a, - const SkPoint& b, - Side* side) const { - - SkVector u = b - a; - SkVector v = *this - a; - - SkScalar uLengthSqd = u.lengthSqd(); - SkScalar det = u.cross(v); - if (NULL != side) { - SkASSERT(-1 == SkPoint::kLeft_Side && - 0 == SkPoint::kOn_Side && - 1 == kRight_Side); - *side = (Side) SkScalarSignAsInt(det); - } - return SkScalarMulDiv(det, det, uLengthSqd); -} - -SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a, - const SkPoint& b) const { - // See comments to distanceToLineBetweenSqd. If the projection of c onto - // u is between a and b then this returns the same result as that - // function. Otherwise, it returns the distance to the closer of a and - // b. Let the projection of v onto u be v'. There are three cases: - // 1. v' points opposite to u. c is not between a and b and is closer - // to a than b. - // 2. v' points along u and has magnitude less than y. c is between - // a and b and the distance to the segment is the same as distance - // to the line ab. - // 3. v' points along u and has greater magnitude than u. c is not - // not between a and b and is closer to b than a. - // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're - // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise - // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to - // avoid a sqrt to compute |u|. - - SkVector u = b - a; - SkVector v = *this - a; - - SkScalar uLengthSqd = u.lengthSqd(); - SkScalar uDotV = SkPoint::DotProduct(u, v); - - if (uDotV <= 0) { - return v.lengthSqd(); - } else if (uDotV > uLengthSqd) { - return b.distanceToSqd(*this); - } else { - SkScalar det = u.cross(v); - return SkScalarMulDiv(det, det, uLengthSqd); - } -} diff --git a/gfx/skia/src/core/SkTypeface.cpp b/gfx/skia/src/core/SkTypeface.cpp deleted file mode 100644 index 6af0ae388f07..000000000000 --- a/gfx/skia/src/core/SkTypeface.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkAdvancedTypefaceMetrics.h" -#include "SkFontDescriptor.h" -#include "SkFontHost.h" -#include "SkFontStream.h" -#include "SkStream.h" -#include "SkTypeface.h" - -SK_DEFINE_INST_COUNT(SkTypeface) - -//#define TRACE_LIFECYCLE - -#ifdef TRACE_LIFECYCLE - static int32_t gTypefaceCounter; -#endif - -SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedPitch) - : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) { -#ifdef TRACE_LIFECYCLE - SkDebugf("SkTypeface: create %p fontID %d total %d\n", - this, fontID, ++gTypefaceCounter); -#endif -} - -SkTypeface::~SkTypeface() { -#ifdef TRACE_LIFECYCLE - SkDebugf("SkTypeface: destroy %p fontID %d total %d\n", - this, fUniqueID, --gTypefaceCounter); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkTypeface::GetDefaultTypeface() { - // 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 SkTypeface* gDefaultTypeface; - - if (NULL == gDefaultTypeface) { - gDefaultTypeface = - SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal); - } - return gDefaultTypeface; -} - -SkTypeface* SkTypeface::RefDefault() { - return SkRef(GetDefaultTypeface()); -} - -uint32_t SkTypeface::UniqueID(const SkTypeface* face) { - if (NULL == face) { - face = GetDefaultTypeface(); - } - return face->uniqueID(); -} - -bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) { - return SkTypeface::UniqueID(facea) == SkTypeface::UniqueID(faceb); -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) { - return SkFontHost::CreateTypeface(NULL, name, style); -} - -SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) { - if (family && family->style() == s) { - family->ref(); - return const_cast(family); - } - return SkFontHost::CreateTypeface(family, NULL, s); -} - -SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) { - return SkFontHost::CreateTypefaceFromStream(stream); -} - -SkTypeface* SkTypeface::CreateFromFile(const char path[]) { - return SkFontHost::CreateTypefaceFromFile(path); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkTypeface::serialize(SkWStream* wstream) const { - bool isLocal = false; - SkFontDescriptor desc(this->style()); - this->onGetFontDescriptor(&desc, &isLocal); - - desc.serialize(wstream); - if (isLocal) { - int ttcIndex; // TODO: write this to the stream? - SkAutoTUnref rstream(this->openStream(&ttcIndex)); - if (rstream.get()) { - size_t length = rstream->getLength(); - wstream->writePackedUInt(length); - wstream->writeStream(rstream, length); - } else { - wstream->writePackedUInt(0); - } - } else { - wstream->writePackedUInt(0); - } -} - -SkTypeface* SkTypeface::Deserialize(SkStream* stream) { - SkFontDescriptor desc(stream); - size_t length = stream->readPackedUInt(); - if (length > 0) { - void* addr = sk_malloc_flags(length, 0); - if (addr) { - SkAutoTUnref localStream(SkNEW_ARGS(SkMemoryStream, - (addr, length, false))); - return SkTypeface::CreateFromStream(localStream.get()); - } - // failed to allocate, so just skip and create-from-name - stream->skip(length); - } - - return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle()); -} - -/////////////////////////////////////////////////////////////////////////////// - -int SkTypeface::countTables() const { - return this->onGetTableTags(NULL); -} - -int SkTypeface::getTableTags(SkFontTableTag tags[]) const { - return this->onGetTableTags(tags); -} - -size_t SkTypeface::getTableSize(SkFontTableTag tag) const { - return this->onGetTableData(tag, 0, ~0U, NULL); -} - -size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length, - void* data) const { - return this->onGetTableData(tag, offset, length, data); -} - -SkStream* SkTypeface::openStream(int* ttcIndex) const { - int ttcIndexStorage; - if (NULL == ttcIndex) { - // So our subclasses don't need to check for null param - ttcIndex = &ttcIndexStorage; - } - return this->onOpenStream(ttcIndex); -} - -int SkTypeface::getUnitsPerEm() const { - // should we try to cache this in the base-class? - return this->onGetUPEM(); -} - -SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics( - SkAdvancedTypefaceMetrics::PerGlyphInfo info, - const uint32_t* glyphIDs, - uint32_t glyphIDsCount) const { - return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -int SkTypeface::onGetUPEM() const { - int upem = 0; - - SkAdvancedTypefaceMetrics* metrics; - metrics = this->getAdvancedTypefaceMetrics( - SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo, - NULL, 0); - if (metrics) { - upem = metrics->fEmSize; - metrics->unref(); - } - return upem; -} - -int SkTypeface::onGetTableTags(SkFontTableTag tags[]) const { - int ttcIndex; - SkAutoTUnref stream(this->openStream(&ttcIndex)); - return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0; -} - -size_t SkTypeface::onGetTableData(SkFontTableTag tag, size_t offset, - size_t length, void* data) const { - int ttcIndex; - SkAutoTUnref stream(this->openStream(&ttcIndex)); - return stream.get() - ? SkFontStream::GetTableData(stream, ttcIndex, tag, offset, length, data) - : 0; -} diff --git a/gfx/skia/src/core/SkWriter32.cpp b/gfx/skia/src/core/SkWriter32.cpp deleted file mode 100644 index 56edd1969803..000000000000 --- a/gfx/skia/src/core/SkWriter32.cpp +++ /dev/null @@ -1,296 +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 "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 { - SkASSERT(fSize > 0); - 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" - -/* - * 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(); - const void* ptr = this->peek(); - - // skip over teh string + '\0' and then pad to a multiple of 4 - size_t alignedSize = SkAlign4(len + 1); - this->skip(alignedSize); - - if (outLen) { - *outLen = len; - } - return (const char*)ptr; -} - -size_t SkReader32::readIntoString(SkString* copy) { - size_t len; - const char* ptr = this->readString(&len); - if (copy) { - copy->set(ptr, len); - } - return len; -} - -void SkWriter32::writeString(const char str[], size_t len) { - if ((long)len < 0) { - SkASSERT(str); - 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); -} - -size_t SkWriter32::WriteStringSize(const char* str, size_t len) { - if ((long)len < 0) { - SkASSERT(str); - len = strlen(str); - } - const size_t lenBytes = 4; // we use 4 bytes to record the length - // add 1 since we also write a terminating 0 - return SkAlign4(lenBytes + len + 1); -} diff --git a/gfx/skia/src/effects/SkArithmeticMode.cpp b/gfx/skia/src/effects/SkArithmeticMode.cpp deleted file mode 100644 index 7492cce5ec08..000000000000 --- a/gfx/skia/src/effects/SkArithmeticMode.cpp +++ /dev/null @@ -1,193 +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 "SkArithmeticMode.h" -#include "SkColorPriv.h" -#include "SkString.h" -#include "SkUnPreMultiply.h" - -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; - } - - virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, - const SkAlpha aa[]) const SK_OVERRIDE; - - SK_DEVELOPER_TO_STRING() - SK_DECLARE_UNFLATTENABLE_OBJECT() - -private: - SkScalar fK[4]; - - typedef SkXfermode INHERITED; -}; - -static int pinToByte(int value) { - if (value < 0) { - value = 0; - } else if (value > 255) { - value = 255; - } - return value; -} - -static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, - int src, int dst) { - SkScalar result = SkScalarMul(k1, src * dst) + - SkScalarMul(k2, src) + - SkScalarMul(k3, dst) + - k4; - int res = SkScalarRoundToInt(result); - return pinToByte(res); -} - -static int blend(int src, int dst, int scale) { - return dst + ((src - dst) * scale >> 8); -} - -static bool needsUnpremul(int alpha) { - return 0 != alpha && 0xFF != alpha; -} - -void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[], - int count, const SkAlpha aaCoverage[]) const { - SkScalar k1 = fK[0] / 255; - SkScalar k2 = fK[1]; - SkScalar k3 = fK[2]; - SkScalar k4 = fK[3] * 255; - - for (int i = 0; i < count; ++i) { - if ((NULL == aaCoverage) || aaCoverage[i]) { - SkPMColor sc = src[i]; - SkPMColor dc = dst[i]; - int sa = SkGetPackedA32(sc); - int da = SkGetPackedA32(dc); - - int srcNeedsUnpremul = needsUnpremul(sa); - int dstNeedsUnpremul = needsUnpremul(sa); - - int a, r, g, b; - - if (!srcNeedsUnpremul && !dstNeedsUnpremul) { - a = arith(k1, k2, k3, k4, sa, sa); - r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc)); - g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc)); - b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc)); - } else { - int sr = SkGetPackedR32(sc); - int sg = SkGetPackedG32(sc); - int sb = SkGetPackedB32(sc); - if (srcNeedsUnpremul) { - SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa); - sr = SkUnPreMultiply::ApplyScale(scale, sr); - sg = SkUnPreMultiply::ApplyScale(scale, sg); - sb = SkUnPreMultiply::ApplyScale(scale, sb); - } - - int dr = SkGetPackedR32(dc); - int dg = SkGetPackedG32(dc); - int db = SkGetPackedB32(dc); - if (dstNeedsUnpremul) { - SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da); - dr = SkUnPreMultiply::ApplyScale(scale, dr); - dg = SkUnPreMultiply::ApplyScale(scale, dg); - db = SkUnPreMultiply::ApplyScale(scale, db); - } - - a = arith(k1, k2, k3, k4, sa, sa); - r = arith(k1, k2, k3, k4, sr, dr); - g = arith(k1, k2, k3, k4, sg, dg); - b = arith(k1, k2, k3, k4, sb, db); - } - - // apply antialias coverage if necessary - if (aaCoverage && 0xFF != aaCoverage[i]) { - int scale = aaCoverage[i] + (aaCoverage[i] >> 7); - a = blend(a, SkGetPackedA32(sc), scale); - r = blend(r, SkGetPackedR32(sc), scale); - g = blend(g, SkGetPackedG32(sc), scale); - b = blend(b, SkGetPackedB32(sc), scale); - } - - // turn the result back into premul - if (0xFF != a) { - int scale = a + (a >> 7); - r = SkAlphaMul(r, scale); - g = SkAlphaMul(g, scale); - b = SkAlphaMul(b, scale); - } - dst[i] = SkPackARGB32(a, r, g, b); - } - } -} - -#ifdef SK_DEVELOPER -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(" "); - } - } -} -#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) { - if (fitsInBits(k1, 8) && fitsInBits(k2, 16) && - fitsInBits(k2, 16) && fitsInBits(k2, 24)) { - -#if 0 // UNUSED - int32_t i1 = toDot8(k1); - int32_t i2 = toDot8(k2); - int32_t i3 = toDot8(k3); - int32_t i4 = toDot8(k4); - if (i1) { - return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4)); - } - if (0 == i2) { - return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4)); - } - if (0 == i3) { - return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4)); - } - return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4)); -#endif - } - return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4)); -} diff --git a/gfx/skia/src/effects/SkBicubicImageFilter.cpp b/gfx/skia/src/effects/SkBicubicImageFilter.cpp deleted file mode 100644 index c10937eaea8f..000000000000 --- a/gfx/skia/src/effects/SkBicubicImageFilter.cpp +++ /dev/null @@ -1,372 +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 "SkBicubicImageFilter.h" -#include "SkBitmap.h" -#include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" -#include "SkMatrix.h" -#include "SkRect.h" -#include "SkUnPreMultiply.h" - -#if SK_SUPPORT_GPU -#include "gl/GrGLEffectMatrix.h" -#include "effects/GrSingleTextureEffect.h" -#include "GrTBackendEffectFactory.h" -#include "GrContext.h" -#include "GrTexture.h" -#include "SkImageFilterUtils.h" -#endif - -SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16], SkImageFilter* input) - : INHERITED(input), - fScale(scale) { - memcpy(fCoefficients, coefficients, sizeof(fCoefficients)); -} - -#define DS(x) SkDoubleToScalar(x) - -SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale, - SkImageFilter* input) { - static const SkScalar coefficients[16] = { - DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), - DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), - DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), - DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), - }; - return SkNEW_ARGS(SkBicubicImageFilter, (scale, coefficients, input)); -} - -SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients); - SkASSERT(readSize == 16); - fScale.fWidth = buffer.readScalar(); - fScale.fHeight = buffer.readScalar(); -} - -void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeScalarArray(fCoefficients, 16); - buffer.writeScalar(fScale.fWidth); - buffer.writeScalar(fScale.fHeight); -} - -SkBicubicImageFilter::~SkBicubicImageFilter() { -} - -inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPMColor c1, SkPMColor c2, SkPMColor c3) { - SkScalar t2 = t * t, t3 = t2 * t; - SkScalar cc[4]; - // FIXME: For the fractx case, this should be refactored out of this function. - cc[0] = c[0] + SkScalarMul(c[1], t) + SkScalarMul(c[2], t2) + SkScalarMul(c[3], t3); - cc[1] = c[4] + SkScalarMul(c[5], t) + SkScalarMul(c[6], t2) + SkScalarMul(c[7], t3); - cc[2] = c[8] + SkScalarMul(c[9], t) + SkScalarMul(c[10], t2) + SkScalarMul(c[11], t3); - cc[3] = c[12] + SkScalarMul(c[13], t) + SkScalarMul(c[14], t2) + SkScalarMul(c[15], t3); - SkScalar a = SkScalarClampMax(SkScalarMul(cc[0], SkGetPackedA32(c0)) + SkScalarMul(cc[1], SkGetPackedA32(c1)) + SkScalarMul(cc[2], SkGetPackedA32(c2)) + SkScalarMul(cc[3], SkGetPackedA32(c3)), 255); - SkScalar r = SkScalarMul(cc[0], SkGetPackedR32(c0)) + SkScalarMul(cc[1], SkGetPackedR32(c1)) + SkScalarMul(cc[2], SkGetPackedR32(c2)) + SkScalarMul(cc[3], SkGetPackedR32(c3)); - SkScalar g = SkScalarMul(cc[0], SkGetPackedG32(c0)) + SkScalarMul(cc[1], SkGetPackedG32(c1)) + SkScalarMul(cc[2], SkGetPackedG32(c2)) + SkScalarMul(cc[3], SkGetPackedG32(c3)); - SkScalar b = SkScalarMul(cc[0], SkGetPackedB32(c0)) + SkScalarMul(cc[1], SkGetPackedB32(c1)) + SkScalarMul(cc[2], SkGetPackedB32(c2)) + SkScalarMul(cc[3], SkGetPackedB32(c3)); - return SkPackARGB32(SkScalarRoundToInt(a), - SkScalarRoundToInt(SkScalarClampMax(r, a)), - SkScalarRoundToInt(SkScalarClampMax(g, a)), - SkScalarRoundToInt(SkScalarClampMax(b, a))); -} - -bool SkBicubicImageFilter::onFilterImage(Proxy* proxy, - const SkBitmap& source, - const SkMatrix& matrix, - SkBitmap* result, - SkIPoint* loc) { - SkBitmap src = this->getInputResult(0, proxy, source, matrix, loc); - if (src.config() != SkBitmap::kARGB_8888_Config) { - return false; - } - - SkAutoLockPixels alp(src); - if (!src.getPixels()) { - return false; - } - - SkRect dstRect = SkRect::MakeWH(SkScalarMul(SkIntToScalar(src.width()), fScale.fWidth), - SkScalarMul(SkIntToScalar(src.height()), fScale.fHeight)); - SkIRect dstIRect; - dstRect.roundOut(&dstIRect); - result->setConfig(src.config(), dstIRect.width(), dstIRect.height()); - result->allocPixels(); - if (!result->getPixels()) { - return false; - } - - SkRect srcRect; - src.getBounds(&srcRect); - SkMatrix inverse; - inverse.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit); - inverse.postTranslate(SkFloatToScalar(-0.5f), SkFloatToScalar(-0.5f)); - - for (int y = dstIRect.fTop; y < dstIRect.fBottom; ++y) { - SkPMColor* dptr = result->getAddr32(dstIRect.fLeft, y); - for (int x = dstIRect.fLeft; x < dstIRect.fRight; ++x) { - SkPoint srcPt, dstPt = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); - inverse.mapPoints(&srcPt, &dstPt, 1); - SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX); - SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); - int sx = SkScalarFloorToInt(srcPt.fX); - int sy = SkScalarFloorToInt(srcPt.fY); - int x0 = SkClampMax(sx - 1, src.width() - 1); - int x1 = SkClampMax(sx , src.width() - 1); - int x2 = SkClampMax(sx + 1, src.width() - 1); - int x3 = SkClampMax(sx + 2, src.width() - 1); - int y0 = SkClampMax(sy - 1, src.height() - 1); - int y1 = SkClampMax(sy , src.height() - 1); - int y2 = SkClampMax(sy + 1, src.height() - 1); - int y3 = SkClampMax(sy + 2, src.height() - 1); - SkPMColor s00 = *src.getAddr32(x0, y0); - SkPMColor s10 = *src.getAddr32(x1, y0); - SkPMColor s20 = *src.getAddr32(x2, y0); - SkPMColor s30 = *src.getAddr32(x3, y0); - SkPMColor s0 = cubicBlend(fCoefficients, fractx, s00, s10, s20, s30); - SkPMColor s01 = *src.getAddr32(x0, y1); - SkPMColor s11 = *src.getAddr32(x1, y1); - SkPMColor s21 = *src.getAddr32(x2, y1); - SkPMColor s31 = *src.getAddr32(x3, y1); - SkPMColor s1 = cubicBlend(fCoefficients, fractx, s01, s11, s21, s31); - SkPMColor s02 = *src.getAddr32(x0, y2); - SkPMColor s12 = *src.getAddr32(x1, y2); - SkPMColor s22 = *src.getAddr32(x2, y2); - SkPMColor s32 = *src.getAddr32(x3, y2); - SkPMColor s2 = cubicBlend(fCoefficients, fractx, s02, s12, s22, s32); - SkPMColor s03 = *src.getAddr32(x0, y3); - SkPMColor s13 = *src.getAddr32(x1, y3); - SkPMColor s23 = *src.getAddr32(x2, y3); - SkPMColor s33 = *src.getAddr32(x3, y3); - SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33); - *dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -#if SK_SUPPORT_GPU -class GrGLBicubicEffect; - -class GrBicubicEffect : public GrSingleTextureEffect { -public: - virtual ~GrBicubicEffect(); - - static const char* Name() { return "Bicubic"; } - const float* coefficients() const { return fCoefficients; } - - typedef GrGLBicubicEffect GLEffect; - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; - virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; - - static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16]) { - AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients))); - return CreateEffectRef(effect); - } - -private: - GrBicubicEffect(GrTexture*, const SkScalar coefficients[16]); - virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; - float fCoefficients[16]; - - GR_DECLARE_EFFECT_TEST; - - typedef GrSingleTextureEffect INHERITED; -}; - -class GrGLBicubicEffect : public GrGLEffect { -public: - GrGLBicubicEffect(const GrBackendEffectFactory& factory, - const GrDrawEffect&); - virtual void emitCode(GrGLShaderBuilder*, - const GrDrawEffect&, - EffectKey, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray&) SK_OVERRIDE; - - static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; - -private: - typedef GrGLUniformManager::UniformHandle UniformHandle; - - UniformHandle fCoefficientsUni; - UniformHandle fImageIncrementUni; - - GrGLEffectMatrix fEffectMatrix; - - typedef GrGLEffect INHERITED; -}; - -GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, - const GrDrawEffect& drawEffect) - : INHERITED(factory) - , fCoefficientsUni(GrGLUniformManager::kInvalidUniformHandle) - , fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle) - , fEffectMatrix(drawEffect.castEffect().coordsType()) { -} - -void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect&, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) { - const char* coords; - fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords); - fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kMat44f_GrSLType, "Coefficients"); - fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec2f_GrSLType, "ImageIncrement"); - - const char* imgInc = builder->getUniformCStr(fImageIncrementUni); - const char* coeff = builder->getUniformCStr(fCoefficientsUni); - - SkString cubicBlendName; - - static const GrGLShaderVar gCubicBlendArgs[] = { - GrGLShaderVar("coefficients", kMat44f_GrSLType), - GrGLShaderVar("t", kFloat_GrSLType), - GrGLShaderVar("c0", kVec4f_GrSLType), - GrGLShaderVar("c1", kVec4f_GrSLType), - GrGLShaderVar("c2", kVec4f_GrSLType), - GrGLShaderVar("c3", kVec4f_GrSLType), - }; - builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, - "cubicBlend", - SK_ARRAY_COUNT(gCubicBlendArgs), - gCubicBlendArgs, - "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n" - "\tvec4 c = coefficients * ts;\n" - "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n", - &cubicBlendName); - builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5, 0.5);\n", coords, imgInc); - builder->fsCodeAppendf("\tvec2 f = fract(coord / %s);\n", imgInc); - 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->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, - samplers[0], - coord.c_str()); - builder->fsCodeAppend(";\n"); - } - 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("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor, cubicBlendName.c_str(), coeff); -} - -GrGLEffect::EffectKey GrGLBicubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const GrBicubicEffect& bicubic = drawEffect.castEffect(); - EffectKey matrixKey = GrGLEffectMatrix::GenKey(bicubic.getMatrix(), - drawEffect, - bicubic.coordsType(), - bicubic.texture(0)); - return matrixKey; -} - -void GrGLBicubicEffect::setData(const GrGLUniformManager& uman, - const GrDrawEffect& drawEffect) { - const GrBicubicEffect& effect = drawEffect.castEffect(); - GrTexture& texture = *effect.texture(0); - float imageIncrement[2]; - imageIncrement[0] = 1.0f / texture.width(); - imageIncrement[1] = 1.0f / texture.height(); - uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement); - uman.setMatrix4f(fCoefficientsUni, effect.coefficients()); - fEffectMatrix.setData(uman, - effect.getMatrix(), - drawEffect, - effect.texture(0)); -} - -GrBicubicEffect::GrBicubicEffect(GrTexture* texture, - const SkScalar coefficients[16]) - : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) { - 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]); - } - } -} - -GrBicubicEffect::~GrBicubicEffect() { -} - -const GrBackendEffectFactory& GrBicubicEffect::getFactory() const { - return GrTBackendEffectFactory::getInstance(); -} - -bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const { - const GrBicubicEffect& s = CastEffect(sBase); - return this->texture(0) == s.texture(0) && - !memcmp(fCoefficients, s.coefficients(), 16); -} - -void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { - // FIXME: Perhaps we can do better. - *validFlags = 0; - return; -} - -GR_DEFINE_EFFECT_TEST(GrBicubicEffect); - -GrEffectRef* GrBicubicEffect::TestCreate(SkMWCRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : - GrEffectUnitTest::kAlphaTextureIdx; - SkScalar coefficients[16]; - for (int i = 0; i < 16; i++) { - coefficients[i] = random->nextSScalar1(); - } - return GrBicubicEffect::Create(textures[texIdx], coefficients); -} - -bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) { - SkBitmap srcBM; - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &srcBM)) { - return false; - } - GrTexture* srcTexture = (GrTexture*) srcBM.getTexture(); - GrContext* context = srcTexture->getContext(); - - SkRect dstRect = SkRect::MakeWH(srcBM.width() * fScale.fWidth, - srcBM.height() * fScale.fHeight); - - GrTextureDesc desc; - desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fWidth = SkScalarCeilToInt(dstRect.width()); - desc.fHeight = SkScalarCeilToInt(dstRect.height()); - desc.fConfig = kSkia8888_GrPixelConfig; - - GrAutoScratchTexture ast(context, desc); - SkAutoTUnref dst(ast.detach()); - if (!dst) { - return false; - } - GrContext::AutoRenderTarget art(context, dst->asRenderTarget()); - GrPaint paint; - paint.colorStage(0)->setEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->unref(); - SkRect srcRect; - srcBM.getBounds(&srcRect); - context->drawRectToRect(paint, dstRect, srcRect); - return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, result); -} -#endif - -/////////////////////////////////////////////////////////////////////////////// diff --git a/gfx/skia/src/effects/SkBitmapSource.cpp b/gfx/skia/src/effects/SkBitmapSource.cpp deleted file mode 100644 index 854df9df226b..000000000000 --- a/gfx/skia/src/effects/SkBitmapSource.cpp +++ /dev/null @@ -1,29 +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. - */ - -#include "SkBitmapSource.h" - -SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap) - : INHERITED(0), - fBitmap(bitmap) { -} - -SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) { - fBitmap.unflatten(buffer); -} - -void SkBitmapSource::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - fBitmap.flatten(buffer); -} - -bool SkBitmapSource::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) { - *result = fBitmap; - return true; -} diff --git a/gfx/skia/src/effects/SkBlendImageFilter.cpp b/gfx/skia/src/effects/SkBlendImageFilter.cpp deleted file mode 100644 index 330e87d76d8e..000000000000 --- a/gfx/skia/src/effects/SkBlendImageFilter.cpp +++ /dev/null @@ -1,321 +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. - */ - -#include "SkBlendImageFilter.h" -#include "SkCanvas.h" -#include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" -#if SK_SUPPORT_GPU -#include "GrContext.h" -#include "gl/GrGLEffect.h" -#include "gl/GrGLEffectMatrix.h" -#include "GrTBackendEffectFactory.h" -#include "SkImageFilterUtils.h" -#endif - -namespace { - -SkXfermode::Mode modeToXfermode(SkBlendImageFilter::Mode mode) { - switch (mode) { - case SkBlendImageFilter::kNormal_Mode: - return SkXfermode::kSrcOver_Mode; - case SkBlendImageFilter::kMultiply_Mode: - return SkXfermode::kMultiply_Mode; - case SkBlendImageFilter::kScreen_Mode: - return SkXfermode::kScreen_Mode; - case SkBlendImageFilter::kDarken_Mode: - return SkXfermode::kDarken_Mode; - case SkBlendImageFilter::kLighten_Mode: - return SkXfermode::kLighten_Mode; - } - SkASSERT(0); - return SkXfermode::kSrcOver_Mode; -} - -}; - -/////////////////////////////////////////////////////////////////////////////// - -SkBlendImageFilter::SkBlendImageFilter(SkBlendImageFilter::Mode mode, SkImageFilter* background, SkImageFilter* foreground) - : INHERITED(background, foreground), fMode(mode) -{ -} - -SkBlendImageFilter::~SkBlendImageFilter() { -} - -SkBlendImageFilter::SkBlendImageFilter(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) -{ - fMode = (SkBlendImageFilter::Mode) buffer.readInt(); -} - -void SkBlendImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeInt((int) fMode); -} - -bool SkBlendImageFilter::onFilterImage(Proxy* proxy, - const SkBitmap& src, - const SkMatrix& ctm, - SkBitmap* dst, - SkIPoint* offset) { - SkBitmap background, foreground = src; - SkImageFilter* backgroundInput = getBackgroundInput(); - SkImageFilter* foregroundInput = getForegroundInput(); - SkASSERT(NULL != backgroundInput); - if (!backgroundInput->filterImage(proxy, src, ctm, &background, offset)) { - return false; - } - if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) { - return false; - } - SkAutoLockPixels alp_foreground(foreground), alp_background(background); - if (!foreground.getPixels() || !background.getPixels()) { - return false; - } - dst->setConfig(background.config(), background.width(), background.height()); - dst->allocPixels(); - SkCanvas canvas(*dst); - SkPaint paint; - paint.setXfermodeMode(SkXfermode::kSrc_Mode); - canvas.drawBitmap(background, 0, 0, &paint); - paint.setXfermodeMode(modeToXfermode(fMode)); - canvas.drawBitmap(foreground, 0, 0, &paint); - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -#if SK_SUPPORT_GPU -class GrGLBlendEffect : public GrGLEffect { -public: - GrGLBlendEffect(const GrBackendEffectFactory&, const GrDrawEffect&); - virtual ~GrGLBlendEffect(); - - virtual void emitCode(GrGLShaderBuilder*, - const GrDrawEffect&, - EffectKey, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray&) SK_OVERRIDE; - - static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; - -private: - static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType; - - SkBlendImageFilter::Mode fMode; - GrGLEffectMatrix fForegroundEffectMatrix; - GrGLEffectMatrix fBackgroundEffectMatrix; - - typedef GrGLEffect INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -class GrBlendEffect : public GrEffect { -public: - static GrEffectRef* Create(SkBlendImageFilter::Mode mode, - GrTexture* foreground, - GrTexture* background) { - AutoEffectUnref effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, background))); - return CreateEffectRef(effect); - } - - virtual ~GrBlendEffect(); - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; - SkBlendImageFilter::Mode mode() const { return fMode; } - - typedef GrGLBlendEffect GLEffect; - static const char* Name() { return "Blend"; } - - virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; - -private: - virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; - - GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, GrTexture* background); - GrTextureAccess fForegroundAccess; - GrTextureAccess fBackgroundAccess; - SkBlendImageFilter::Mode fMode; - - typedef GrEffect INHERITED; -}; - -bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) { - SkBitmap backgroundBM; - if (!SkImageFilterUtils::GetInputResultGPU(getBackgroundInput(), proxy, src, &backgroundBM)) { - return false; - } - GrTexture* background = (GrTexture*) backgroundBM.getTexture(); - SkBitmap foregroundBM; - if (!SkImageFilterUtils::GetInputResultGPU(getForegroundInput(), proxy, src, &foregroundBM)) { - return false; - } - GrTexture* foreground = (GrTexture*) foregroundBM.getTexture(); - GrContext* context = foreground->getContext(); - - GrTextureDesc desc; - desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; - desc.fWidth = src.width(); - desc.fHeight = src.height(); - desc.fConfig = kSkia8888_GrPixelConfig; - - GrAutoScratchTexture ast(context, desc); - SkAutoTUnref dst(ast.detach()); - - GrContext::AutoRenderTarget art(context, dst->asRenderTarget()); - - GrPaint paint; - paint.colorStage(0)->setEffect( - GrBlendEffect::Create(fMode, foreground, background))->unref(); - SkRect srcRect; - src.getBounds(&srcRect); - context->drawRect(paint, srcRect); - return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result); -} - -/////////////////////////////////////////////////////////////////////////////// - -GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode, - GrTexture* foreground, - GrTexture* background) - : fForegroundAccess(foreground) - , fBackgroundAccess(background) - , fMode(mode) { - this->addTextureAccess(&fForegroundAccess); - this->addTextureAccess(&fBackgroundAccess); -} - -GrBlendEffect::~GrBlendEffect() { -} - -bool GrBlendEffect::onIsEqual(const GrEffect& sBase) const { - const GrBlendEffect& s = CastEffect(sBase); - return fForegroundAccess.getTexture() == s.fForegroundAccess.getTexture() && - fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture() && - fMode == s.fMode; -} - -const GrBackendEffectFactory& GrBlendEffect::getFactory() const { - return GrTBackendEffectFactory::getInstance(); -} - -void GrBlendEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { - // The output alpha is always 1 - (1 - FGa) * (1 - BGa). So if either FGa or BGa is known to - // be one then the output alpha is one. (This effect ignores its input. We should have a way to - // communicate this.) - if (GrPixelConfigIsOpaque(fForegroundAccess.getTexture()->config()) || - GrPixelConfigIsOpaque(fBackgroundAccess.getTexture()->config())) { - *validFlags = kA_GrColorComponentFlag; - *color = GrColorPackRGBA(0, 0, 0, 0xff); - } else { - *validFlags = 0; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory, - const GrDrawEffect& drawEffect) - : INHERITED(factory) - , fMode(drawEffect.castEffect().mode()) - , fForegroundEffectMatrix(kCoordsType) - , fBackgroundEffectMatrix(kCoordsType) { -} - -GrGLBlendEffect::~GrGLBlendEffect() { -} - -void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect&, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) { - const char* fgCoords; - const char* bgCoords; - GrSLType fgCoordsType = fForegroundEffectMatrix.emitCode(builder, key, &fgCoords, NULL, "FG"); - GrSLType bgCoordsType = fBackgroundEffectMatrix.emitCode(builder, key, &bgCoords, NULL, "BG"); - - const char* bgColor = "bgColor"; - const char* fgColor = "fgColor"; - - builder->fsCodeAppendf("\t\tvec4 %s = ", fgColor); - builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, - samplers[0], - fgCoords, - fgCoordsType); - builder->fsCodeAppend(";\n"); - - builder->fsCodeAppendf("\t\tvec4 %s = ", bgColor); - builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType, - samplers[1], - bgCoords, - bgCoordsType); - builder->fsCodeAppendf(";\n"); - - builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.b);\n", outputColor, bgColor, fgColor); - switch (fMode) { - case SkBlendImageFilter::kNormal_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + %s.rgb;\n", outputColor, fgColor, bgColor, fgColor); - break; - case SkBlendImageFilter::kMultiply_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb + %s.rgb * %s.rgb;\n", outputColor, fgColor, bgColor, bgColor, fgColor, fgColor, bgColor); - break; - case SkBlendImageFilter::kScreen_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - %s.rgb * %s.rgb;\n", outputColor, bgColor, fgColor, fgColor, bgColor); - break; - case SkBlendImageFilter::kDarken_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, (1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, fgColor, bgColor, fgColor, bgColor, fgColor, bgColor); - break; - case SkBlendImageFilter::kLighten_Mode: - builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, (1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, fgColor, bgColor, fgColor, bgColor, fgColor, bgColor); - break; - } -} - -void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { - const GrBlendEffect& blend = drawEffect.castEffect(); - GrTexture* fgTex = blend.texture(0); - GrTexture* bgTex = blend.texture(1); - fForegroundEffectMatrix.setData(uman, - GrEffect::MakeDivByTextureWHMatrix(fgTex), - drawEffect, - fgTex); - fBackgroundEffectMatrix.setData(uman, - GrEffect::MakeDivByTextureWHMatrix(bgTex), - drawEffect, - bgTex); - -} - -GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const GrBlendEffect& blend = drawEffect.castEffect(); - - GrTexture* fgTex = blend.texture(0); - GrTexture* bgTex = blend.texture(1); - - EffectKey fgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(fgTex), - drawEffect, - kCoordsType, - fgTex); - - EffectKey bgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(bgTex), - drawEffect, - kCoordsType, - bgTex); - bgKey <<= GrGLEffectMatrix::kKeyBits; - EffectKey modeKey = blend.mode() << (2 * GrGLEffectMatrix::kKeyBits); - - return modeKey | bgKey | fgKey; -} -#endif diff --git a/gfx/skia/src/effects/SkBlurImageFilter.cpp b/gfx/skia/src/effects/SkBlurImageFilter.cpp deleted file mode 100644 index 4885070264ea..000000000000 --- a/gfx/skia/src/effects/SkBlurImageFilter.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBitmap.h" -#include "SkBlurImageFilter.h" -#include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" -#if SK_SUPPORT_GPU -#include "GrContext.h" -#include "SkImageFilterUtils.h" -#endif - -SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) { - fSigma.fWidth = buffer.readScalar(); - fSigma.fHeight = buffer.readScalar(); -} - -SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input) - : INHERITED(input), fSigma(SkSize::Make(sigmaX, sigmaY)) { - SkASSERT(sigmaX >= 0 && sigmaY >= 0); -} - -void SkBlurImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeScalar(fSigma.fWidth); - buffer.writeScalar(fSigma.fHeight); -} - -static void boxBlurX(const SkBitmap& src, SkBitmap* dst, int kernelSize, - int leftOffset, int rightOffset) -{ - int width = src.width(), height = src.height(); - int rightBorder = SkMin32(rightOffset + 1, width); - for (int y = 0; y < height; ++y) { - int sumA = 0, sumR = 0, sumG = 0, sumB = 0; - SkPMColor* p = src.getAddr32(0, y); - for (int i = 0; i < rightBorder; ++i) { - sumA += SkGetPackedA32(*p); - sumR += SkGetPackedR32(*p); - sumG += SkGetPackedG32(*p); - sumB += SkGetPackedB32(*p); - p++; - } - - const SkColor* sptr = src.getAddr32(0, y); - SkColor* dptr = dst->getAddr32(0, y); - for (int x = 0; x < width; ++x) { - *dptr = SkPackARGB32(sumA / kernelSize, - sumR / kernelSize, - sumG / kernelSize, - sumB / kernelSize); - if (x >= leftOffset) { - SkColor l = *(sptr - leftOffset); - sumA -= SkGetPackedA32(l); - sumR -= SkGetPackedR32(l); - sumG -= SkGetPackedG32(l); - sumB -= SkGetPackedB32(l); - } - if (x + rightOffset + 1 < width) { - SkColor r = *(sptr + rightOffset + 1); - sumA += SkGetPackedA32(r); - sumR += SkGetPackedR32(r); - sumG += SkGetPackedG32(r); - sumB += SkGetPackedB32(r); - } - sptr++; - dptr++; - } - } -} - -static void boxBlurY(const SkBitmap& src, SkBitmap* dst, int kernelSize, - int topOffset, int bottomOffset) -{ - int width = src.width(), height = src.height(); - int bottomBorder = SkMin32(bottomOffset + 1, height); - int srcStride = src.rowBytesAsPixels(); - int dstStride = dst->rowBytesAsPixels(); - for (int x = 0; x < width; ++x) { - int sumA = 0, sumR = 0, sumG = 0, sumB = 0; - SkColor* p = src.getAddr32(x, 0); - for (int i = 0; i < bottomBorder; ++i) { - sumA += SkGetPackedA32(*p); - sumR += SkGetPackedR32(*p); - sumG += SkGetPackedG32(*p); - sumB += SkGetPackedB32(*p); - p += srcStride; - } - - const SkColor* sptr = src.getAddr32(x, 0); - SkColor* dptr = dst->getAddr32(x, 0); - for (int y = 0; y < height; ++y) { - *dptr = SkPackARGB32(sumA / kernelSize, - sumR / kernelSize, - sumG / kernelSize, - sumB / kernelSize); - if (y >= topOffset) { - SkColor l = *(sptr - topOffset * srcStride); - sumA -= SkGetPackedA32(l); - sumR -= SkGetPackedR32(l); - sumG -= SkGetPackedG32(l); - sumB -= SkGetPackedB32(l); - } - if (y + bottomOffset + 1 < height) { - SkColor r = *(sptr + (bottomOffset + 1) * srcStride); - sumA += SkGetPackedA32(r); - sumR += SkGetPackedR32(r); - sumG += SkGetPackedG32(r); - sumB += SkGetPackedB32(r); - } - sptr += srcStride; - dptr += dstStride; - } - } -} - -static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset, int *highOffset) -{ - float pi = SkScalarToFloat(SK_ScalarPI); - int d = static_cast(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f)); - *kernelSize = d; - if (d % 2 == 1) { - *lowOffset = *highOffset = (d - 1) / 2; - *kernelSize3 = d; - } else { - *highOffset = d / 2; - *lowOffset = *highOffset - 1; - *kernelSize3 = d + 1; - } -} - -bool SkBlurImageFilter::onFilterImage(Proxy* proxy, - const SkBitmap& source, const SkMatrix& ctm, - SkBitmap* dst, SkIPoint* offset) { - SkBitmap src = this->getInputResult(0, proxy, source, ctm, offset); - if (src.config() != SkBitmap::kARGB_8888_Config) { - return false; - } - - SkAutoLockPixels alp(src); - if (!src.getPixels()) { - return false; - } - - dst->setConfig(src.config(), src.width(), src.height()); - dst->allocPixels(); - int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX; - int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY; - getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX); - getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY); - - if (kernelSizeX < 0 || kernelSizeY < 0) { - return false; - } - - if (kernelSizeX == 0 && kernelSizeY == 0) { - src.copyTo(dst, dst->config()); - return true; - } - - SkBitmap temp; - temp.setConfig(dst->config(), dst->width(), dst->height()); - if (!temp.allocPixels()) { - return false; - } - - if (kernelSizeX > 0 && kernelSizeY > 0) { - boxBlurX(src, &temp, kernelSizeX, lowOffsetX, highOffsetX); - boxBlurY(temp, dst, kernelSizeY, lowOffsetY, highOffsetY); - boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX); - boxBlurY(temp, dst, kernelSizeY, highOffsetY, lowOffsetY); - boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX); - boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY); - } else if (kernelSizeX > 0) { - boxBlurX(src, dst, kernelSizeX, lowOffsetX, highOffsetX); - boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX); - boxBlurX(temp, dst, kernelSizeX3, highOffsetX, highOffsetX); - } else if (kernelSizeY > 0) { - boxBlurY(src, dst, kernelSizeY, lowOffsetY, highOffsetY); - boxBlurY(*dst, &temp, kernelSizeY, highOffsetY, lowOffsetY); - boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY); - } - return true; -} - -bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) { -#if SK_SUPPORT_GPU - SkBitmap input; - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &input)) { - return false; - } - GrTexture* source = (GrTexture*) input.getTexture(); - SkRect rect; - src.getBounds(&rect); - SkAutoTUnref tex(source->getContext()->gaussianBlur(source, false, rect, - fSigma.width(), fSigma.height())); - return SkImageFilterUtils::WrapTexture(tex, src.width(), src.height(), result); -#else - SkDEBUGFAIL("Should not call in GPU-less build"); - return false; -#endif -} diff --git a/gfx/skia/src/effects/SkBlurMask.h b/gfx/skia/src/effects/SkBlurMask.h deleted file mode 100644 index b60c2aadccbc..000000000000 --- a/gfx/skia/src/effects/SkBlurMask.h +++ /dev/null @@ -1,57 +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 SkBlurMask_DEFINED -#define SkBlurMask_DEFINED - -#include "SkShader.h" -#include "SkMask.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(SkMask *dst, const SkRect &src, - SkScalar radius, Style style, - SkIPoint *margin = NULL, - SkMask::CreateMode createMode=SkMask::kComputeBoundsAndRenderImage_CreateMode); - static bool Blur(SkMask* dst, const SkMask& src, - SkScalar radius, Style style, Quality quality, - SkIPoint* margin = NULL); - static bool BlurSeparable(SkMask* dst, const SkMask& src, - SkScalar radius, Style style, Quality quality, - SkIPoint* margin = NULL); - - - // the "ground truth" blur does a gaussian convolution; it's slow - // but useful for comparison purposes. - - static bool BlurGroundTruth(SkMask* dst, const SkMask& src, - SkScalar provided_radius, Style style, - SkIPoint* margin = NULL); - -private: - static bool Blur(SkMask* dst, const SkMask& src, - SkScalar radius, Style style, Quality quality, - SkIPoint* margin, bool separable); -}; - -#endif diff --git a/gfx/skia/src/effects/SkBlurMaskFilter.cpp b/gfx/skia/src/effects/SkBlurMaskFilter.cpp deleted file mode 100644 index 3d0fb81e4858..000000000000 --- a/gfx/skia/src/effects/SkBlurMaskFilter.cpp +++ /dev/null @@ -1,375 +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 "SkBlurMaskFilter.h" -#include "SkBlurMask.h" -#include "SkFlattenableBuffers.h" -#include "SkMaskFilter.h" -#include "SkBounder.h" -#include "SkRasterClip.h" -#include "SkRTConf.h" -#include "SkStringUtils.h" - -class SkBlurMaskFilterImpl : public SkMaskFilter { -public: - SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle, - uint32_t flags); - - // overrides from SkMaskFilter - virtual SkMask::Format getFormat() const SK_OVERRIDE; - virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, - SkIPoint* margin) const SK_OVERRIDE; - - virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE; - virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; - - SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) - -protected: - virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&, - const SkIRect& clipBounds, - NinePatch*) const SK_OVERRIDE; - - bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix, - SkIPoint* margin, SkMask::CreateMode createMode) const; - -private: - SkScalar fRadius; - SkBlurMaskFilter::BlurStyle fBlurStyle; - uint32_t fBlurFlags; - - SkBlurMaskFilterImpl(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - - typedef SkMaskFilter INHERITED; -}; - -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) { - return NULL; - } - - return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags)); -} - -/////////////////////////////////////////////////////////////////////////////// - -SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius, - SkBlurMaskFilter::BlurStyle style, - uint32_t flags) - : fRadius(radius), 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(radius >= 0); - SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount); - SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag); -} - -SkMask::Format SkBlurMaskFilterImpl::getFormat() const { - return SkMask::kA8_Format; -} - -bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, - const SkMatrix& matrix, - SkIPoint* margin) const{ - SkScalar radius; - if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { - radius = fRadius; - } else { - radius = matrix.mapRadius(fRadius); - } - - // To avoid unseemly allocation requests (esp. for finite platforms like - // handset) we limit the radius so something manageable. (as opposed to - // a request like 10,000) - static const SkScalar MAX_RADIUS = SkIntToScalar(128); - radius = SkMinScalar(radius, MAX_RADIUS); - SkBlurMask::Quality blurQuality = - (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ? - SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality; - -#ifndef SK_DISABLE_SEPARABLE_MASK_BLUR - return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle, - blurQuality, margin); -#else - return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle, - blurQuality, margin); -#endif -} - -bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r, - const SkMatrix& matrix, - SkIPoint* margin, SkMask::CreateMode createMode) const{ - SkScalar radius; - if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) { - radius = fRadius; - } else { - radius = matrix.mapRadius(fRadius); - } - - // To avoid unseemly allocation requests (esp. for finite platforms like - // handset) we limit the radius so something manageable. (as opposed to - // a request like 10,000) - static const SkScalar MAX_RADIUS = SkIntToScalar(128); - radius = SkMinScalar(radius, MAX_RADIUS); - - return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle, - margin, createMode); -} - -#include "SkCanvas.h" - -static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) { - rects[0].roundOut(&mask->fBounds); - mask->fRowBytes = SkAlign4(mask->fBounds.width()); - mask->fFormat = SkMask::kA8_Format; - size_t size = mask->computeImageSize(); - mask->fImage = SkMask::AllocImage(size); - if (NULL == mask->fImage) { - return false; - } - sk_bzero(mask->fImage, size); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kA8_Config, - mask->fBounds.width(), mask->fBounds.height(), - mask->fRowBytes); - bitmap.setPixels(mask->fImage); - - SkCanvas canvas(bitmap); - canvas.translate(-SkIntToScalar(mask->fBounds.left()), - -SkIntToScalar(mask->fBounds.top())); - - SkPaint paint; - paint.setAntiAlias(true); - - if (1 == count) { - canvas.drawRect(rects[0], paint); - } else { - // todo: do I need a fast way to do this? - SkPath path; - path.addRect(rects[0]); - path.addRect(rects[1]); - path.setFillType(SkPath::kEvenOdd_FillType); - canvas.drawPath(path, paint); - } - return true; -} - -static bool rect_exceeds(const SkRect& r, SkScalar v) { - return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v || - r.width() > v || r.height() > v; -} - -#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, - const SkMatrix& matrix, - const SkIRect& clipBounds, - NinePatch* patch) const { - if (count < 1 || count > 2) { - return kUnimplemented_FilterReturn; - } - - // 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) { - return kUnimplemented_FilterReturn; - } - - // TODO: take clipBounds into account to limit our coordinates up front - // for now, just skip too-large src rects (to take the old code path). - if (rect_exceeds(rects[0], SkIntToScalar(32767))) { - return kUnimplemented_FilterReturn; - } - - SkIPoint margin; - SkMask srcM, dstM; - rects[0].roundOut(&srcM.fBounds); - srcM.fImage = NULL; - srcM.fFormat = SkMask::kA8_Format; - srcM.fRowBytes = 0; - - bool filterResult = false; - if (count == 1 && c_analyticBlurNinepatch) { - // special case for fast rect blur - // don't actually do the blur the first time, just compute the correct size - filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin, - SkMask::kJustComputeBounds_CreateMode); - } else { - filterResult = this->filterMask(&dstM, srcM, matrix, &margin); - } - - if (!filterResult) { - return kFalse_FilterReturn; - } - - /* - * smallR is the smallest version of 'rect' that will still guarantee that - * we get the same blur results on all edges, plus 1 center row/col that is - * representative of the extendible/stretchable edges of the ninepatch. - * Since our actual edge may be fractional we inset 1 more to be sure we - * don't miss any interior blur. - * x is an added pixel of blur, and { and } are the (fractional) edge - * pixels from the original rect. - * - * x x { x x .... x x } x x - * - * Thus, in this case, we inset by a total of 5 (on each side) beginning - * with our outer-rect (dstM.fBounds) - */ - SkRect smallR[2]; - SkIPoint center; - - // +2 is from +1 for each edge (to account for possible fractional edges - int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2; - int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2; - SkIRect innerIR; - - if (1 == count) { - innerIR = srcM.fBounds; - center.set(smallW, smallH); - } else { - SkASSERT(2 == count); - rects[1].roundIn(&innerIR); - center.set(smallW + (innerIR.left() - srcM.fBounds.left()), - smallH + (innerIR.top() - srcM.fBounds.top())); - } - - // +1 so we get a clean, stretchable, center row/col - smallW += 1; - smallH += 1; - - // we want the inset amounts to be integral, so we don't change any - // fractional phase on the fRight or fBottom of our smallR. - const SkScalar dx = SkIntToScalar(innerIR.width() - smallW); - const SkScalar dy = SkIntToScalar(innerIR.height() - smallH); - if (dx < 0 || dy < 0) { - // we're too small, relative to our blur, to break into nine-patch, - // so we ask to have our normal filterMask() be called. - return kUnimplemented_FilterReturn; - } - - smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy); - SkASSERT(!smallR[0].isEmpty()); - if (2 == count) { - smallR[1].set(rects[1].left(), rects[1].top(), - rects[1].right() - dx, rects[1].bottom() - dy); - SkASSERT(!smallR[1].isEmpty()); - } - - if (count > 1 || !c_analyticBlurNinepatch) { - if (!drawRectsIntoMask(smallR, count, &srcM)) { - return kFalse_FilterReturn; - } - - SkAutoMaskFreeImage amf(srcM.fImage); - - if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { - return kFalse_FilterReturn; - } - } else { - if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, - SkMask::kComputeBoundsAndRenderImage_CreateMode)) { - return kFalse_FilterReturn; - } - } - patch->fMask.fBounds.offsetTo(0, 0); - patch->fOuterRect = dstM.fBounds; - patch->fCenter = center; - return kTrue_FilterReturn; -} - -void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, - SkRect* dst) const { - dst->set(src.fLeft - fRadius, src.fTop - fRadius, - src.fRight + fRadius, src.fBottom + fRadius); -} - -SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer) - : SkMaskFilter(buffer) { - fRadius = buffer.readScalar(); - fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt(); - fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag; - SkASSERT(fRadius >= 0); - SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount); -} - -void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeScalar(fRadius); - buffer.writeInt(fBlurStyle); - buffer.writeUInt(fBlurFlags); -} - -static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = { - SkMaskFilter::kNormal_BlurType, - SkMaskFilter::kSolid_BlurType, - SkMaskFilter::kOuter_BlurType, - SkMaskFilter::kInner_BlurType, -}; - -SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const { - if (info) { - info->fRadius = fRadius; - info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag); - info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag); - } - return gBlurStyle2BlurType[fBlurStyle]; -} - -#ifdef SK_DEVELOPER -void SkBlurMaskFilterImpl::toString(SkString* str) const { - str->append("SkBlurMaskFilterImpl: ("); - - str->append("radius: "); - str->appendScalar(fRadius); - str->append(" "); - - static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = { - "normal", "solid", "outer", "inner" - }; - - str->appendf("style: %s ", gStyleName[fBlurStyle]); - str->append("flags: ("); - if (fBlurFlags) { - bool needSeparator = false; - SkAddFlagToString(str, - SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag), - "IgnoreXform", &needSeparator); - SkAddFlagToString(str, - SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag), - "HighQuality", &needSeparator); - } else { - str->append("None"); - } - str->append("))"); -} -#endif - -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl) -SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END diff --git a/gfx/skia/src/effects/SkColorFilters.cpp b/gfx/skia/src/effects/SkColorFilters.cpp deleted file mode 100644 index a14babc7cd9e..000000000000 --- a/gfx/skia/src/effects/SkColorFilters.cpp +++ /dev/null @@ -1,492 +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 "SkBlitRow.h" -#include "SkColorFilter.h" -#include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" -#include "SkUtils.h" - -#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1) - -// baseclass for filters that store a color and mode -class SkModeColorFilter : public SkColorFilter { -public: - SkModeColorFilter(SkColor color) { - fColor = color; - fMode = ILLEGAL_XFERMODE_MODE; - this->updateCache(); - } - - SkModeColorFilter(SkColor color, SkXfermode::Mode mode) { - fColor = color; - fMode = mode; - this->updateCache(); - }; - - SkColor getColor() const { return fColor; } - SkXfermode::Mode getMode() const { return fMode; } - bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; } - SkPMColor getPMColor() const { return fPMColor; } - - virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE { - if (ILLEGAL_XFERMODE_MODE == fMode) { - return false; - } - - if (color) { - *color = fColor; - } - if (mode) { - *mode = fMode; - } - return true; - } - - virtual uint32_t getFlags() const SK_OVERRIDE { - return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0; - } - - virtual void filterSpan(const SkPMColor shader[], int count, - SkPMColor result[]) const SK_OVERRIDE { - SkPMColor color = fPMColor; - SkXfermodeProc proc = fProc; - - for (int i = 0; i < count; i++) { - result[i] = proc(color, shader[i]); - } - } - - virtual void filterSpan16(const uint16_t shader[], int count, - uint16_t result[]) const SK_OVERRIDE { - SkASSERT(this->getFlags() & kHasFilter16_Flag); - - SkPMColor color = fPMColor; - SkXfermodeProc16 proc16 = fProc16; - - for (int i = 0; i < count; i++) { - result[i] = proc16(color, shader[i]); - } - } - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter) - -protected: - virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { - this->INHERITED::flatten(buffer); - buffer.writeColor(fColor); - buffer.writeUInt(fMode); - } - - SkModeColorFilter(SkFlattenableReadBuffer& buffer) { - fColor = buffer.readColor(); - fMode = (SkXfermode::Mode)buffer.readUInt(); - this->updateCache(); - } - -private: - SkColor fColor; - SkXfermode::Mode fMode; - // cache - SkPMColor fPMColor; - SkXfermodeProc fProc; - SkXfermodeProc16 fProc16; - - void updateCache() { - fPMColor = SkPreMultiplyColor(fColor); - fProc = SkXfermode::GetProc(fMode); - fProc16 = SkXfermode::GetProc16(fMode, fColor); - } - - typedef SkColorFilter INHERITED; -}; - -class Src_SkModeColorFilter : public SkModeColorFilter { -public: - Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {} - - virtual uint32_t getFlags() const SK_OVERRIDE { - if (SkGetPackedA32(this->getPMColor()) == 0xFF) { - return kAlphaUnchanged_Flag | kHasFilter16_Flag; - } else { - return 0; - } - } - - virtual void filterSpan(const SkPMColor shader[], int count, - SkPMColor result[]) const SK_OVERRIDE { - sk_memset32(result, this->getPMColor(), count); - } - - virtual void filterSpan16(const uint16_t shader[], int count, - uint16_t result[]) const SK_OVERRIDE { - SkASSERT(this->getFlags() & kHasFilter16_Flag); - sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count); - } - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter) - -protected: - Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) {} - -private: - typedef SkModeColorFilter INHERITED; -}; - -class SrcOver_SkModeColorFilter : public SkModeColorFilter { -public: - SrcOver_SkModeColorFilter(SkColor color) - : INHERITED(color, SkXfermode::kSrcOver_Mode) { - fColor32Proc = SkBlitRow::ColorProcFactory(); - } - - virtual uint32_t getFlags() const SK_OVERRIDE { - if (SkGetPackedA32(this->getPMColor()) == 0xFF) { - return kAlphaUnchanged_Flag | kHasFilter16_Flag; - } else { - return 0; - } - } - - virtual void filterSpan(const SkPMColor shader[], int count, - SkPMColor result[]) const SK_OVERRIDE { - fColor32Proc(result, shader, count, this->getPMColor()); - } - - virtual void filterSpan16(const uint16_t shader[], int count, - uint16_t result[]) const SK_OVERRIDE { - SkASSERT(this->getFlags() & kHasFilter16_Flag); - sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count); - } - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter) - -protected: - SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) { - fColor32Proc = SkBlitRow::ColorProcFactory(); - } - -private: - - SkBlitRow::ColorProc fColor32Proc; - - typedef SkModeColorFilter INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, - SkXfermode::Mode mode) { - unsigned alpha = SkColorGetA(color); - - // first collaps some modes if possible - - if (SkXfermode::kClear_Mode == mode) { - color = 0; - mode = SkXfermode::kSrc_Mode; - } else if (SkXfermode::kSrcOver_Mode == mode) { - if (0 == alpha) { - mode = SkXfermode::kDst_Mode; - } else if (255 == alpha) { - mode = SkXfermode::kSrc_Mode; - } - // else just stay srcover - } - - // weed out combinations that are noops, and just return null - if (SkXfermode::kDst_Mode == mode || - (0 == alpha && (SkXfermode::kSrcOver_Mode == mode || - SkXfermode::kDstOver_Mode == mode || - SkXfermode::kDstOut_Mode == mode || - SkXfermode::kSrcATop_Mode == mode || - SkXfermode::kXor_Mode == mode || - SkXfermode::kDarken_Mode == mode)) || - (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) { - return NULL; - } - - switch (mode) { - case SkXfermode::kSrc_Mode: - return SkNEW_ARGS(Src_SkModeColorFilter, (color)); - case SkXfermode::kSrcOver_Mode: - return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color)); - default: - return SkNEW_ARGS(SkModeColorFilter, (color, mode)); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static inline unsigned pin(unsigned value, unsigned max) { - if (value > max) { - value = max; - } - 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; - } - } - - 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; - } - } - - 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; - } - } - - 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); - } - } - - 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; - } - } - - 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); - } - -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() { - 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)); -} - -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/gfx/skia/src/effects/SkImageFilterUtils.cpp b/gfx/skia/src/effects/SkImageFilterUtils.cpp deleted file mode 100644 index 2dfb33d73cdd..000000000000 --- a/gfx/skia/src/effects/SkImageFilterUtils.cpp +++ /dev/null @@ -1,46 +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) { - SkASSERT(texture->config() == kSkia8888_GrPixelConfig); - result->setConfig(SkBitmap::kARGB_8888_Config, width, height); - result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref(); - return true; -} - -bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result) { - if (!filter) { - *result = src; - return true; - } else if (filter->canFilterImageGPU()) { - return filter->filterImageGPU(proxy, src, result); - } else { - SkIPoint offset; - if (filter->filterImage(proxy, src, SkMatrix(), result, &offset)) { - if (!result->getTexture()) { - GrContext* context = ((GrTexture *) src.getTexture())->getContext(); - GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, - *result, NULL); - result->setPixelRef(new SkGrPixelRef(resultTex))->unref(); - GrUnlockAndUnrefCachedBitmapTexture(resultTex); - } - return true; - } else { - return false; - } - } -} -#endif diff --git a/gfx/skia/src/effects/SkOffsetImageFilter.cpp b/gfx/skia/src/effects/SkOffsetImageFilter.cpp deleted file mode 100644 index 2a4f71c0b207..000000000000 --- a/gfx/skia/src/effects/SkOffsetImageFilter.cpp +++ /dev/null @@ -1,49 +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. - */ - -#include "SkOffsetImageFilter.h" -#include "SkBitmap.h" -#include "SkMatrix.h" -#include "SkFlattenableBuffers.h" - -bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, - const SkMatrix& matrix, - SkBitmap* result, - SkIPoint* loc) { - SkBitmap src = this->getInputResult(0, proxy, source, matrix, loc); - SkVector vec; - matrix.mapVectors(&vec, &fOffset, 1); - - loc->fX += SkScalarRoundToInt(vec.fX); - loc->fY += SkScalarRoundToInt(vec.fY); - *result = src; - return true; -} - -bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, - SkIRect* dst) { - SkVector vec; - ctm.mapVectors(&vec, &fOffset, 1); - - *dst = src; - dst->offset(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY)); - return true; -} - -void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writePoint(fOffset); -} - -SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, - SkImageFilter* input) : INHERITED(input) { - fOffset.set(dx, dy); -} - -SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - buffer.readPoint(&fOffset); -} diff --git a/gfx/skia/src/effects/SkRectShaderImageFilter.cpp b/gfx/skia/src/effects/SkRectShaderImageFilter.cpp deleted file mode 100644 index f5466cc2ccd8..000000000000 --- a/gfx/skia/src/effects/SkRectShaderImageFilter.cpp +++ /dev/null @@ -1,58 +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 "SkRectShaderImageFilter.h" -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkFlattenableBuffers.h" -#include "SkShader.h" - -SkRectShaderImageFilter* SkRectShaderImageFilter::Create(SkShader* s, const SkRect& rect) { - SkASSERT(s); - return SkNEW_ARGS(SkRectShaderImageFilter, (s, rect)); -} - -SkRectShaderImageFilter::SkRectShaderImageFilter(SkShader* s, const SkRect& rect) - : INHERITED(NULL) - , fShader(s) - , fRect(rect) { - SkASSERT(s); - s->ref(); -} - -SkRectShaderImageFilter::SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) { - fShader = buffer.readFlattenableT(); - buffer.readRect(&fRect); -} - -void SkRectShaderImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - - buffer.writeFlattenable(fShader); - buffer.writeRect(fRect); -} - -SkRectShaderImageFilter::~SkRectShaderImageFilter() { - SkSafeUnref(fShader); -} - -bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy, - const SkBitmap& source, - const SkMatrix& matrix, - SkBitmap* result, - SkIPoint* loc) { - SkAutoTUnref device(proxy->createDevice(SkScalarCeilToInt(fRect.width()), - SkScalarCeilToInt(fRect.height()))); - SkCanvas canvas(device.get()); - SkPaint paint; - paint.setShader(fShader); - canvas.drawRect(fRect, paint); - *result = device.get()->accessBitmap(false); - return true; -} diff --git a/gfx/skia/src/effects/SkTestImageFilters.cpp b/gfx/skia/src/effects/SkTestImageFilters.cpp deleted file mode 100755 index 9af61c8cbfca..000000000000 --- a/gfx/skia/src/effects/SkTestImageFilters.cpp +++ /dev/null @@ -1,129 +0,0 @@ - -#include "SkTestImageFilters.h" -#include "SkCanvas.h" -#include "SkDevice.h" -#include "SkFlattenableBuffers.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 -// with the following: -// -// SkCanvas canvas(device); -// SkAutoTUnref aur(device); -// -class OwnDeviceCanvas : public SkCanvas { -public: - OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) { - SkSafeUnref(device); - } -}; - -/////////////////////////////////////////////////////////////////////////////// - -SkComposeImageFilter::~SkComposeImageFilter() { -} - -bool SkComposeImageFilter::onFilterImage(Proxy* proxy, - const SkBitmap& src, - const SkMatrix& ctm, - SkBitmap* result, - SkIPoint* loc) { - SkImageFilter* outer = getInput(0); - SkImageFilter* inner = getInput(1); - - if (!outer && !inner) { - return false; - } - - if (!outer || !inner) { - return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, loc); - } - - SkBitmap tmp; - return inner->filterImage(proxy, src, ctm, &tmp, loc) && - outer->filterImage(proxy, tmp, ctm, result, loc); -} - -bool SkComposeImageFilter::onFilterBounds(const SkIRect& src, - const SkMatrix& ctm, - SkIRect* dst) { - SkImageFilter* outer = getInput(0); - SkImageFilter* inner = getInput(1); - - if (!outer && !inner) { - return false; - } - - if (!outer || !inner) { - return (outer ? outer : inner)->filterBounds(src, ctm, dst); - } - - SkIRect tmp; - return inner->filterBounds(src, ctm, &tmp) && - outer->filterBounds(tmp, ctm, dst); -} - -SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { -} - -/////////////////////////////////////////////////////////////////////////////// - -bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, - const SkMatrix&, - SkBitmap* result, SkIPoint*) { - SkScalar scale = fScale; - if (scale > SK_Scalar1 || scale <= 0) { - return false; - } - - int dstW = SkScalarRoundToInt(src.width() * scale); - int dstH = SkScalarRoundToInt(src.height() * scale); - if (dstW < 1) { - dstW = 1; - } - if (dstH < 1) { - dstH = 1; - } - - SkBitmap tmp; - - // downsample - { - SkDevice* dev = proxy->createDevice(dstW, dstH); - if (NULL == dev) { - return false; - } - OwnDeviceCanvas canvas(dev); - SkPaint paint; - - paint.setFilterBitmap(true); - canvas.scale(scale, scale); - canvas.drawBitmap(src, 0, 0, &paint); - tmp = dev->accessBitmap(false); - } - - // upscale - { - SkDevice* dev = proxy->createDevice(src.width(), src.height()); - if (NULL == dev) { - return false; - } - OwnDeviceCanvas canvas(dev); - - SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()), - SkIntToScalar(src.height())); - canvas.drawBitmapRect(tmp, NULL, r, NULL); - *result = dev->accessBitmap(false); - } - return true; -} - -void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - - buffer.writeScalar(fScale); -} - -SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - fScale = buffer.readScalar(); -} diff --git a/gfx/skia/src/effects/gradients/SkGradientTileProc.cpp b/gfx/skia/src/effects/gradients/SkGradientTileProc.cpp deleted file mode 100644 index abdb347fcb8a..000000000000 --- a/gfx/skia/src/effects/gradients/SkGradientTileProc.cpp +++ /dev/null @@ -1,38 +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 "SkGradientShaderPriv.h" - -// Clamp - -SkFixed clamp_tileproc(SkFixed x) { - return SkClampMax(x, 0xFFFF); -} - -// Repeat - -SkFixed repeat_tileproc(SkFixed x) { - return x & 0xFFFF; -} - -// Mirror - -// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly. -// See http://code.google.com/p/skia/issues/detail?id=472 -#if defined(_MSC_VER) && (_MSC_VER >= 1600) -#pragma optimize("", off) -#endif - -SkFixed mirror_tileproc(SkFixed x) { - int s = x << 15 >> 31; - return (x ^ s) & 0xFFFF; -} - -#if defined(_MSC_VER) && (_MSC_VER >= 1600) -#pragma optimize("", on) -#endif - diff --git a/gfx/skia/src/gpu/GrAAHairLinePathRenderer.cpp b/gfx/skia/src/gpu/GrAAHairLinePathRenderer.cpp deleted file mode 100644 index fdb6009857ce..000000000000 --- a/gfx/skia/src/gpu/GrAAHairLinePathRenderer.cpp +++ /dev/null @@ -1,849 +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 "GrAAHairLinePathRenderer.h" - -#include "GrContext.h" -#include "GrDrawState.h" -#include "GrDrawTargetCaps.h" -#include "GrEffect.h" -#include "GrGpu.h" -#include "GrIndexBuffer.h" -#include "GrPathUtils.h" -#include "GrTBackendEffectFactory.h" -#include "SkGeometry.h" -#include "SkStroke.h" -#include "SkTemplates.h" - -#include "gl/GrGLEffect.h" -#include "gl/GrGLSL.h" - -namespace { -// quadratics are rendered as 5-sided polys in order to bound the -// AA stroke around the center-curve. See comments in push_quad_index_buffer and -// bloat_quad. -static const int kVertsPerQuad = 5; -static const int kIdxsPerQuad = 9; - -static const int kVertsPerLineSeg = 4; -static const int kIdxsPerLineSeg = 6; - -static const int kNumQuadsInIdxBuffer = 256; -static const size_t kQuadIdxSBufize = kIdxsPerQuad * - sizeof(uint16_t) * - kNumQuadsInIdxBuffer; - -bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { - uint16_t* data = (uint16_t*) qIdxBuffer->lock(); - bool tempData = NULL == data; - if (tempData) { - data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); - } - for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { - - // Each quadratic is rendered as a five sided polygon. This poly bounds - // the quadratic's bounding triangle but has been expanded so that the - // 1-pixel wide area around the curve is inside the poly. - // If a,b,c are the original control points then the poly a0,b0,c0,c1,a1 - // that is rendered would look like this: - // b0 - // b - // - // a0 c0 - // a c - // a1 c1 - // Each is drawn as three triangles specified by these 9 indices: - int baseIdx = i * kIdxsPerQuad; - uint16_t baseVert = (uint16_t)(i * kVertsPerQuad); - data[0 + baseIdx] = baseVert + 0; // a0 - data[1 + baseIdx] = baseVert + 1; // a1 - data[2 + baseIdx] = baseVert + 2; // b0 - data[3 + baseIdx] = baseVert + 2; // b0 - data[4 + baseIdx] = baseVert + 4; // c1 - data[5 + baseIdx] = baseVert + 3; // c0 - data[6 + baseIdx] = baseVert + 1; // a1 - data[7 + baseIdx] = baseVert + 4; // c1 - data[8 + baseIdx] = baseVert + 2; // b0 - } - if (tempData) { - bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize); - delete[] data; - return ret; - } else { - qIdxBuffer->unlock(); - return true; - } -} -} - -GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { - const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer(); - if (NULL == lIdxBuffer) { - return NULL; - } - GrGpu* gpu = context->getGpu(); - GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); - SkAutoTUnref qIdxBuffer(qIdxBuf); - if (NULL == qIdxBuf || - !push_quad_index_data(qIdxBuf)) { - return NULL; - } - return SkNEW_ARGS(GrAAHairLinePathRenderer, - (context, lIdxBuffer, qIdxBuf)); -} - -GrAAHairLinePathRenderer::GrAAHairLinePathRenderer( - const GrContext* context, - const GrIndexBuffer* linesIndexBuffer, - const GrIndexBuffer* quadsIndexBuffer) { - fLinesIndexBuffer = linesIndexBuffer; - linesIndexBuffer->ref(); - fQuadsIndexBuffer = quadsIndexBuffer; - quadsIndexBuffer->ref(); -} - -GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { - fLinesIndexBuffer->unref(); - fQuadsIndexBuffer->unref(); -} - -namespace { - -typedef SkTArray PtArray; -#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> -typedef SkTArray IntArray; - -// Takes 178th time of logf on Z600 / VC2010 -int get_float_exp(float x) { - GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); -#if GR_DEBUG - static bool tested; - if (!tested) { - tested = true; - GrAssert(get_float_exp(0.25f) == -2); - GrAssert(get_float_exp(0.3f) == -2); - GrAssert(get_float_exp(0.5f) == -1); - GrAssert(get_float_exp(1.f) == 0); - GrAssert(get_float_exp(2.f) == 1); - GrAssert(get_float_exp(2.5f) == 1); - GrAssert(get_float_exp(8.f) == 3); - GrAssert(get_float_exp(100.f) == 6); - GrAssert(get_float_exp(1000.f) == 9); - GrAssert(get_float_exp(1024.f) == 10); - GrAssert(get_float_exp(3000000.f) == 21); - } -#endif - const int* iptr = (const int*)&x; - return (((*iptr) & 0x7f800000) >> 23) - 127; -} - -// we subdivide the quads to avoid huge overfill -// if it returns -1 then should be drawn as lines -int num_quad_subdivs(const SkPoint p[3]) { - static const SkScalar gDegenerateToLineTol = SK_Scalar1; - static const SkScalar gDegenerateToLineTolSqd = - SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); - - if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || - p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { - return -1; - } - - SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); - if (dsqd < gDegenerateToLineTolSqd) { - return -1; - } - - if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { - return -1; - } - - // tolerance of triangle height in pixels - // tuned on windows Quadro FX 380 / Z600 - // trade off of fill vs cpu time on verts - // maybe different when do this using gpu (geo or tess shaders) - static const SkScalar gSubdivTol = 175 * SK_Scalar1; - - if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) { - return 0; - } else { - static const int kMaxSub = 4; - // subdividing the quad reduces d by 4. so we want x = log4(d/tol) - // = 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); - 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 - } -} - -/** - * Generates the lines and quads to be rendered. Lines are always recorded in - * device space. We will do a device space bloat to account for the 1pixel - * thickness. - * Quads are recorded in device space unless m contains - * perspective, then in they are in src space. We do this because we will - * subdivide large quads to reduce over-fill. This subdivision has to be - * performed before applying the perspective matrix. - */ -int generate_lines_and_quads(const SkPath& path, - const SkMatrix& m, - const GrIRect& devClipBounds, - PtArray* lines, - PtArray* quads, - IntArray* quadSubdivCnts) { - SkPath::Iter iter(path, false); - - int totalQuadCount = 0; - GrRect bounds; - GrIRect ibounds; - - bool persp = m.hasPerspective(); - - for (;;) { - GrPoint pts[4]; - GrPoint devPts[4]; - GrPathCmd cmd = (GrPathCmd)iter.next(pts); - switch (cmd) { - case kMove_PathCmd: - break; - case kLine_PathCmd: - m.mapPoints(devPts, pts, 2); - bounds.setBounds(devPts, 2); - bounds.outset(SK_Scalar1, SK_Scalar1); - bounds.roundOut(&ibounds); - if (SkIRect::Intersects(devClipBounds, ibounds)) { - SkPoint* pts = lines->push_back_n(2); - pts[0] = devPts[0]; - pts[1] = devPts[1]; - } - break; - case kQuadratic_PathCmd: - m.mapPoints(devPts, pts, 3); - bounds.setBounds(devPts, 3); - bounds.outset(SK_Scalar1, SK_Scalar1); - bounds.roundOut(&ibounds); - if (SkIRect::Intersects(devClipBounds, ibounds)) { - int subdiv = num_quad_subdivs(devPts); - GrAssert(subdiv >= -1); - if (-1 == subdiv) { - SkPoint* pts = lines->push_back_n(4); - pts[0] = devPts[0]; - pts[1] = devPts[1]; - pts[2] = devPts[1]; - pts[3] = devPts[2]; - } else { - // when in perspective keep quads in src space - SkPoint* qPts = persp ? pts : devPts; - SkPoint* pts = quads->push_back_n(3); - pts[0] = qPts[0]; - pts[1] = qPts[1]; - pts[2] = qPts[2]; - quadSubdivCnts->push_back() = subdiv; - totalQuadCount += 1 << subdiv; - } - } - break; - case kCubic_PathCmd: - m.mapPoints(devPts, pts, 4); - bounds.setBounds(devPts, 4); - bounds.outset(SK_Scalar1, SK_Scalar1); - bounds.roundOut(&ibounds); - if (SkIRect::Intersects(devClipBounds, ibounds)) { - PREALLOC_PTARRAY(32) q; - // we don't need a direction if we aren't constraining the subdivision - static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction; - // We convert cubics to quadratics (for now). - // In perspective have to do conversion in src space. - if (persp) { - SkScalar tolScale = - GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m, - path.getBounds()); - GrPathUtils::convertCubicToQuads(pts, tolScale, false, kDummyDir, &q); - } else { - GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q); - } - for (int i = 0; i < q.count(); i += 3) { - SkPoint* qInDevSpace; - // bounds has to be calculated in device space, but q is - // in src space when there is perspective. - if (persp) { - m.mapPoints(devPts, &q[i], 3); - bounds.setBounds(devPts, 3); - qInDevSpace = devPts; - } else { - bounds.setBounds(&q[i], 3); - qInDevSpace = &q[i]; - } - bounds.outset(SK_Scalar1, SK_Scalar1); - bounds.roundOut(&ibounds); - if (SkIRect::Intersects(devClipBounds, ibounds)) { - int subdiv = num_quad_subdivs(qInDevSpace); - GrAssert(subdiv >= -1); - if (-1 == subdiv) { - SkPoint* pts = lines->push_back_n(4); - // lines should always be in device coords - pts[0] = qInDevSpace[0]; - pts[1] = qInDevSpace[1]; - pts[2] = qInDevSpace[1]; - pts[3] = qInDevSpace[2]; - } else { - SkPoint* pts = quads->push_back_n(3); - // q is already in src space when there is no - // perspective and dev coords otherwise. - pts[0] = q[0 + i]; - pts[1] = q[1 + i]; - pts[2] = q[2 + i]; - quadSubdivCnts->push_back() = subdiv; - totalQuadCount += 1 << subdiv; - } - } - } - } - break; - case kClose_PathCmd: - break; - case kEnd_PathCmd: - return totalQuadCount; - } - } -} - -struct Vertex { - GrPoint fPos; - union { - struct { - SkScalar fA; - SkScalar fB; - SkScalar fC; - } fLine; - GrVec fQuadCoord; - struct { - SkScalar fBogus[4]; - }; - }; -}; -GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint)); - -void intersect_lines(const SkPoint& ptA, const SkVector& normA, - const SkPoint& ptB, const SkVector& normB, - SkPoint* result) { - - SkScalar lineAW = -normA.dot(ptA); - SkScalar lineBW = -normB.dot(ptB); - - SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - - SkScalarMul(normA.fY, normB.fX); - wInv = SkScalarInvert(wInv); - - result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); - result->fX = SkScalarMul(result->fX, wInv); - - result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); - result->fY = SkScalarMul(result->fY, wInv); -} - -void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, - const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { - GrAssert(!toDevice == !toSrc); - // original quad is specified by tri a,b,c - SkPoint a = qpts[0]; - SkPoint b = qpts[1]; - SkPoint c = qpts[2]; - - // this should be in the src space, not dev coords, when we have perspective - GrPathUtils::QuadUVMatrix DevToUV(qpts); - - if (toDevice) { - toDevice->mapPoints(&a, 1); - toDevice->mapPoints(&b, 1); - toDevice->mapPoints(&c, 1); - } - // make a new poly where we replace a and c by a 1-pixel wide edges orthog - // to edges ab and bc: - // - // before | after - // | b0 - // b | - // | - // | a0 c0 - // a c | a1 c1 - // - // edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c, - // respectively. - Vertex& a0 = verts[0]; - Vertex& a1 = verts[1]; - Vertex& b0 = verts[2]; - Vertex& c0 = verts[3]; - Vertex& c1 = verts[4]; - - SkVector ab = b; - ab -= a; - SkVector ac = c; - ac -= a; - SkVector cb = b; - cb -= c; - - // We should have already handled degenerates - GrAssert(ab.length() > 0 && cb.length() > 0); - - ab.normalize(); - SkVector abN; - abN.setOrthog(ab, SkVector::kLeft_Side); - if (abN.dot(ac) > 0) { - abN.negate(); - } - - cb.normalize(); - SkVector cbN; - cbN.setOrthog(cb, SkVector::kLeft_Side); - if (cbN.dot(ac) < 0) { - cbN.negate(); - } - - a0.fPos = a; - a0.fPos += abN; - a1.fPos = a; - a1.fPos -= abN; - - c0.fPos = c; - c0.fPos += cbN; - c1.fPos = c; - c1.fPos -= cbN; - - intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); - - if (toSrc) { - toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); - } - DevToUV.apply(verts); -} - -void add_quads(const SkPoint p[3], - int subdiv, - const SkMatrix* toDevice, - const SkMatrix* toSrc, - Vertex** vert) { - GrAssert(subdiv >= 0); - if (subdiv) { - SkPoint newP[5]; - SkChopQuadAtHalf(p, newP); - add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); - add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); - } else { - bloat_quad(p, toDevice, toSrc, *vert); - *vert += kVertsPerQuad; - } -} - -void add_line(const SkPoint p[2], - int rtHeight, - const SkMatrix* toSrc, - Vertex** vert) { - const SkPoint& a = p[0]; - const SkPoint& b = p[1]; - - SkVector orthVec = b; - orthVec -= a; - - if (orthVec.setLength(SK_Scalar1)) { - orthVec.setOrthog(orthVec); - - SkScalar lineC = -(a.dot(orthVec)); - for (int i = 0; i < kVertsPerLineSeg; ++i) { - (*vert)[i].fPos = (i < 2) ? a : b; - if (0 == i || 3 == i) { - (*vert)[i].fPos -= orthVec; - } else { - (*vert)[i].fPos += orthVec; - } - (*vert)[i].fLine.fA = orthVec.fX; - (*vert)[i].fLine.fB = orthVec.fY; - (*vert)[i].fLine.fC = lineC; - } - if (NULL != toSrc) { - toSrc->mapPointsWithStride(&(*vert)->fPos, - sizeof(Vertex), - kVertsPerLineSeg); - } - } else { - // just make it degenerate and likely offscreen - (*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax); - (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); - (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); - (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); - } - - *vert += kVertsPerLineSeg; -} - -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The output of this effect is a hairline edge for quadratics. - * Quadratic specified by 0=u^2-v canonical coords. u and v are the first - * two components of the vertex attribute. Uses unsigned distance. - * Coverage is min(0, 1-distance). 3rd & 4th component unused. - * Requires shader derivative instruction support. - */ -class HairQuadEdgeEffect : public GrEffect { -public: - - static GrEffectRef* Create() { - // we go through this so we only have one copy of each effect - static GrEffectRef* gHairQuadEdgeEffectRef = - CreateEffectRef(AutoEffectUnref(SkNEW(HairQuadEdgeEffect))); - static SkAutoTUnref gUnref(gHairQuadEdgeEffectRef); - - gHairQuadEdgeEffectRef->ref(); - return gHairQuadEdgeEffectRef; - } - - virtual ~HairQuadEdgeEffect() {} - - static const char* Name() { return "HairQuadEdge"; } - - virtual void getConstantColorComponents(GrColor* color, - uint32_t* validFlags) const SK_OVERRIDE { - *validFlags = 0; - } - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { - return GrTBackendEffectFactory::getInstance(); - } - - class GLEffect : public GrGLEffect { - public: - GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) - : INHERITED (factory) {} - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - const char *vsName, *fsName; - const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); - - SkAssertResult(builder->enableFeature( - GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); - builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName); - - builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); - builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n" - "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n", - fsName, fsName); - builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName, - fsName); - builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n"); - builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); - - SkString modulate; - GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - return 0x0; - } - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} - - private: - typedef GrGLEffect INHERITED; - }; - -private: - HairQuadEdgeEffect() { - this->addVertexAttrib(kVec4f_GrSLType); - } - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { - return true; - } - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - -GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); - -GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, - GrContext*, - const GrDrawTargetCaps& caps, - GrTexture*[]) { - // Doesn't work without derivative instructions. - return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;} - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The output of this effect is a 1-pixel wide line. - * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component unused. - */ -class HairLineEdgeEffect : public GrEffect { -public: - - static GrEffectRef* Create() { - // we go through this so we only have one copy of each effect - static GrEffectRef* gHairLineEdgeEffectRef = - CreateEffectRef(AutoEffectUnref(SkNEW(HairLineEdgeEffect))); - static SkAutoTUnref gUnref(gHairLineEdgeEffectRef); - - gHairLineEdgeEffectRef->ref(); - return gHairLineEdgeEffectRef; - } - - virtual ~HairLineEdgeEffect() {} - - static const char* Name() { return "HairLineEdge"; } - - virtual void getConstantColorComponents(GrColor* color, - uint32_t* validFlags) const SK_OVERRIDE { - *validFlags = 0; - } - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { - return GrTBackendEffectFactory::getInstance(); - } - - class GLEffect : public GrGLEffect { - public: - GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) - : INHERITED (factory) {} - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - const char *vsName, *fsName; - const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); - - builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsName); - - builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n", - builder->fragmentPosition(), fsName); - builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n"); - - SkString modulate; - GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - return 0x0; - } - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} - - private: - typedef GrGLEffect INHERITED; - }; - -private: - HairLineEdgeEffect() { - this->addVertexAttrib(kVec4f_GrSLType); - } - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { - return true; - } - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - -GR_DEFINE_EFFECT_TEST(HairLineEdgeEffect); - -GrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random, - GrContext*, - const GrDrawTargetCaps& caps, - GrTexture*[]) { - return HairLineEdgeEffect::Create(); -} - -/////////////////////////////////////////////////////////////////////////////// - -bool GrAAHairLinePathRenderer::createGeom( - const SkPath& path, - GrDrawTarget* target, - int* lineCnt, - int* quadCnt, - GrDrawTarget::AutoReleaseGeometry* arg) { - GrDrawState* drawState = target->drawState(); - int rtHeight = drawState->getRenderTarget()->height(); - - GrIRect devClipBounds; - target->getClip()->getConservativeBounds(drawState->getRenderTarget(), - &devClipBounds); - - // position + edge - static const GrVertexAttrib kAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} - }; - SkMatrix viewM = drawState->getViewMatrix(); - - PREALLOC_PTARRAY(128) lines; - PREALLOC_PTARRAY(128) quads; - IntArray qSubdivs; - *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, - &lines, &quads, &qSubdivs); - - *lineCnt = lines.count() / 2; - int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; - - target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs)); - GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); - - if (!arg->set(target, vertCnt, 0)) { - return false; - } - - Vertex* verts = reinterpret_cast(arg->vertices()); - - const SkMatrix* toDevice = NULL; - const SkMatrix* toSrc = NULL; - SkMatrix ivm; - - if (viewM.hasPerspective()) { - if (viewM.invert(&ivm)) { - toDevice = &viewM; - toSrc = &ivm; - } - } - - for (int i = 0; i < *lineCnt; ++i) { - add_line(&lines[2*i], rtHeight, toSrc, &verts); - } - - int unsubdivQuadCnt = quads.count() / 3; - for (int i = 0; i < unsubdivQuadCnt; ++i) { - GrAssert(qSubdivs[i] >= 0); - add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); - } - - return true; -} - -bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, - const SkStrokeRec& stroke, - const GrDrawTarget* target, - bool antiAlias) const { - if (!stroke.isHairlineStyle() || !antiAlias) { - return false; - } - - static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | - SkPath::kQuad_SegmentMask; - if (!target->caps()->shaderDerivativeSupport() && - (gReqDerivMask & path.getSegmentMasks())) { - return false; - } - return true; -} - -bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, - const SkStrokeRec&, - GrDrawTarget* target, - bool antiAlias) { - - int lineCnt; - int quadCnt; - GrDrawTarget::AutoReleaseGeometry arg; - if (!this->createGeom(path, - target, - &lineCnt, - &quadCnt, - &arg)) { - return false; - } - - GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); - GrDrawState* drawState = target->drawState(); - - GrDrawState::AutoDeviceCoordDraw adcd; - // createGeom transforms the geometry to device space when the matrix does not have - // perspective. - if (!drawState->getViewMatrix().hasPerspective()) { - adcd.set(drawState); - if (!adcd.succeeded()) { - return false; - } - } - - // TODO: See whether rendering lines as degenerate quads improves perf - // when we have a mix - - enum { - // the edge effects share this stage with glyph rendering - // (kGlyphMaskStage in GrTextContext) && SW path rendering - // (kPathMaskStage in GrSWMaskHelper) - kEdgeEffectStage = GrPaint::kTotalStages, - }; - static const int kEdgeAttrIndex = 1; - - GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); - GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); - - target->setIndexSourceToBuffer(fLinesIndexBuffer); - int lines = 0; - int nBufLines = fLinesIndexBuffer->maxQuads(); - drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref(); - while (lines < lineCnt) { - int n = GrMin(lineCnt - lines, nBufLines); - target->drawIndexed(kTriangles_GrPrimitiveType, - kVertsPerLineSeg*lines, // startV - 0, // startI - kVertsPerLineSeg*n, // vCount - kIdxsPerLineSeg*n); // iCount - lines += n; - } - - target->setIndexSourceToBuffer(fQuadsIndexBuffer); - int quads = 0; - drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref(); - while (quads < quadCnt) { - int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); - target->drawIndexed(kTriangles_GrPrimitiveType, - 4 * lineCnt + kVertsPerQuad*quads, // startV - 0, // startI - kVertsPerQuad*n, // vCount - kIdxsPerQuad*n); // iCount - quads += n; - } - - return true; -} diff --git a/gfx/skia/src/gpu/GrAARectRenderer.cpp b/gfx/skia/src/gpu/GrAARectRenderer.cpp deleted file mode 100644 index 0093b08078ed..000000000000 --- a/gfx/skia/src/gpu/GrAARectRenderer.cpp +++ /dev/null @@ -1,273 +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 "GrAARectRenderer.h" -#include "GrRefCnt.h" -#include "GrGpu.h" - -SK_DEFINE_INST_COUNT(GrAARectRenderer) - -namespace { - -static void aa_rect_attributes(bool useCoverage, const GrVertexAttrib** attribs, int* count) { - static const GrVertexAttrib kCoverageAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding}, - }; - static const GrVertexAttrib kColorAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding}, - }; - *attribs = useCoverage ? kCoverageAttribs : kColorAttribs; - *count = 2; -} - -static void set_inset_fan(GrPoint* pts, size_t stride, - const GrRect& r, SkScalar dx, SkScalar dy) { - pts->setRectFan(r.fLeft + dx, r.fTop + dy, - r.fRight - dx, r.fBottom - dy, stride); -} - -}; - -void GrAARectRenderer::reset() { - GrSafeSetNull(fAAFillRectIndexBuffer); - GrSafeSetNull(fAAStrokeRectIndexBuffer); -} - -static const uint16_t gFillAARectIdx[] = { - 0, 1, 5, 5, 4, 0, - 1, 2, 6, 6, 5, 1, - 2, 3, 7, 7, 6, 2, - 3, 0, 4, 4, 7, 3, - 4, 5, 6, 6, 7, 4, -}; - -static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx); -static const int kVertsPerAAFillRect = 8; -static const int kNumAAFillRectsInIndexBuffer = 256; - -GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) { - static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect * - sizeof(uint16_t) * - kNumAAFillRectsInIndexBuffer; - - if (NULL == fAAFillRectIndexBuffer) { - fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false); - if (NULL != fAAFillRectIndexBuffer) { - uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock(); - bool useTempData = (NULL == data); - if (useTempData) { - data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect); - } - for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) { - // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around - // the inner rect (for AA) and 2 for the inner rect. - int baseIdx = i * kIndicesPerAAFillRect; - uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect); - for (int j = 0; j < kIndicesPerAAFillRect; ++j) { - data[baseIdx+j] = baseVert + gFillAARectIdx[j]; - } - } - if (useTempData) { - if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) { - GrCrash("Can't get AA Fill Rect indices into buffer!"); - } - SkDELETE_ARRAY(data); - } else { - fAAFillRectIndexBuffer->unlock(); - } - } - } - - return fAAFillRectIndexBuffer; -} - -static const uint16_t gStrokeAARectIdx[] = { - 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, - 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, - 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, - 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, - - 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, - 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, - 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, - 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, - - 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, - 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, - 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, - 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, -}; - -int GrAARectRenderer::aaStrokeRectIndexCount() { - return GR_ARRAY_COUNT(gStrokeAARectIdx); -} - -GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) { - if (NULL == fAAStrokeRectIndexBuffer) { - fAAStrokeRectIndexBuffer = - gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false); - if (NULL != fAAStrokeRectIndexBuffer) { -#if GR_DEBUG - bool updated = -#endif - fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx, - sizeof(gStrokeAARectIdx)); - GR_DEBUGASSERT(updated); - } - } - return fAAStrokeRectIndexBuffer; -} - -void GrAARectRenderer::fillAARect(GrGpu* gpu, - GrDrawTarget* target, - const GrRect& devRect, - bool useVertexCoverage) { - GrDrawState* drawState = target->drawState(); - - const GrVertexAttrib* attribs; - int attribCount; - aa_rect_attributes(useVertexCoverage, &attribs, &attribCount); - drawState->setVertexAttribs(attribs, attribCount); - - GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); - if (!geo.succeeded()) { - GrPrintf("Failed to get space for vertices!\n"); - return; - } - - GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); - if (NULL == indexBuffer) { - GrPrintf("Failed to create index buffer!\n"); - return; - } - - intptr_t verts = reinterpret_cast(geo.vertices()); - size_t vsize = drawState->getVertexSize(); - GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize); - - GrPoint* fan0Pos = reinterpret_cast(verts); - GrPoint* fan1Pos = reinterpret_cast(verts + 4 * vsize); - - set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf); - set_inset_fan(fan1Pos, vsize, devRect, SK_ScalarHalf, SK_ScalarHalf); - - verts += sizeof(GrPoint); - for (int i = 0; i < 4; ++i) { - *reinterpret_cast(verts + i * vsize) = 0; - } - - GrColor innerColor; - if (useVertexCoverage) { - innerColor = 0xffffffff; - } else { - innerColor = target->getDrawState().getColor(); - } - - verts += 4 * vsize; - for (int i = 0; i < 4; ++i) { - *reinterpret_cast(verts + i * vsize) = innerColor; - } - - target->setIndexSourceToBuffer(indexBuffer); - target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, - kVertsPerAAFillRect, - kIndicesPerAAFillRect); -} - -void GrAARectRenderer::strokeAARect(GrGpu* gpu, - GrDrawTarget* target, - const GrRect& devRect, - const GrVec& devStrokeSize, - bool useVertexCoverage) { - GrDrawState* drawState = target->drawState(); - - const SkScalar& dx = devStrokeSize.fX; - const SkScalar& dy = devStrokeSize.fY; - const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); - const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); - - SkScalar spare; - { - SkScalar w = devRect.width() - dx; - SkScalar h = devRect.height() - dy; - spare = GrMin(w, h); - } - - if (spare <= 0) { - GrRect r(devRect); - r.inset(-rx, -ry); - this->fillAARect(gpu, target, r, useVertexCoverage); - return; - } - - const GrVertexAttrib* attribs; - int attribCount; - aa_rect_attributes(useVertexCoverage, &attribs, &attribCount); - drawState->setVertexAttribs(attribs, attribCount); - - GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); - if (!geo.succeeded()) { - GrPrintf("Failed to get space for vertices!\n"); - return; - } - GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu); - if (NULL == indexBuffer) { - GrPrintf("Failed to create index buffer!\n"); - return; - } - - intptr_t verts = reinterpret_cast(geo.vertices()); - size_t vsize = drawState->getVertexSize(); - GrAssert(sizeof(GrPoint) + 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(verts); - GrPoint* fan1Pos = reinterpret_cast(verts + 4 * vsize); - GrPoint* fan2Pos = reinterpret_cast(verts + 8 * vsize); - GrPoint* fan3Pos = reinterpret_cast(verts + 12 * vsize); - - set_inset_fan(fan0Pos, vsize, devRect, - -rx - SK_ScalarHalf, -ry - SK_ScalarHalf); - set_inset_fan(fan1Pos, vsize, devRect, - -rx + SK_ScalarHalf, -ry + SK_ScalarHalf); - set_inset_fan(fan2Pos, vsize, devRect, - rx - SK_ScalarHalf, ry - SK_ScalarHalf); - set_inset_fan(fan3Pos, vsize, devRect, - rx + SK_ScalarHalf, ry + SK_ScalarHalf); - - // The outermost rect has 0 coverage - verts += sizeof(GrPoint); - for (int i = 0; i < 4; ++i) { - *reinterpret_cast(verts + i * vsize) = 0; - } - - // The inner two rects have full coverage - GrColor innerColor; - if (useVertexCoverage) { - innerColor = 0xffffffff; - } else { - innerColor = target->getDrawState().getColor(); - } - verts += 4 * vsize; - for (int i = 0; i < 8; ++i) { - *reinterpret_cast(verts + i * vsize) = innerColor; - } - - // The innermost rect has full coverage - verts += 8 * vsize; - for (int i = 0; i < 4; ++i) { - *reinterpret_cast(verts + i * vsize) = 0; - } - - target->setIndexSourceToBuffer(indexBuffer); - target->drawIndexed(kTriangles_GrPrimitiveType, - 0, 0, 16, aaStrokeRectIndexCount()); -} diff --git a/gfx/skia/src/gpu/GrAtlas.cpp b/gfx/skia/src/gpu/GrAtlas.cpp deleted file mode 100644 index c1d6d3d693c4..000000000000 --- a/gfx/skia/src/gpu/GrAtlas.cpp +++ /dev/null @@ -1,206 +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 "GrAtlas.h" -#include "GrContext.h" -#include "GrGpu.h" -#include "GrRectanizer.h" -#include "GrPlotMgr.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 341 -#define GR_ATLAS_HEIGHT 341 - -#define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH) -#define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT) - -#endif - -/////////////////////////////////////////////////////////////////////////////// - -#define BORDER 1 - -#if GR_DEBUG - static int gCounter; -#endif - -GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) { - fAtlasMgr = mgr; // just a pointer, not an owner - fNext = NULL; - fTexture = mgr->getTexture(format); // we're not an owner, just a pointer - fPlot.set(plotX, plotY); - - fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER, - GR_ATLAS_HEIGHT - BORDER); - - fMaskFormat = format; - -#if GR_DEBUG -// GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter); - gCounter += 1; -#endif -} - -GrAtlas::~GrAtlas() { - fAtlasMgr->freePlot(fPlot.fX, fPlot.fY); - - delete fRects; - -#if GR_DEBUG - --gCounter; -// GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter); -#endif -} - -static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) { - loc->fX += plot.fX * GR_ATLAS_WIDTH; - loc->fY += plot.fY * GR_ATLAS_HEIGHT; -} - -static uint8_t* zerofill(uint8_t* ptr, int count) { - while (--count >= 0) { - *ptr++ = 0; - } - return ptr; -} - -bool GrAtlas::addSubImage(int width, int height, const void* image, - GrIPoint16* loc) { - if (!fRects->addRect(width + BORDER, height + BORDER, loc)) { - return false; - } - - SkAutoSMalloc<1024> storage; - int dstW = width + 2*BORDER; - int dstH = height + 2*BORDER; - if (BORDER) { - const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat); - const size_t dstRB = dstW * bpp; - uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB); - Gr_bzero(dst, dstRB); // zero top row - dst += dstRB; - for (int y = 0; y < height; y++) { - dst = zerofill(dst, bpp); // zero left edge - memcpy(dst, image, width * bpp); - dst += width * bpp; - dst = zerofill(dst, bpp); // zero right edge - image = (const void*)((const char*)image + width * bpp); - } - Gr_bzero(dst, dstRB); // zero bottom row - image = storage.get(); - } - adjustForPlot(loc, fPlot); - 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; - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) { - fGpu = gpu; - gpu->ref(); - Gr_bzero(fTexture, sizeof(fTexture)); - fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT)); -} - -GrAtlasMgr::~GrAtlasMgr() { - for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) { - GrSafeUnref(fTexture[i]); - } - delete fPlotMgr; - fGpu->unref(); -} - -static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) { - switch (format) { - case kA8_GrMaskFormat: - return kAlpha_8_GrPixelConfig; - case kA565_GrMaskFormat: - return kRGB_565_GrPixelConfig; - case kA888_GrMaskFormat: - return kSkia8888_GrPixelConfig; - default: - GrAssert(!"unknown maskformat"); - } - return kUnknown_GrPixelConfig; -} - -GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas, - int width, int height, const void* image, - GrMaskFormat format, - GrIPoint16* loc) { - GrAssert(NULL == atlas || atlas->getMaskFormat() == format); - - if (atlas && atlas->addSubImage(width, height, image, loc)) { - return atlas; - } - - // If the above fails, then either we have no starting atlas, or the current - // one is full. Either way we need to allocate a new atlas - - GrIPoint16 plot; - if (!fPlotMgr->newPlot(&plot)) { - return NULL; - } - - GrAssert(0 == kA8_GrMaskFormat); - GrAssert(1 == kA565_GrMaskFormat); - if (NULL == fTexture[format]) { - // 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.fConfig = maskformat2pixelconfig(format); - - fTexture[format] = fGpu->createTexture(desc, NULL, 0); - if (NULL == fTexture[format]) { - return NULL; - } - } - - GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, format)); - if (!newAtlas->addSubImage(width, height, image, loc)) { - delete newAtlas; - return NULL; - } - - newAtlas->fNext = atlas; - return newAtlas; -} - -void GrAtlasMgr::freePlot(int x, int y) { - GrAssert(fPlotMgr->isBusy(x, y)); - fPlotMgr->freePlot(x, y); -} diff --git a/gfx/skia/src/gpu/GrAtlas.h b/gfx/skia/src/gpu/GrAtlas.h deleted file mode 100644 index 40a21545e15e..000000000000 --- a/gfx/skia/src/gpu/GrAtlas.h +++ /dev/null @@ -1,81 +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. - */ - - - -#ifndef GrAtlas_DEFINED -#define GrAtlas_DEFINED - -#include "GrPoint.h" -#include "GrTexture.h" - -class GrGpu; -class GrRectanizer; -class GrAtlasMgr; - -class GrAtlas { -public: - GrAtlas(GrAtlasMgr*, int plotX, int plotY, GrMaskFormat); - - int getPlotX() const { return fPlot.fX; } - int getPlotY() const { return fPlot.fY; } - GrMaskFormat getMaskFormat() const { return fMaskFormat; } - - GrTexture* texture() const { return fTexture; } - - bool addSubImage(int width, int height, const void*, GrIPoint16*); - - static void FreeLList(GrAtlas* atlas) { - while (atlas) { - GrAtlas* next = atlas->fNext; - delete atlas; - atlas = next; - } - } - - // testing - GrAtlas* nextAtlas() const { return fNext; } - -private: - ~GrAtlas(); // does not try to delete the fNext field - - GrAtlas* fNext; - GrTexture* fTexture; - GrRectanizer* fRects; - GrAtlasMgr* fAtlasMgr; - GrIPoint16 fPlot; - GrMaskFormat fMaskFormat; - - friend class GrAtlasMgr; -}; - -class GrPlotMgr; - -class GrAtlasMgr { -public: - GrAtlasMgr(GrGpu*); - ~GrAtlasMgr(); - - GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*, - GrMaskFormat, GrIPoint16*); - - GrTexture* getTexture(GrMaskFormat format) const { - GrAssert((unsigned)format < kCount_GrMaskFormats); - return fTexture[format]; - } - - // to be called by ~GrAtlas() - void freePlot(int x, int y); - -private: - GrGpu* fGpu; - GrTexture* fTexture[kCount_GrMaskFormats]; - GrPlotMgr* fPlotMgr; -}; - -#endif diff --git a/gfx/skia/src/gpu/GrBinHashKey.h b/gfx/skia/src/gpu/GrBinHashKey.h deleted file mode 100644 index 8fa53ef68a44..000000000000 --- a/gfx/skia/src/gpu/GrBinHashKey.h +++ /dev/null @@ -1,110 +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 GrBinHashKey_DEFINED -#define GrBinHashKey_DEFINED - -#include "GrTypes.h" - -/** - * Hash function class that can take a data chunk of any predetermined length. The hash function - * used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html). - * - * Keys are computed from ENTRY objects. ENTRY must be fully ordered by a member: - * int compare(const GrTBinHashKey& k); - * which returns negative if the ENTRY < k, 0 if it equals k, and positive if k < the ENTRY. - * Additionally, ENTRY must be flattenable into the key using setKeyData. - * - * This class satisfies the requirements to be a key for a GrTHashTable. - */ -template -class GrTBinHashKey { -public: - enum { kKeySize = KEY_SIZE }; - - GrTBinHashKey() { - this->reset(); - } - - GrTBinHashKey(const GrTBinHashKey& other) { - *this = other; - } - - GrTBinHashKey& operator=(const GrTBinHashKey& other) { - memcpy(this, &other, sizeof(*this)); - return *this; - } - - ~GrTBinHashKey() { - } - - void reset() { - fHash = 0; -#if GR_DEBUG - fIsValid = false; -#endif - } - - void setKeyData(const uint32_t* SK_RESTRICT data) { - GrAssert(GrIsALIGN4(KEY_SIZE)); - memcpy(&fData, data, KEY_SIZE); - - uint32_t hash = 0; - size_t len = KEY_SIZE; - while (len >= 4) { - hash += *data++; - hash += (fHash << 10); - hash ^= (hash >> 6); - len -= 4; - } - hash += (fHash << 3); - hash ^= (fHash >> 11); - hash += (fHash << 15); -#if GR_DEBUG - fIsValid = true; -#endif - fHash = hash; - } - - int compare(const GrTBinHashKey& key) const { - GrAssert(fIsValid && key.fIsValid); - return memcmp(fData, key.fData, KEY_SIZE); - } - - static bool EQ(const ENTRY& entry, const GrTBinHashKey& key) { - GrAssert(key.fIsValid); - return 0 == entry.compare(key); - } - - static bool LT(const ENTRY& entry, const GrTBinHashKey& key) { - GrAssert(key.fIsValid); - return entry.compare(key) < 0; - } - - uint32_t getHash() const { - GrAssert(fIsValid); - return fHash; - } - - const uint8_t* getData() const { - GrAssert(fIsValid); - return fData; - } - -private: - uint32_t fHash; - uint8_t fData[KEY_SIZE]; // Buffer for key storage - -#if GR_DEBUG -public: - bool fIsValid; -#endif -}; - -#endif diff --git a/gfx/skia/src/gpu/GrGeometryBuffer.cpp b/gfx/skia/src/gpu/GrGeometryBuffer.cpp deleted file mode 100644 index 202d0c33eea4..000000000000 --- a/gfx/skia/src/gpu/GrGeometryBuffer.cpp +++ /dev/null @@ -1,10 +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 "GrGeometryBuffer.h" - -SK_DEFINE_INST_COUNT(GrGeometryBuffer) diff --git a/gfx/skia/src/gpu/GrOvalRenderer.cpp b/gfx/skia/src/gpu/GrOvalRenderer.cpp deleted file mode 100644 index 65715f8a5be8..000000000000 --- a/gfx/skia/src/gpu/GrOvalRenderer.cpp +++ /dev/null @@ -1,524 +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 "GrOvalRenderer.h" - -#include "GrEffect.h" -#include "gl/GrGLEffect.h" -#include "gl/GrGLSL.h" -#include "GrTBackendEffectFactory.h" - -#include "GrDrawState.h" -#include "GrDrawTarget.h" -#include "SkStrokeRec.h" - -SK_DEFINE_INST_COUNT(GrOvalRenderer) - -namespace { - -struct CircleVertex { - GrPoint fPos; - GrPoint fCenter; - SkScalar fOuterRadius; - SkScalar fInnerRadius; -}; - -struct EllipseVertex { - GrPoint fPos; - GrPoint fCenter; - SkScalar fOuterXRadius; - SkScalar fOuterXYRatio; - SkScalar fInnerXRadius; - SkScalar fInnerXYRatio; -}; - -inline bool circle_stays_circle(const SkMatrix& m) { - return m.isSimilarity(); -} - -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The output of this effect is a modulation of the input color and coverage for a circle, - * specified as center_x, center_y, x_radius, inner radius and outer radius in window space - * (y-down). - */ - -class CircleEdgeEffect : public GrEffect { -public: - static GrEffectRef* Create(bool stroke) { - // we go through this so we only have one copy of each effect (stroked/filled) - static SkAutoTUnref gCircleStrokeEdgeEffectRef( - CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (true))))); - static SkAutoTUnref gCircleFillEdgeEffectRef( - CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (false))))); - - if (stroke) { - gCircleStrokeEdgeEffectRef.get()->ref(); - return gCircleStrokeEdgeEffectRef; - } else { - gCircleFillEdgeEffectRef.get()->ref(); - return gCircleFillEdgeEffectRef; - } - } - - virtual void getConstantColorComponents(GrColor* color, - uint32_t* validFlags) const SK_OVERRIDE { - *validFlags = 0; - } - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { - return GrTBackendEffectFactory::getInstance(); - } - - virtual ~CircleEdgeEffect() {} - - static const char* Name() { return "CircleEdge"; } - - inline bool isStroked() const { return fStroke; } - - class GLEffect : public GrGLEffect { - public: - GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) - : INHERITED (factory) {} - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - const CircleEdgeEffect& circleEffect = drawEffect.castEffect(); - const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName); - - const SkString* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); - - builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n", - builder->fragmentPosition(), fsName); - builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); - if (circleEffect.isStroked()) { - builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName); - builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); - } - SkString modulate; - GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const CircleEdgeEffect& circleEffect = drawEffect.castEffect(); - - return circleEffect.isStroked() ? 0x1 : 0x0; - } - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} - - private: - typedef GrGLEffect INHERITED; - }; - - -private: - CircleEdgeEffect(bool stroke) : GrEffect() { - this->addVertexAttrib(kVec4f_GrSLType); - fStroke = stroke; - } - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { - const CircleEdgeEffect& cee = CastEffect(other); - return cee.fStroke == fStroke; - } - - bool fStroke; - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - -GR_DEFINE_EFFECT_TEST(CircleEdgeEffect); - -GrEffectRef* CircleEdgeEffect::TestCreate(SkMWCRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - return CircleEdgeEffect::Create(random->nextBool()); -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The output of this effect is a modulation of the input color and coverage for an axis-aligned - * ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in window space (y-down). - */ - -class EllipseEdgeEffect : public GrEffect { -public: - static GrEffectRef* Create(bool stroke) { - // we go through this so we only have one copy of each effect (stroked/filled) - static SkAutoTUnref gEllipseStrokeEdgeEffectRef( - CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEffect, (true))))); - static SkAutoTUnref gEllipseFillEdgeEffectRef( - CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEffect, (false))))); - - if (stroke) { - gEllipseStrokeEdgeEffectRef.get()->ref(); - return gEllipseStrokeEdgeEffectRef; - } else { - gEllipseFillEdgeEffectRef.get()->ref(); - return gEllipseFillEdgeEffectRef; - } - } - - virtual void getConstantColorComponents(GrColor* color, - uint32_t* validFlags) const SK_OVERRIDE { - *validFlags = 0; - } - - virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { - return GrTBackendEffectFactory::getInstance(); - } - - virtual ~EllipseEdgeEffect() {} - - static const char* Name() { return "EllipseEdge"; } - - inline bool isStroked() const { return fStroke; } - - class GLEffect : public GrGLEffect { - public: - GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) - : INHERITED (factory) {} - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect(); - - const char *vsCenterName, *fsCenterName; - const char *vsEdgeName, *fsEdgeName; - - builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName); - const SkString* attr0Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); - builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_str()); - - builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fsEdgeName); - const SkString* attr1Name = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); - builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str()); - - // translate to origin - builder->fsCodeAppendf("\tvec2 outerOffset = (%s.xy - %s.xy);\n", - builder->fragmentPosition(), fsCenterName); - builder->fsCodeAppend("\tvec2 innerOffset = outerOffset;\n"); - // scale y by xRadius/yRadius - builder->fsCodeAppendf("\touterOffset.y *= %s.y;\n", fsEdgeName); - builder->fsCodeAppend("\tfloat dOuter = length(outerOffset);\n"); - // compare outer lengths against xOuterRadius - builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", - fsEdgeName); - - if (ellipseEffect.isStroked()) { - builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName); - builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n"); - - // compare inner lengths against xInnerRadius - builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.z, 0.0, 1.0);\n", - fsEdgeName); - builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); - } - - SkString modulate; - GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); - builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect(); - - return ellipseEffect.isStroked() ? 0x1 : 0x0; - } - - virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE { - } - - private: - typedef GrGLEffect INHERITED; - }; - -private: - EllipseEdgeEffect(bool stroke) : GrEffect() { - this->addVertexAttrib(kVec2f_GrSLType); - this->addVertexAttrib(kVec4f_GrSLType); - fStroke = stroke; - } - - virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { - const EllipseEdgeEffect& eee = CastEffect(other); - return eee.fStroke == fStroke; - } - - bool fStroke; - - GR_DECLARE_EFFECT_TEST; - - typedef GrEffect INHERITED; -}; - -GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); - -GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, - GrContext* context, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - return EllipseEdgeEffect::Create(random->nextBool()); -} - -/////////////////////////////////////////////////////////////////////////////// - -bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, const GrPaint& paint, - const GrRect& oval, const SkStrokeRec& stroke) -{ - if (!paint.isAntiAlias()) { - return false; - } - - const SkMatrix& vm = context->getMatrix(); - - // we can draw circles - if (SkScalarNearlyEqual(oval.width(), oval.height()) - && circle_stays_circle(vm)) { - drawCircle(target, paint, oval, stroke); - - // and axis-aligned ellipses only - } else if (vm.rectStaysRect()) { - drawEllipse(target, paint, oval, stroke); - - } else { - return false; - } - - return true; -} - -void GrOvalRenderer::drawCircle(GrDrawTarget* target, - const GrPaint& paint, - const GrRect& circle, - const SkStrokeRec& stroke) -{ - GrDrawState* drawState = target->drawState(); - - const SkMatrix& vm = drawState->getViewMatrix(); - GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY()); - vm.mapPoints(¢er, 1); - SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); - SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); - - GrDrawState::AutoDeviceCoordDraw adcd(drawState); - if (!adcd.succeeded()) { - return; - } - - // position + edge - static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} - }; - drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); - GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); - if (!geo.succeeded()) { - GrPrintf("Failed to get space for vertices!\n"); - return; - } - - CircleVertex* verts = reinterpret_cast(geo.vertices()); - - SkStrokeRec::Style style = stroke.getStyle(); - bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); - enum { - // the edge effects share this stage with glyph rendering - // (kGlyphMaskStage in GrTextContext) && SW path rendering - // (kPathMaskStage in GrSWMaskHelper) - kEdgeEffectStage = GrPaint::kTotalStages, - }; - - GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); - static const int kCircleEdgeAttrIndex = 1; - drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref(); - - SkScalar innerRadius = 0.0f; - SkScalar outerRadius = radius; - SkScalar halfWidth = 0; - if (style != SkStrokeRec::kFill_Style) { - if (SkScalarNearlyZero(strokeWidth)) { - halfWidth = SK_ScalarHalf; - } else { - halfWidth = SkScalarHalf(strokeWidth); - } - - outerRadius += halfWidth; - if (isStroked) { - innerRadius = SkMaxScalar(0, radius - halfWidth); - } - } - - // The radii are outset for two reasons. First, it allows the shader to simply perform - // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the - // verts of the bounding box that is rendered and the outset ensures the box will cover all - // pixels partially covered by the circle. - outerRadius += SK_ScalarHalf; - innerRadius -= SK_ScalarHalf; - - for (int i = 0; i < 4; ++i) { - verts[i].fCenter = center; - verts[i].fOuterRadius = outerRadius; - verts[i].fInnerRadius = innerRadius; - } - - SkRect bounds = SkRect::MakeLTRB( - center.fX - outerRadius, - center.fY - outerRadius, - center.fX + outerRadius, - center.fY + outerRadius - ); - - verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); - verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); - verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); - verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); - - target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); -} - -void GrOvalRenderer::drawEllipse(GrDrawTarget* target, - const GrPaint& paint, - const GrRect& ellipse, - const SkStrokeRec& stroke) -{ - GrDrawState* drawState = target->drawState(); -#ifdef SK_DEBUG - { - // we should have checked for this previously - bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect(); - SkASSERT(paint.isAntiAlias() && isAxisAlignedEllipse); - } -#endif - - const SkMatrix& vm = drawState->getViewMatrix(); - GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY()); - vm.mapPoints(¢er, 1); - SkRect xformedRect; - vm.mapRect(&xformedRect, ellipse); - - GrDrawState::AutoDeviceCoordDraw adcd(drawState); - if (!adcd.succeeded()) { - return; - } - - // position + edge - static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}, - {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding} - }; - drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); - GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize()); - - GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); - if (!geo.succeeded()) { - GrPrintf("Failed to get space for vertices!\n"); - return; - } - - EllipseVertex* verts = reinterpret_cast(geo.vertices()); - - SkStrokeRec::Style style = stroke.getStyle(); - bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); - enum { - // the edge effects share this stage with glyph rendering - // (kGlyphMaskStage in GrTextContext) && SW path rendering - // (kPathMaskStage in GrSWMaskHelper) - kEdgeEffectStage = GrPaint::kTotalStages, - }; - - GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); - static const int kEllipseCenterAttrIndex = 1; - static const int kEllipseEdgeAttrIndex = 2; - drawState->setEffect(kEdgeEffectStage, effect, - kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref(); - - SkScalar xRadius = SkScalarHalf(xformedRect.width()); - SkScalar yRadius = SkScalarHalf(xformedRect.height()); - SkScalar innerXRadius = 0.0f; - SkScalar innerRatio = 1.0f; - - if (SkStrokeRec::kFill_Style != style) { - SkScalar strokeWidth = stroke.getWidth(); - - // do (potentially) anisotropic mapping - SkVector scaledStroke; - scaledStroke.set(strokeWidth, strokeWidth); - vm.mapVectors(&scaledStroke, 1); - - if (SkScalarNearlyZero(scaledStroke.length())) { - scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); - } else { - scaledStroke.scale(0.5f); - } - - // this is legit only if scale & translation (which should be the case at the moment) - if (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style) { - SkScalar innerYRadius = SkMaxScalar(0, yRadius - scaledStroke.fY); - if (innerYRadius > SK_ScalarNearlyZero) { - innerXRadius = SkMaxScalar(0, xRadius - scaledStroke.fX); - innerRatio = innerXRadius/innerYRadius; - } - } - xRadius += scaledStroke.fX; - yRadius += scaledStroke.fY; - } - - SkScalar outerRatio = SkScalarDiv(xRadius, yRadius); - - for (int i = 0; i < 4; ++i) { - verts[i].fCenter = center; - verts[i].fOuterXRadius = xRadius + 0.5f; - verts[i].fOuterXYRatio = outerRatio; - verts[i].fInnerXRadius = innerXRadius - 0.5f; - verts[i].fInnerXYRatio = innerRatio; - } - - SkScalar L = -xRadius; - SkScalar R = +xRadius; - SkScalar T = -yRadius; - SkScalar B = +yRadius; - - // We've extended the outer x radius out half a pixel to antialias. - // Expand the drawn rect here so all the pixels will be captured. - L += center.fX - SK_ScalarHalf; - R += center.fX + SK_ScalarHalf; - T += center.fY - SK_ScalarHalf; - B += center.fY + SK_ScalarHalf; - - verts[0].fPos = SkPoint::Make(L, T); - verts[1].fPos = SkPoint::Make(R, T); - verts[2].fPos = SkPoint::Make(L, B); - verts[3].fPos = SkPoint::Make(R, B); - - target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); -} diff --git a/gfx/skia/src/gpu/GrPath.cpp b/gfx/skia/src/gpu/GrPath.cpp deleted file mode 100644 index afd223902fd4..000000000000 --- a/gfx/skia/src/gpu/GrPath.cpp +++ /dev/null @@ -1,10 +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 "GrPath.h" - -SK_DEFINE_INST_COUNT(GrPath) diff --git a/gfx/skia/src/gpu/GrPath.h b/gfx/skia/src/gpu/GrPath.h deleted file mode 100644 index ad3a5c30e0a8..000000000000 --- a/gfx/skia/src/gpu/GrPath.h +++ /dev/null @@ -1,30 +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 GrPath_DEFINED -#define GrPath_DEFINED - -#include "GrResource.h" -#include "GrRect.h" - -class GrPath : public GrResource { -public: - SK_DECLARE_INST_COUNT(GrPath); - - GrPath(GrGpu* gpu, bool isWrapped) : INHERITED(gpu, isWrapped) {} - - const GrRect& getBounds() const { return fBounds; } - -protected: - GrRect fBounds; - -private: - typedef GrResource INHERITED; -}; - -#endif diff --git a/gfx/skia/src/gpu/GrPathRenderer.cpp b/gfx/skia/src/gpu/GrPathRenderer.cpp deleted file mode 100644 index e0d2682bcd37..000000000000 --- a/gfx/skia/src/gpu/GrPathRenderer.cpp +++ /dev/null @@ -1,14 +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" - -SK_DEFINE_INST_COUNT(GrPathRenderer) - -GrPathRenderer::GrPathRenderer() { -} diff --git a/gfx/skia/src/gpu/GrSurface.cpp b/gfx/skia/src/gpu/GrSurface.cpp deleted file mode 100644 index 47d9959d2672..000000000000 --- a/gfx/skia/src/gpu/GrSurface.cpp +++ /dev/null @@ -1,10 +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 "GrSurface.h" - -SK_DEFINE_INST_COUNT(GrSurface) diff --git a/gfx/skia/src/gpu/GrTextContext.cpp b/gfx/skia/src/gpu/GrTextContext.cpp deleted file mode 100644 index 58b3e92c6166..000000000000 --- a/gfx/skia/src/gpu/GrTextContext.cpp +++ /dev/null @@ -1,251 +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 "GrTextContext.h" -#include "GrAtlas.h" -#include "GrContext.h" -#include "GrDrawTarget.h" -#include "GrFontScaler.h" -#include "GrIndexBuffer.h" -#include "GrTextStrike.h" -#include "GrTextStrike_impl.h" -#include "SkPath.h" -#include "SkStrokeRec.h" - -// glyph rendering shares this stage with edge rendering (kEdgeEffectStage in GrContext) && SW path -// rendering (kPathMaskStage in GrSWMaskHelper) -static const int kGlyphMaskStage = GrPaint::kTotalStages; -static const int kGlyphCoordsAttributeIndex = 1; - -void GrTextContext::flushGlyphs() { - if (NULL == fDrawTarget) { - return; - } - GrDrawState* drawState = fDrawTarget->drawState(); - if (fCurrVertex > 0) { - // setup our sampler state for our text texture/atlas - GrAssert(GrIsALIGN4(fCurrVertex)); - GrAssert(fCurrTexture); - GrTextureParams params(SkShader::kRepeat_TileMode, false); - - // This effect could be stored with one of the cache objects (atlas?) - drawState->setEffect(kGlyphMaskStage, - GrSimpleTextureEffect::CreateWithCustomCoords(fCurrTexture, params), - kGlyphCoordsAttributeIndex)->unref(); - - if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { - if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || - kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || - fPaint.hasColorStage()) { - GrPrintf("LCD Text will not draw correctly.\n"); - } - // setup blend so that we get mask * paintColor + (1-mask)*dstColor - drawState->setBlendConstant(fPaint.getColor()); - drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); - // don't modulate by the paint's color in the frag since we're - // already doing it via the blend const. - drawState->setColor(0xffffffff); - } else { - // set back to normal in case we took LCD path previously. - drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); - drawState->setColor(fPaint.getColor()); - } - - int nGlyphs = fCurrVertex / 4; - fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); - fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, - nGlyphs, - 4, 6); - fDrawTarget->resetVertexSource(); - fVertices = NULL; - fMaxVertices = 0; - fCurrVertex = 0; - GrSafeSetNull(fCurrTexture); - } - drawState->disableStages(); - fDrawTarget = NULL; -} - -GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint(paint) { - fContext = context; - fStrike = NULL; - - fCurrTexture = NULL; - fCurrVertex = 0; - - const GrClipData* clipData = context->getClip(); - - GrRect devConservativeBound; - clipData->fClipStack->getConservativeBounds( - -clipData->fOrigin.fX, - -clipData->fOrigin.fY, - context->getRenderTarget()->width(), - context->getRenderTarget()->height(), - &devConservativeBound); - - devConservativeBound.roundOut(&fClipRect); - - fAutoMatrix.setIdentity(fContext, &fPaint); - - fDrawTarget = NULL; - - fVertices = NULL; - fMaxVertices = 0; -} - -GrTextContext::~GrTextContext() { - this->flushGlyphs(); - if (fDrawTarget) { - fDrawTarget->drawState()->disableStages(); - } -} - -void GrTextContext::flush() { - this->flushGlyphs(); -} - -void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, - GrFixed vx, GrFixed vy, - GrFontScaler* scaler) { - if (NULL == fStrike) { - fStrike = fContext->getFontCache()->getStrike(scaler); - } - - GrGlyph* glyph = fStrike->getGlyph(packed, scaler); - if (NULL == glyph || glyph->fBounds.isEmpty()) { - return; - } - - vx += SkIntToFixed(glyph->fBounds.fLeft); - 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(); - - // check if we clipped out - if (true || NULL == glyph->fAtlas) { - int x = vx >> 16; - int y = vy >> 16; - if (fClipRect.quickReject(x, y, x + width, y + height)) { -// SkCLZ(3); // so we can set a break-point in the debugger - return; - } - } - - if (NULL == glyph->fAtlas) { - if (fStrike->getGlyphAtlas(glyph, scaler)) { - goto HAS_ATLAS; - } - - // before we purge the cache, we must flush any accumulated draws - this->flushGlyphs(); - fContext->flush(); - - // try to purge - fContext->getFontCache()->purgeExceptFor(fStrike); - if (fStrike->getGlyphAtlas(glyph, scaler)) { - goto HAS_ATLAS; - } - - if (NULL == glyph->fPath) { - SkPath* path = SkNEW(SkPath); - if (!scaler->getGlyphPath(glyph->glyphID(), path)) { - // flag the glyph as being dead? - delete path; - return; - } - glyph->fPath = path; - } - - GrContext::AutoMatrix am; - SkMatrix translate; - translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)), - 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); - return; - } - -HAS_ATLAS: - GrAssert(glyph->fAtlas); - - // now promote them to fixed (TODO: Rethink using fixed pt). - width = SkIntToFixed(width); - height = SkIntToFixed(height); - - GrTexture* texture = glyph->fAtlas->texture(); - GrAssert(texture); - - if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { - this->flushGlyphs(); - fCurrTexture = texture; - fCurrTexture->ref(); - } - - if (NULL == fVertices) { - // position + texture coord - static const GrVertexAttrib kVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} - }; - - // 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; - bool flush = false; - fDrawTarget = fContext->getTextTarget(fPaint); - if (NULL != fDrawTarget) { - fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); - flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); - } - if (flush) { - this->flushGlyphs(); - fContext->flush(); - // flushGlyphs() will reset fDrawTarget to NULL. - fDrawTarget = fContext->getTextTarget(fPaint); - fDrawTarget->drawState()->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs)); - } - fMaxVertices = kDefaultRequestedVerts; - // ignore return, no point in flushing again. - fDrawTarget->geometryHints(&fMaxVertices, NULL); - - int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); - if (fMaxVertices < kMinRequestedVerts) { - fMaxVertices = kDefaultRequestedVerts; - } else if (fMaxVertices > maxQuadVertices) { - // don't exceed the limit of the index buffer - fMaxVertices = maxQuadVertices; - } - bool success = fDrawTarget->reserveVertexAndIndexSpace( - fMaxVertices, - 0, - GrTCast(&fVertices), - NULL); - GrAlwaysAssert(success); - GrAssert(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)); - fCurrVertex += 4; -} diff --git a/gfx/skia/src/gpu/GrTextStrike.cpp b/gfx/skia/src/gpu/GrTextStrike.cpp deleted file mode 100644 index 4b4298a96c5a..000000000000 --- a/gfx/skia/src/gpu/GrTextStrike.cpp +++ /dev/null @@ -1,209 +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 "GrAtlas.h" -#include "GrGpu.h" -#include "GrRectanizer.h" -#include "GrTextStrike.h" -#include "GrTextStrike_impl.h" -#include "GrRect.h" - -SK_DEFINE_INST_COUNT(GrFontScaler) -SK_DEFINE_INST_COUNT(GrKey) - -/////////////////////////////////////////////////////////////////////////////// - -GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { - gpu->ref(); - fAtlasMgr = NULL; - - fHead = fTail = NULL; -} - -GrFontCache::~GrFontCache() { - fCache.deleteAll(); - delete fAtlasMgr; - fGpu->unref(); -} - -GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler, - const Key& key) { - if (NULL == fAtlasMgr) { - fAtlasMgr = SkNEW_ARGS(GrAtlasMgr, (fGpu)); - } - GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, - (this, scaler->getKey(), - scaler->getMaskFormat(), fAtlasMgr)); - fCache.insert(key, strike); - - if (fHead) { - fHead->fPrev = strike; - } else { - GrAssert(NULL == fTail); - fTail = strike; - } - strike->fPrev = NULL; - strike->fNext = fHead; - fHead = strike; - - return strike; -} - -void GrFontCache::freeAll() { - fCache.deleteAll(); - delete fAtlasMgr; - fAtlasMgr = NULL; - fHead = NULL; - fTail = NULL; -} - -void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { - GrTextStrike* strike = fTail; - while (strike) { - if (strike == preserveStrike) { - strike = strike->fPrev; - continue; - } - GrTextStrike* strikeToPurge = strike; - // keep going if we won't free up any atlases with this strike. - strike = (NULL == strikeToPurge->fAtlas) ? strikeToPurge->fPrev : NULL; - int index = fCache.slowFindIndex(strikeToPurge); - GrAssert(index >= 0); - fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); - this->detachStrikeFromList(strikeToPurge); - delete strikeToPurge; - } -} - -#if GR_DEBUG -void GrFontCache::validate() const { - int count = fCache.count(); - if (0 == count) { - GrAssert(!fHead); - GrAssert(!fTail); - } else if (1 == count) { - GrAssert(fHead == fTail); - } else { - GrAssert(fHead != fTail); - } - - int count2 = 0; - const GrTextStrike* strike = fHead; - while (strike) { - count2 += 1; - strike = strike->fNext; - } - GrAssert(count == count2); - - count2 = 0; - strike = fTail; - while (strike) { - count2 += 1; - strike = strike->fPrev; - } - GrAssert(count == count2); -} -#endif - -/////////////////////////////////////////////////////////////////////////////// - -#if GR_DEBUG - static int gCounter; -#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(). - - We map a 32bit glyphID to a GrGlyph record, which in turn points to a - atlas and a position within that texture. - */ - -GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, - GrMaskFormat format, - GrAtlasMgr* atlasMgr) : fPool(64) { - fFontScalerKey = key; - fFontScalerKey->ref(); - - fFontCache = cache; // no need to ref, it won't go away before we do - fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do - fAtlas = NULL; - - fMaskFormat = format; - -#if GR_DEBUG -// GrPrintf(" GrTextStrike %p %d\n", this, gCounter); - gCounter += 1; -#endif -} - -static void FreeGlyph(GrGlyph*& glyph) { glyph->free(); } - -GrTextStrike::~GrTextStrike() { - GrAtlas::FreeLList(fAtlas); - fFontScalerKey->unref(); - fCache.getArray().visitAll(FreeGlyph); - -#if GR_DEBUG - gCounter -= 1; -// GrPrintf("~GrTextStrike %p %d\n", this, gCounter); -#endif -} - -GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, - GrFontScaler* scaler) { - GrIRect bounds; - if (!scaler->getPackedGlyphBounds(packed, &bounds)) { - return NULL; - } - - GrGlyph* glyph = fPool.alloc(); - glyph->init(packed, bounds); - fCache.insert(packed, glyph); - return glyph; -} - -bool GrTextStrike::getGlyphAtlas(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; -#endif - - GrAssert(glyph); - GrAssert(scaler); - GrAssert(fCache.contains(glyph)); - if (glyph->fAtlas) { - return true; - } - - GrAutoRef ar(scaler); - - int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); - 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; - } - - GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(), - glyph->height(), storage.get(), - fMaskFormat, - &glyph->fAtlasLocation); - if (NULL == atlas) { - return false; - } - - // update fAtlas as well, since they may be chained in a linklist - glyph->fAtlas = fAtlas = atlas; - return true; -} diff --git a/gfx/skia/src/gpu/effects/GrSimpleTextureEffect.cpp b/gfx/skia/src/gpu/effects/GrSimpleTextureEffect.cpp deleted file mode 100644 index 172558dec959..000000000000 --- a/gfx/skia/src/gpu/effects/GrSimpleTextureEffect.cpp +++ /dev/null @@ -1,128 +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 "GrSimpleTextureEffect.h" -#include "gl/GrGLEffect.h" -#include "gl/GrGLEffectMatrix.h" -#include "gl/GrGLSL.h" -#include "gl/GrGLTexture.h" -#include "GrTBackendEffectFactory.h" -#include "GrTexture.h" - -class GrGLSimpleTextureEffect : public GrGLEffect { -public: - GrGLSimpleTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect) - : INHERITED (factory) { - GrEffect::CoordsType coordsType = - drawEffect.castEffect().coordsType(); - if (GrEffect::kCustom_CoordsType != coordsType) { - SkNEW_IN_TLAZY(&fEffectMatrix, GrGLEffectMatrix, (coordsType)); - } - } - - virtual void emitCode(GrGLShaderBuilder* builder, - const GrDrawEffect& drawEffect, - EffectKey key, - const char* outputColor, - const char* inputColor, - const TextureSamplerArray& samplers) SK_OVERRIDE { - const GrSimpleTextureEffect& ste = drawEffect.castEffect(); - const char* fsCoordName; - GrSLType fsCoordSLType; - if (GrEffect::kCustom_CoordsType == ste.coordsType()) { - GrAssert(ste.getMatrix().isIdentity()); - GrAssert(1 == ste.numVertexAttribs()); - fsCoordSLType = kVec2f_GrSLType; - const char* vsVaryingName; - builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsCoordName); - const char* attrName = - builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str(); - builder->vsCodeAppendf("\t%s = %s;", vsVaryingName, attrName); - } else { - fsCoordSLType = fEffectMatrix.get()->emitCode(builder, key, &fsCoordName); - } - builder->fsCodeAppendf("\t%s = ", outputColor); - builder->appendTextureLookupAndModulate(GrGLShaderBuilder::kFragment_ShaderType, - inputColor, - samplers[0], - fsCoordName, - fsCoordSLType); - builder->fsCodeAppend(";\n"); - } - - static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - const GrSimpleTextureEffect& ste = drawEffect.castEffect(); - if (GrEffect::kCustom_CoordsType == ste.coordsType()) { - return 1 << GrGLEffectMatrix::kKeyBits; - } else { - return GrGLEffectMatrix::GenKey(ste.getMatrix(), - drawEffect, - ste.coordsType(), - ste.texture(0)); - } - } - - virtual void setData(const GrGLUniformManager& uman, - const GrDrawEffect& drawEffect) SK_OVERRIDE { - const GrSimpleTextureEffect& ste = drawEffect.castEffect(); - if (GrEffect::kCustom_CoordsType == ste.coordsType()) { - GrAssert(ste.getMatrix().isIdentity()); - } else { - fEffectMatrix.get()->setData(uman, ste.getMatrix(), drawEffect, ste.texture(0)); - } - } - -private: - SkTLazy fEffectMatrix; - typedef GrGLEffect INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -void GrSimpleTextureEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const { - this->updateConstantColorComponentsForModulation(color, validFlags); -} - -const GrBackendEffectFactory& GrSimpleTextureEffect::getFactory() const { - return GrTBackendEffectFactory::getInstance(); -} - -/////////////////////////////////////////////////////////////////////////////// - -GR_DEFINE_EFFECT_TEST(GrSimpleTextureEffect); - -GrEffectRef* GrSimpleTextureEffect::TestCreate(SkMWCRandom* random, - GrContext*, - const GrDrawTargetCaps&, - GrTexture* textures[]) { - int texIdx = 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()); - - static const CoordsType kCoordsTypes[] = { - kLocal_CoordsType, - kPosition_CoordsType, - kCustom_CoordsType - }; - CoordsType coordsType = kCoordsTypes[random->nextULessThan(GR_ARRAY_COUNT(kCoordsTypes))]; - - if (kCustom_CoordsType == coordsType) { - return GrSimpleTextureEffect::CreateWithCustomCoords(textures[texIdx], params); - } else { - const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random); - return GrSimpleTextureEffect::Create(textures[texIdx], matrix); - } -} diff --git a/gfx/skia/src/gpu/gl/GrGLContext.cpp b/gfx/skia/src/gpu/gl/GrGLContext.cpp deleted file mode 100644 index d384b4ee6f2b..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLContext.cpp +++ /dev/null @@ -1,88 +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 "GrGLContext.h" - -//////////////////////////////////////////////////////////////////////////////// -GrGLContextInfo& GrGLContextInfo::operator= (const GrGLContextInfo& ctxInfo) { - fBindingInUse = ctxInfo.fBindingInUse; - fGLVersion = ctxInfo.fGLVersion; - fGLSLGeneration = ctxInfo.fGLSLGeneration; - fVendor = ctxInfo.fVendor; - fExtensions = ctxInfo.fExtensions; - *fGLCaps = *ctxInfo.fGLCaps.get(); - return *this; -} - -bool GrGLContextInfo::initialize(const GrGLInterface* interface) { - this->reset(); - // We haven't validated the GrGLInterface yet, so check for GetString - // function pointer - if (interface->fGetString) { - const GrGLubyte* verUByte; - GR_GL_CALL_RET(interface, verUByte, GetString(GR_GL_VERSION)); - const char* ver = reinterpret_cast(verUByte); - GrGLBinding binding = GrGLGetBindingInUseFromString(ver); - - if (0 != binding && interface->validate(binding) && fExtensions.init(binding, interface)) { - fBindingInUse = binding; - - fGLVersion = GrGLGetVersionFromString(ver); - - fGLSLGeneration = GrGetGLSLGeneration(fBindingInUse, interface); - - fVendor = GrGLGetVendor(interface); - fGLCaps->init(*this, interface); - return true; - } - } - return false; -} - -bool GrGLContextInfo::isInitialized() const { - return kNone_GrGLBinding != fBindingInUse; -} - -void GrGLContextInfo::reset() { - fBindingInUse = kNone_GrGLBinding; - fGLVersion = GR_GL_VER(0, 0); - fGLSLGeneration = static_cast(0); - fVendor = kOther_GrGLVendor; - 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) { - GrSafeAssign(fInterface, ctx.fInterface); - fInfo = ctx.fInfo; - return *this; -} - -void GrGLContext::reset() { - GrSafeSetNull(fInterface); - fInfo.reset(); -} - -bool GrGLContext::initialize(const GrGLInterface* interface) { - if (fInfo.initialize(interface)) { - fInterface = interface; - interface->ref(); - return true; - } - return false; -} diff --git a/gfx/skia/src/gpu/gl/GrGLContext.h b/gfx/skia/src/gpu/gl/GrGLContext.h deleted file mode 100644 index 71b3861a9452..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLContext.h +++ /dev/null @@ -1,126 +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 GrGLContext_DEFINED -#define GrGLContext_DEFINED - -#include "gl/GrGLExtensions.h" -#include "gl/GrGLInterface.h" -#include "GrGLCaps.h" -#include "GrGLSL.h" -#include "GrGLUtil.h" - -#include "SkString.h" - -/** - * Encapsulates information about an OpenGL context including the OpenGL - * version, the GrGLBinding type of the context, and GLSL version. - */ -class GrGLContextInfo { -public: - /** - * Default constructor - */ - GrGLContextInfo() { - fGLCaps.reset(SkNEW(GrGLCaps)); - this->reset(); - } - - /** - * Copies a GrGLContextInfo - */ - GrGLContextInfo& operator= (const GrGLContextInfo& ctxInfo); - - /** - * Initializes a GrGLContextInfo from a GrGLInterface and the currently - * bound OpenGL context accessible by the GrGLInterface. - */ - bool initialize(const GrGLInterface* interface); - bool isInitialized() const; - - GrGLBinding binding() const { return fBindingInUse; } - GrGLVersion version() const { return fGLVersion; } - GrGLSLGeneration glslGeneration() const { return fGLSLGeneration; } - GrGLVendor vendor() const { return fVendor; } - const GrGLCaps* caps() const { return fGLCaps.get(); } - GrGLCaps* caps() { return fGLCaps; } - - /** - * Checks for extension support using a cached copy of the GL_EXTENSIONS - * string. - */ - bool hasExtension(const char* ext) const { - if (!this->isInitialized()) { - return false; - } - return fExtensions.has(ext); - } - - /** - * Reset the information - */ - void reset(); - -private: - - GrGLBinding fBindingInUse; - GrGLVersion fGLVersion; - GrGLSLGeneration fGLSLGeneration; - GrGLVendor fVendor; - GrGLExtensions fExtensions; - SkAutoTUnref fGLCaps; -}; - -/** - * Encapsulates the GrGLInterface used to make GL calls plus information - * about the context (via GrGLContextInfo). - */ -class GrGLContext { -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() { GrSafeUnref(fInterface); } - - /** - * Copies a GrGLContext - */ - GrGLContext& operator= (const GrGLContext& ctx); - - /** - * 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(); } - - const GrGLInterface* interface() const { return fInterface; } - const GrGLContextInfo& info() const { return fInfo; } - GrGLContextInfo& info() { return fInfo; } - -private: - void reset(); - - const GrGLInterface* fInterface; - GrGLContextInfo fInfo; -}; - -#endif diff --git a/gfx/skia/src/gpu/gl/GrGLCreateNullInterface.cpp b/gfx/skia/src/gpu/gl/GrGLCreateNullInterface.cpp deleted file mode 100644 index ebaacbc1af37..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLCreateNullInterface.cpp +++ /dev/null @@ -1,287 +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 "gl/GrGLInterface.h" -#include "GrGLDefines.h" -#include "SkTDArray.h" -#include "GrGLNoOpInterface.h" - -// Functions not declared in GrGLBogusInterface.h (not common with the Debug GL interface). - -namespace { // added to suppress 'no previous prototype' warning - -GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLAttachShader(GrGLuint program, GrGLuint shader) {} -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 nullGLBufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLPixelStorei(GrGLenum pname, GrGLint param) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLReadPixels(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLUseProgram(GrGLuint program) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {} -GrGLvoid GR_GL_FUNCTION_TYPE nullGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {} - -GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateProgram() { - static int gCurrID = 0; - return ++gCurrID; -} - -GrGLuint GR_GL_FUNCTION_TYPE nullGLCreateShader(GrGLenum type) { - static int gCurrID = 0; - return ++gCurrID; -} - -// same delete used for shaders and programs -GrGLvoid GR_GL_FUNCTION_TYPE nullGLDelete(GrGLuint program) { -} - -// In debug builds we do asserts that ensure we agree with GL about when a buffer -// is mapped. -static SkTDArray gMappedBuffers; -static GrGLuint gCurrArrayBuffer; -static GrGLuint gCurrElementArrayBuffer; - -GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindBuffer(GrGLenum target, GrGLuint buffer) { - switch (target) { - case GR_GL_ARRAY_BUFFER: - gCurrArrayBuffer = buffer; - break; - case GR_GL_ELEMENT_ARRAY_BUFFER: - gCurrElementArrayBuffer = buffer; - break; - } -} - -// deleting a bound buffer has the side effect of binding 0 -GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* ids) { - for (int i = 0; i < n; ++i) { - if (ids[i] == gCurrArrayBuffer) { - gCurrArrayBuffer = 0; - } - if (ids[i] == gCurrElementArrayBuffer) { - gCurrElementArrayBuffer = 0; - } - for (int j = 0; j < gMappedBuffers.count(); ++j) { - if (gMappedBuffers[j] == ids[i]) { - gMappedBuffers.remove(j); - // don't break b/c we didn't check for dupes on insert - --j; - } - } - } -} - -GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) { - // We just reserve 32MB of RAM for all locks and hope its big enough - static SkAutoMalloc gBufferData(32 * (1 << 20)); - GrGLuint buf = 0; - switch (target) { - case GR_GL_ARRAY_BUFFER: - buf = gCurrArrayBuffer; - break; - case GR_GL_ELEMENT_ARRAY_BUFFER: - buf = gCurrElementArrayBuffer; - break; - } - if (buf) { - *gMappedBuffers.append() = buf; - } - return gBufferData.get(); -} - -GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) { - GrGLuint buf = 0; - switch (target) { - case GR_GL_ARRAY_BUFFER: - buf = gCurrArrayBuffer; - break; - case GR_GL_ELEMENT_ARRAY_BUFFER: - buf = gCurrElementArrayBuffer; - break; - } - if (buf) { - for (int i = 0; i < gMappedBuffers.count(); ++i) { - if (gMappedBuffers[i] == buf) { - gMappedBuffers.remove(i); - // don't break b/c we didn't check for dupes on insert - --i; - } - } - } - return GR_GL_TRUE; -} - -GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenum pname, GrGLint* params) { - switch (pname) { - case GR_GL_BUFFER_MAPPED: { - *params = GR_GL_FALSE; - GrGLuint buf = 0; - switch (target) { - case GR_GL_ARRAY_BUFFER: - buf = gCurrArrayBuffer; - break; - case GR_GL_ELEMENT_ARRAY_BUFFER: - buf = gCurrElementArrayBuffer; - break; - } - if (buf) { - for (int i = 0; i < gMappedBuffers.count(); ++i) { - if (gMappedBuffers[i] == buf) { - *params = GR_GL_TRUE; - break; - } - } - } - break; } - default: - GrCrash("Unexpected pname to GetBufferParamateriv"); - break; - } -}; - -} // end anonymous namespace - -const GrGLInterface* GrGLCreateNullInterface() { - // The gl functions are not context-specific so we create one global - // interface - static SkAutoTUnref 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->fColorMask = noOpGLColorMask; - interface->fCompileShader = noOpGLCompileShader; - interface->fCompressedTexImage2D = noOpGLCompressedTexImage2D; - 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->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray; - interface->fDrawArrays = noOpGLDrawArrays; - interface->fDrawBuffer = noOpGLDrawBuffer; - interface->fDrawBuffers = noOpGLDrawBuffers; - interface->fDrawElements = noOpGLDrawElements; - interface->fEnable = noOpGLEnable; - interface->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray; - interface->fEndQuery = noOpGLEndQuery; - interface->fFinish = noOpGLFinish; - interface->fFlush = noOpGLFlush; - interface->fFrontFace = noOpGLFrontFace; - interface->fGenBuffers = noOpGLGenIds; - 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->fLineWidth = noOpGLLineWidth; - interface->fLinkProgram = noOpGLLinkProgram; - 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->fTexImage2D = noOpGLTexImage2D; - interface->fTexParameteri = noOpGLTexParameteri; - interface->fTexParameteriv = noOpGLTexParameteriv; - interface->fTexSubImage2D = noOpGLTexSubImage2D; - interface->fTexStorage2D = noOpGLTexStorage2D; - 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->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(); -} diff --git a/gfx/skia/src/gpu/gl/GrGLEffect.cpp b/gfx/skia/src/gpu/gl/GrGLEffect.cpp deleted file mode 100644 index e21ab1dab947..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLEffect.cpp +++ /dev/null @@ -1,50 +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 "GrGLSL.h" -#include "GrGLEffect.h" -#include "GrDrawEffect.h" - -GrGLEffect::GrGLEffect(const GrBackendEffectFactory& factory) - : fFactory(factory) { -} - -GrGLEffect::~GrGLEffect() { -} - -/////////////////////////////////////////////////////////////////////////////// - -void GrGLEffect::setData(const GrGLUniformManager&, const GrDrawEffect&) { -} - -GrGLEffect::EffectKey GrGLEffect::GenTextureKey(const GrDrawEffect& drawEffect, - const GrGLCaps& caps) { - EffectKey key = 0; - int numTextures = (*drawEffect.effect())->numTextures(); - for (int index = 0; index < numTextures; ++index) { - const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(index); - EffectKey value = GrGLShaderBuilder::KeyForTextureAccess(access, caps) << index; - GrAssert(0 == (value & key)); // keys for each access ought not to overlap - key |= value; - } - return key; -} - -GrGLEffect::EffectKey GrGLEffect::GenAttribKey(const GrDrawEffect& drawEffect) { - EffectKey key = 0; - - int numAttributes = drawEffect.getVertexAttribIndexCount(); - GrAssert(numAttributes <= 2); - const int* attributeIndices = drawEffect.getVertexAttribIndices(); - for (int index = 0; index < numAttributes; ++index) { - EffectKey value = attributeIndices[index] << 3*index; - GrAssert(0 == (value & key)); // keys for each attribute ought not to overlap - key |= value; - } - - return key; -} diff --git a/gfx/skia/src/gpu/gl/GrGLEffectMatrix.cpp b/gfx/skia/src/gpu/gl/GrGLEffectMatrix.cpp deleted file mode 100644 index 7e7a9c940aa3..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLEffectMatrix.cpp +++ /dev/null @@ -1,238 +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 "GrGLEffectMatrix.h" -#include "GrDrawEffect.h" -#include "GrTexture.h" - -GrGLEffect::EffectKey GrGLEffectMatrix::GenKey(const SkMatrix& effectMatrix, - const GrDrawEffect& drawEffect, - CoordsType coordsType, - const GrTexture* texture) { - EffectKey key = 0; - SkMatrix::TypeMask type0 = effectMatrix.getType(); - SkMatrix::TypeMask type1; - if (GrEffect::kLocal_CoordsType == coordsType) { - type1 = drawEffect.getCoordChangeMatrix().getType(); - } else { - if (drawEffect.programHasExplicitLocalCoords()) { - // We only make the key indicate that device coords are referenced when the local coords - // are not actually determined by positions. - key |= kPositionCoords_Flag; - } - type1 = SkMatrix::kIdentity_Mask; - } - - int combinedTypes = type0 | type1; - - bool reverseY = (NULL != texture) && kBottomLeft_GrSurfaceOrigin == texture->origin(); - - if (SkMatrix::kPerspective_Mask & combinedTypes) { - key |= kGeneral_MatrixType; - } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) { - key |= kNoPersp_MatrixType; - } else if (SkMatrix::kTranslate_Mask & combinedTypes) { - key |= kTrans_MatrixType; - } else { - key |= kIdentity_MatrixType; - } - return key; -} - -GrSLType GrGLEffectMatrix::emitCode(GrGLShaderBuilder* builder, - EffectKey key, - const char** fsCoordName, - const char** vsCoordName, - const char* suffix) { - GrSLType varyingType = kVoid_GrSLType; - const char* uniName; - key &= kKeyMask; - switch (key & kMatrixTypeKeyMask) { - case kIdentity_MatrixType: - fUniType = kVoid_GrSLType; - varyingType = kVec2f_GrSLType; - break; - case kTrans_MatrixType: - fUniType = kVec2f_GrSLType; - uniName = "StageTranslate"; - varyingType = kVec2f_GrSLType; - break; - case kNoPersp_MatrixType: - fUniType = kMat33f_GrSLType; - uniName = "StageMatrix"; - varyingType = kVec2f_GrSLType; - break; - case kGeneral_MatrixType: - fUniType = kMat33f_GrSLType; - uniName = "StageMatrix"; - varyingType = kVec3f_GrSLType; - break; - default: - GrCrash("Unexpected key."); - } - SkString suffixedUniName; - if (NULL != suffix) { - suffixedUniName.append(uniName); - suffixedUniName.append(suffix); - uniName = suffixedUniName.c_str(); - } - if (kVoid_GrSLType != fUniType) { - fUni = builder->addUniform(GrGLShaderBuilder::kVertex_ShaderType, - fUniType, - uniName, - &uniName); - } - - const char* varyingName = "StageCoord"; - SkString suffixedVaryingName; - if (NULL != suffix) { - suffixedVaryingName.append(varyingName); - suffixedVaryingName.append(suffix); - varyingName = suffixedVaryingName.c_str(); - } - const char* vsVaryingName; - const char* fsVaryingName; - builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); - - const GrGLShaderVar* coords; - switch (fCoordsType) { - case GrEffect::kLocal_CoordsType: - GrAssert(!(kPositionCoords_Flag & key)); - coords = &builder->localCoordsAttribute(); - break; - case GrEffect::kPosition_CoordsType: - GrAssert((kPositionCoords_Flag & key) || !builder->hasExplicitLocalCoords()); - coords = &builder->positionAttribute(); - break; - default: - coords = NULL; // prevents warning - GrCrash("Unexpected coords type."); - } - // varying = matrix * coords (logically) - switch (fUniType) { - case kVoid_GrSLType: - GrAssert(kVec2f_GrSLType == varyingType); - builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords->c_str()); - break; - case kVec2f_GrSLType: - GrAssert(kVec2f_GrSLType == varyingType); - builder->vsCodeAppendf("\t%s = %s + %s;\n", - vsVaryingName, uniName, coords->c_str()); - break; - case kMat33f_GrSLType: { - GrAssert(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); - if (kVec2f_GrSLType == varyingType) { - builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", - vsVaryingName, uniName, coords->c_str()); - } else { - builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", - vsVaryingName, uniName, coords->c_str()); - } - break; - } - default: - GrCrash("Unexpected uniform type."); - } - if (NULL != vsCoordName) { - *vsCoordName = vsVaryingName; - } - if (NULL != fsCoordName) { - *fsCoordName = fsVaryingName; - } - return varyingType; -} - -/** - * This is similar to emitCode except that it performs perspective division in the FS if the - * texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f. - */ -void GrGLEffectMatrix::emitCodeMakeFSCoords2D(GrGLShaderBuilder* builder, - EffectKey key, - const char** fsCoordName, - const char** vsVaryingName, - GrSLType* vsVaryingType, - const char* suffix) { - const char* fsVaryingName; - - GrSLType varyingType = this->emitCode(builder, - key, - &fsVaryingName, - vsVaryingName, - suffix); - if (kVec3f_GrSLType == varyingType) { - - const char* coordName = "coords2D"; - SkString suffixedCoordName; - if (NULL != suffix) { - suffixedCoordName.append(coordName); - suffixedCoordName.append(suffix); - coordName = suffixedCoordName.c_str(); - } - builder->fsCodeAppendf("\tvec2 %s = %s.xy / %s.z;", - coordName, fsVaryingName, fsVaryingName); - if (NULL != fsCoordName) { - *fsCoordName = coordName; - } - } else if(NULL != fsCoordName) { - *fsCoordName = fsVaryingName; - } - if (NULL != vsVaryingType) { - *vsVaryingType = varyingType; - } -} - -void GrGLEffectMatrix::setData(const GrGLUniformManager& uniformManager, - const SkMatrix& matrix, - const GrDrawEffect& drawEffect, - const GrTexture* texture) { - GrAssert((GrGLUniformManager::kInvalidUniformHandle == fUni) == - (kVoid_GrSLType == fUniType)); - const SkMatrix& coordChangeMatrix = GrEffect::kLocal_CoordsType == fCoordsType ? - drawEffect.getCoordChangeMatrix() : - SkMatrix::I(); - switch (fUniType) { - case kVoid_GrSLType: - GrAssert(matrix.isIdentity()); - GrAssert(coordChangeMatrix.isIdentity()); - GrAssert(NULL == texture || kTopLeft_GrSurfaceOrigin == texture->origin()); - return; - case kVec2f_GrSLType: { - GrAssert(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType())); - GrAssert(NULL == texture || kTopLeft_GrSurfaceOrigin == texture->origin()); - SkScalar tx = matrix[SkMatrix::kMTransX] + (coordChangeMatrix)[SkMatrix::kMTransX]; - SkScalar ty = matrix[SkMatrix::kMTransY] + (coordChangeMatrix)[SkMatrix::kMTransY]; - if (fPrevMatrix.get(SkMatrix::kMTransX) != tx || - fPrevMatrix.get(SkMatrix::kMTransY) != ty) { - uniformManager.set2f(fUni, tx, ty); - fPrevMatrix.set(SkMatrix::kMTransX, tx); - fPrevMatrix.set(SkMatrix::kMTransY, ty); - } - break; - } - case kMat33f_GrSLType: { - SkMatrix combined; - combined.setConcat(matrix, coordChangeMatrix); - if (NULL != texture && kBottomLeft_GrSurfaceOrigin == texture->origin()) { - // combined.postScale(1,-1); - // combined.postTranslate(0,1); - combined.set(SkMatrix::kMSkewY, - combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); - combined.set(SkMatrix::kMScaleY, - combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); - combined.set(SkMatrix::kMTransY, - combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); - } - if (!fPrevMatrix.cheapEqualTo(combined)) { - uniformManager.setSkMatrix(fUni, combined); - fPrevMatrix = combined; - } - break; - } - default: - GrCrash("Unexpected uniform type."); - } -} diff --git a/gfx/skia/src/gpu/gl/GrGLEffectMatrix.h b/gfx/skia/src/gpu/gl/GrGLEffectMatrix.h deleted file mode 100644 index fc4b7831336d..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLEffectMatrix.h +++ /dev/null @@ -1,121 +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 GrGLEffectMatrix_DEFINED -#define GrGLEffectMatrix_DEFINED - -#include "GrGLEffect.h" -#include "SkMatrix.h" - -class GrTexture; - -/** - * This is a helper to implement a matrix in a GrGLEffect that operates on incoming coords in the - * vertex shader and writes them to an attribute to be used in the fragment shader. When the input - * coords in the vertex shader are local coordinates this class accounts for the coord change matrix - * communicated via GrDrawEffect. The input coords may also be positions and in this case the coord - * change matrix is ignored. The GrGLEffectMatrix will emit different code based on the type of - * matrix and thus must contribute to the effect's key. - * - * This class cannot be used to apply a matrix to coordinates that come in the form of custom vertex - * attributes. - */ -class GrGLEffectMatrix { -private: - // We specialize the generated code for each of these matrix types. - enum MatrixTypes { - kIdentity_MatrixType = 0, - kTrans_MatrixType = 1, - kNoPersp_MatrixType = 2, - kGeneral_MatrixType = 3, - }; - // The key for is made up of a matrix type and a bit that indicates the source of the input - // coords. - enum { - kMatrixTypeKeyBits = 2, - kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, - kPositionCoords_Flag = (1 << kMatrixTypeKeyBits), - kKeyBitsPrivate = kMatrixTypeKeyBits + 1, - }; - -public: - - typedef GrEffect::CoordsType CoordsType; - - typedef GrGLEffect::EffectKey EffectKey; - - /** - * The matrix uses kKeyBits of the effect's EffectKey. A GrGLEffect may place these bits at an - * arbitrary shift in its final key. However, when GrGLEffectMatrix::emitCode*() code is called - * the relevant bits must be in the lower kKeyBits of the key parameter. - */ - enum { - kKeyBits = kKeyBitsPrivate, - kKeyMask = (1 << kKeyBits) - 1, - }; - - GrGLEffectMatrix(CoordsType coordsType) - : fUni(GrGLUniformManager::kInvalidUniformHandle) - , fCoordsType(coordsType) { - GrAssert(GrEffect::kLocal_CoordsType == coordsType || - GrEffect::kPosition_CoordsType == coordsType); - fPrevMatrix = SkMatrix::InvalidMatrix(); - } - - /** - * Generates the key for the portion of the code emitted by this class's emitCode() function. - * Pass a texture to make GrGLEffectMatrix automatically adjust for the texture's origin. Pass - * NULL when not using the EffectMatrix for a texture lookup, or if the GrGLEffect subclass - * wants to handle origin adjustments in some other manner. The coords type param must match the - * param that would be used to initialize GrGLEffectMatrix for the generating GrEffect. - */ - static EffectKey GenKey(const SkMatrix& effectMatrix, - const GrDrawEffect&, - CoordsType, - const GrTexture*); - - /** - * Emits code to implement the matrix in the VS. A varying is added as an output of the VS and - * input to the FS. The varying may be either a vec2f or vec3f depending upon whether - * perspective interpolation is required or not. The names of the varying in the VS and FS are - * are returned as output parameters and the type of the varying is the return value. The suffix - * is an optional parameter that can be used to make all variables emitted by the object - * unique within a stage. It is only necessary if multiple GrGLEffectMatrix objects are used by - * a GrGLEffect. - */ - GrSLType emitCode(GrGLShaderBuilder*, - EffectKey, - const char** fsCoordName, /* optional */ - const char** vsCoordName = NULL, - const char* suffix = NULL); - - /** - * This is similar to emitCode except that it performs perspective division in the FS if the - * texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f. - */ - void emitCodeMakeFSCoords2D(GrGLShaderBuilder*, - EffectKey, - const char** fsCoordName, /* optional */ - const char** vsVaryingName = NULL, - GrSLType* vsVaryingType = NULL, - const char* suffix = NULL); - /** - * Call from a GrGLEffect's subclass to update the texture matrix. The effectMatrix and texture - * params should match those used with GenKey. - */ - void setData(const GrGLUniformManager& uniformManager, - const SkMatrix& effectMatrix, - const GrDrawEffect& drawEffect, - const GrTexture*); - - GrGLUniformManager::UniformHandle fUni; - GrSLType fUniType; - SkMatrix fPrevMatrix; - CoordsType fCoordsType; -}; - -#endif diff --git a/gfx/skia/src/gpu/gl/GrGLExtensions.cpp b/gfx/skia/src/gpu/gl/GrGLExtensions.cpp deleted file mode 100644 index 47cdba14b843..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLExtensions.cpp +++ /dev/null @@ -1,83 +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 "gl/GrGLExtensions.h" -#include "gl/GrGLDefines.h" -#include "gl/GrGLUtil.h" - -#include "SkTSearch.h" -#include "SkTSort.h" - -namespace { -inline int extension_compare(const SkString* a, const SkString* b) { - return strcmp(a->c_str(), b->c_str()); -} -} - -bool GrGLExtensions::init(GrGLBinding binding, - GrGLGetStringProc getString, - GrGLGetStringiProc getStringi, - GrGLGetIntegervProc getIntegerv) { - fStrings.reset(); - if (NULL == getString) { - return false; - } - bool indexed = false; - if (kDesktop_GrGLBinding == binding) { - const GrGLubyte* verString = getString(GR_GL_VERSION); - if (NULL == verString) { - return false; - } - GrGLVersion version = GrGLGetVersionFromString((const char*) verString); - indexed = version >= GR_GL_VER(3, 0); - } - if (indexed) { - if (NULL == getStringi || NULL == getIntegerv) { - return false; - } - GrGLint extensionCnt = 0; - getIntegerv(GR_GL_NUM_EXTENSIONS, &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; - } - } else { - const char* extensions = (const char*) getString(GR_GL_EXTENSIONS); - if (NULL == extensions) { - return false; - } - while (true) { - // skip over multiple spaces between extensions - while (' ' == *extensions) { - ++extensions; - } - // quit once we reach the end of the string. - if ('\0' == *extensions) { - break; - } - // we found an extension - size_t length = strcspn(extensions, " "); - fStrings.push_back().set(extensions, length); - extensions += length; - } - } - if (0 != fStrings.count()) { - SkTSearchCompareLTFunctor cmp; - SkTQSort(&fStrings.front(), &fStrings.back(), cmp); - } - return true; -} - -bool GrGLExtensions::has(const char* ext) const { - SkString extensionStr(ext); - int idx = SkTSearch(&fStrings.front(), - fStrings.count(), - extensionStr, - sizeof(SkString)); - return idx >= 0; -} diff --git a/gfx/skia/src/gpu/gl/GrGLInterface.cpp b/gfx/skia/src/gpu/gl/GrGLInterface.cpp deleted file mode 100644 index 0c6bd8604d1a..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLInterface.cpp +++ /dev/null @@ -1,377 +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 "gl/GrGLInterface.h" -#include "gl/GrGLExtensions.h" -#include "gl/GrGLUtil.h" - -#include - -SK_DEFINE_INST_COUNT(GrGLInterface) - -#if GR_GL_PER_GL_FUNC_CALLBACK -namespace { -void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} -} -#endif - -GrGLInterface::GrGLInterface() { - fBindingsExported = kNone_GrGLBinding; - -#if GR_GL_PER_GL_FUNC_CALLBACK - fCallback = GrGLDefaultInterfaceCallback; - fCallbackData = 0; -#endif -} - -bool GrGLInterface::validate(GrGLBinding binding) const { - - // 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); - - if (0 == (binding & fBindingsExported)) { - return false; - } - - GrGLExtensions extensions; - if (!extensions.init(binding, this)) { - return false; - } - - // 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 == 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 == fGetError || - NULL == fGetIntegerv || - NULL == fGetProgramInfoLog || - NULL == fGetProgramiv || - NULL == fGetShaderInfoLog || - NULL == fGetShaderiv || - NULL == fGetString || - NULL == fGetUniformLocation || - NULL == fLinkProgram || - 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; - } - - GrGLVersion glVer = GrGLGetVersion(this); - - // 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 - // 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 (kES2_GrGLBinding == binding) { - if (NULL == fStencilFuncSeparate || - NULL == fStencilMaskSeparate || - NULL == fStencilOpSeparate) { - return false; - } - } else if (kDesktop_GrGLBinding == binding) { - - if (glVer >= GR_GL_VER(2,0)) { - if (NULL == fStencilFuncSeparate || - NULL == fStencilMaskSeparate || - NULL == fStencilOpSeparate) { - return false; - } - } - if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) { - return false; - } - if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) { - if (NULL == fDrawBuffers) { - return false; - } - } - - 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(3,3) || - extensions.has("GL_ARB_timer_query") || - extensions.has("GL_EXT_timer_query")) { - if (NULL == fGetQueryObjecti64v || - NULL == fGetQueryObjectui64v) { - return false; - } - } - if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) { - if (NULL == fQueryCounter) { - return false; - } - } - // The below two blocks are checks for functions used with - // GL_NV_path_rendering. We're not enforcing that they be non-NULL - // because they aren't actually called at this time. - if (false && - (NULL == fMatrixMode || - NULL == fLoadIdentity || - NULL == fLoadMatrixf)) { - return false; - } - 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; - } - } - } - - // optional function on desktop before 1.3 - if (kDesktop_GrGLBinding != binding || - (glVer >= GR_GL_VER(1,3)) || - extensions.has("GL_ARB_texture_compression")) { - if (NULL == fCompressedTexImage2D) { - return false; - } - } - - // part of desktop GL, but not ES - if (kDesktop_GrGLBinding == binding && - (NULL == fLineWidth || - NULL == fGetTexLevelParameteriv || - NULL == fDrawBuffer || - NULL == fReadBuffer)) { - return false; - } - - // 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 (glVer >= GR_GL_VER(4,2) || - extensions.has("GL_ARB_texture_storage") || - extensions.has("GL_EXT_texture_storage")) { - if (NULL == fTexStorage2D) { - return false; - } - } - } else if (extensions.has("GL_EXT_texture_storage")) { - if (NULL == fTexStorage2D) { - return false; - } - } - - // FBO MSAA - if (kDesktop_GrGLBinding == binding) { - // 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; - } - } else { - if (extensions.has("GL_EXT_framebuffer_blit") && - NULL == fBlitFramebuffer) { - return false; - } - if (extensions.has("GL_EXT_framebuffer_multisample") && - NULL == fRenderbufferStorageMultisample) { - return false; - } - } - } else { - if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) { - if (NULL == fRenderbufferStorageMultisample || - NULL == fBlitFramebuffer) { - return false; - } - } - if (extensions.has("GL_APPLE_framebuffer_multisample")) { - if (NULL == fRenderbufferStorageMultisample || - NULL == fResolveMultisampleFramebuffer) { - return false; - } - } - if (extensions.has("GL_IMG_multisampled_render_to_texture")) { - if (NULL == fRenderbufferStorageMultisample || - NULL == fFramebufferTexture2DMultisample) { - return false; - } - } - } - - // 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; - } - } - - // 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 (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3, 0)) { - if (NULL == fGetStringi) { - return false; - } - } - - 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; - } - } - } else { - if (extensions.has("GL_OES_vertex_array_object")) { - if (NULL == fBindVertexArray || - NULL == fDeleteVertexArrays || - NULL == fGenVertexArrays) { - return false; - } - } - } - - return true; -} diff --git a/gfx/skia/src/gpu/gl/GrGLPath.cpp b/gfx/skia/src/gpu/gl/GrGLPath.cpp deleted file mode 100644 index 8c6e11e667b0..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLPath.cpp +++ /dev/null @@ -1,109 +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 "GrGLPath.h" -#include "GrGpuGL.h" - -#define GPUGL static_cast(this->getGpu()) - -#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) -#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X) - -namespace { -inline GrGLubyte verb_to_gl_path_cmd(const SkPath::Verb verb) { - static const GrGLubyte gTable[] = { - GR_GL_MOVE_TO, - GR_GL_LINE_TO, - GR_GL_QUADRATIC_CURVE_TO, - GR_GL_CUBIC_CURVE_TO, - GR_GL_CLOSE_PATH, - }; - GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); - GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); - GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); - GR_STATIC_ASSERT(3 == SkPath::kCubic_Verb); - GR_STATIC_ASSERT(4 == SkPath::kClose_Verb); - - GrAssert(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable)); - return gTable[verb]; -} - -#ifdef SK_DEBUG -inline int num_pts(const SkPath::Verb verb) { - static const int gTable[] = { - 1, // move - 1, // line - 2, // quad - 3, // cubic - 0, // close - }; - GR_STATIC_ASSERT(0 == SkPath::kMove_Verb); - GR_STATIC_ASSERT(1 == SkPath::kLine_Verb); - GR_STATIC_ASSERT(2 == SkPath::kQuad_Verb); - GR_STATIC_ASSERT(3 == SkPath::kCubic_Verb); - GR_STATIC_ASSERT(4 == SkPath::kClose_Verb); - - GrAssert(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable)); - return gTable[verb]; -} -#endif -} - -static const bool kIsWrapped = false; // The constructor creates the GL path object. - -GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path) : INHERITED(gpu, kIsWrapped) { - GL_CALL_RET(fPathID, GenPaths(1)); - SkPath::Iter iter(path, true); - - SkSTArray<16, GrGLubyte, true> pathCommands; -#ifndef SK_SCALAR_IS_FLOAT - GrCrash("Assumes scalar is float."); -#endif - SkSTArray<16, SkPoint, true> pathPoints; - - int verbCnt = path.countVerbs(); - int pointCnt = path.countPoints(); - pathCommands.resize_back(verbCnt); - pathPoints.resize_back(pointCnt); - - // TODO: Direct access to path points since we could pass them on directly. - path.getPoints(&pathPoints[0], pointCnt); - path.getVerbs(&pathCommands[0], verbCnt); - - GR_DEBUGCODE(int numPts = 0); - for (int i = 0; i < verbCnt; ++i) { - SkPath::Verb v = static_cast(pathCommands[i]); - pathCommands[i] = verb_to_gl_path_cmd(v); - GR_DEBUGCODE(numPts += num_pts(v)); - } - GrAssert(pathPoints.count() == numPts); - - GL_CALL(PathCommands(fPathID, - verbCnt, &pathCommands[0], - 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0])); - fBounds = path.getBounds(); -} - -GrGLPath::~GrGLPath() { - this->release(); -} - -void GrGLPath::onRelease() { - if (0 != fPathID && !this->isWrapped()) { - GL_CALL(DeletePaths(fPathID, 1)); - fPathID = 0; - } - - INHERITED::onRelease(); -} - -void GrGLPath::onAbandon() { - fPathID = 0; - - INHERITED::onAbandon(); -} diff --git a/gfx/skia/src/gpu/gl/GrGLProgram.cpp b/gfx/skia/src/gpu/gl/GrGLProgram.cpp deleted file mode 100644 index 51cae5c8c81f..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLProgram.cpp +++ /dev/null @@ -1,975 +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 "GrGLProgram.h" - -#include "GrAllocator.h" -#include "GrEffect.h" -#include "GrDrawEffect.h" -#include "GrGLEffect.h" -#include "GrGpuGL.h" -#include "GrGLShaderVar.h" -#include "SkTrace.h" -#include "SkXfermode.h" - -#include "SkRTConf.h" - -SK_DEFINE_INST_COUNT(GrGLProgram) - -#define GL_CALL(X) GR_GL_CALL(fContext.interface(), X) -#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fContext.interface(), R, X) - -SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false, - "Print the source code for all shaders generated."); - -#define COL_ATTR_NAME "aColor" -#define COV_ATTR_NAME "aCoverage" -#define EDGE_ATTR_NAME "aEdge" - -namespace { -inline const char* declared_color_output_name() { return "fsColorOut"; } -inline const char* dual_source_output_name() { return "dualSourceOut"; } -} - -GrGLProgram* GrGLProgram::Create(const GrGLContext& gl, - const GrGLProgramDesc& desc, - const GrEffectStage* stages[]) { - GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gl, desc, stages)); - if (!program->succeeded()) { - delete program; - program = NULL; - } - return program; -} - -GrGLProgram::GrGLProgram(const GrGLContext& gl, - const GrGLProgramDesc& desc, - const GrEffectStage* stages[]) -: fContext(gl) -, fUniformManager(gl) { - fDesc = desc; - fVShaderID = 0; - fGShaderID = 0; - fFShaderID = 0; - fProgramID = 0; - - fColor = GrColor_ILLEGAL; - fColorFilterColor = GrColor_ILLEGAL; - - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - fEffects[s] = NULL; - } - - this->genProgram(stages); -} - -GrGLProgram::~GrGLProgram() { - if (fVShaderID) { - GL_CALL(DeleteShader(fVShaderID)); - } - if (fGShaderID) { - GL_CALL(DeleteShader(fGShaderID)); - } - if (fFShaderID) { - GL_CALL(DeleteShader(fFShaderID)); - } - if (fProgramID) { - GL_CALL(DeleteProgram(fProgramID)); - } - - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - delete fEffects[i]; - } -} - -void GrGLProgram::abandon() { - fVShaderID = 0; - fGShaderID = 0; - fFShaderID = 0; - fProgramID = 0; -} - -void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, - GrBlendCoeff* dstCoeff) const { - switch (fDesc.fDualSrcOutput) { - case GrGLProgramDesc::kNone_DualSrcOutput: - break; - // the prog will write a coverage value to the secondary - // output and the dst is blended by one minus that value. - case GrGLProgramDesc::kCoverage_DualSrcOutput: - case GrGLProgramDesc::kCoverageISA_DualSrcOutput: - case GrGLProgramDesc::kCoverageISC_DualSrcOutput: - *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; - break; - default: - GrCrash("Unexpected dual source blend output"); - break; - } -} - -namespace { - -// given two blend coeffecients determine whether the src -// and/or dst computation can be omitted. -inline void need_blend_inputs(SkXfermode::Coeff srcCoeff, - SkXfermode::Coeff dstCoeff, - bool* needSrcValue, - bool* needDstValue) { - if (SkXfermode::kZero_Coeff == srcCoeff) { - switch (dstCoeff) { - // these all read the src - case SkXfermode::kSC_Coeff: - case SkXfermode::kISC_Coeff: - case SkXfermode::kSA_Coeff: - case SkXfermode::kISA_Coeff: - *needSrcValue = true; - break; - default: - *needSrcValue = false; - break; - } - } else { - *needSrcValue = true; - } - if (SkXfermode::kZero_Coeff == dstCoeff) { - switch (srcCoeff) { - // these all read the dst - case SkXfermode::kDC_Coeff: - case SkXfermode::kIDC_Coeff: - case SkXfermode::kDA_Coeff: - case SkXfermode::kIDA_Coeff: - *needDstValue = true; - break; - default: - *needDstValue = false; - break; - } - } else { - *needDstValue = true; - } -} - -/** - * Create a blend_coeff * value string to be used in shader code. Sets empty - * string if result is trivially zero. - */ -inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff, - const char* src, const char* dst, - const char* value) { - switch (coeff) { - case SkXfermode::kZero_Coeff: /** 0 */ - *str = ""; - break; - case SkXfermode::kOne_Coeff: /** 1 */ - *str = value; - break; - case SkXfermode::kSC_Coeff: - str->printf("(%s * %s)", src, value); - break; - case SkXfermode::kISC_Coeff: - str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value); - break; - case SkXfermode::kDC_Coeff: - str->printf("(%s * %s)", dst, value); - break; - case SkXfermode::kIDC_Coeff: - str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value); - break; - case SkXfermode::kSA_Coeff: /** src alpha */ - str->printf("(%s.a * %s)", src, value); - break; - case SkXfermode::kISA_Coeff: /** inverse src alpha (i.e. 1 - sa) */ - str->printf("((1.0 - %s.a) * %s)", src, value); - break; - case SkXfermode::kDA_Coeff: /** dst alpha */ - str->printf("(%s.a * %s)", dst, value); - break; - case SkXfermode::kIDA_Coeff: /** inverse dst alpha (i.e. 1 - da) */ - str->printf("((1.0 - %s.a) * %s)", dst, value); - break; - default: - GrCrash("Unexpected xfer coeff."); - break; - } -} -/** - * Adds a line to the fragment shader code which modifies the color by - * the specified color filter. - */ -void add_color_filter(GrGLShaderBuilder* builder, - const char * outputVar, - SkXfermode::Coeff uniformCoeff, - SkXfermode::Coeff colorCoeff, - const char* filterColor, - const char* inColor) { - SkString colorStr, constStr; - blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor); - blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor); - - SkString sum; - GrGLSLAdd4f(&sum, colorStr.c_str(), constStr.c_str()); - builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str()); -} -} - -void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { - switch (fDesc.fColorInput) { - case GrGLProgramDesc::kAttribute_ColorInput: { - builder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME); - const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); - builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName); - *inColor = fsName; - } break; - case GrGLProgramDesc::kUniform_ColorInput: { - const char* name; - fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "Color", &name); - *inColor = name; - break; - } - case GrGLProgramDesc::kTransBlack_ColorInput: - GrAssert(!"needComputedColor should be false."); - break; - case GrGLProgramDesc::kSolidWhite_ColorInput: - break; - default: - GrCrash("Unknown color type."); - break; - } -} - -void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { - const char* covUniName; - fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "Coverage", &covUniName); - if (inOutCoverage->size()) { - builder->fsCodeAppendf("\tvec4 uniCoverage = %s * %s;\n", - covUniName, inOutCoverage->c_str()); - *inOutCoverage = "uniCoverage"; - } else { - *inOutCoverage = covUniName; - } -} - -namespace { -void gen_attribute_coverage(GrGLShaderBuilder* builder, - SkString* inOutCoverage) { - builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME); - const char *vsName, *fsName; - builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName); - builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName); - if (inOutCoverage->size()) { - builder->fsCodeAppendf("\tvec4 attrCoverage = %s * %s;\n", fsName, inOutCoverage->c_str()); - *inOutCoverage = "attrCoverage"; - } else { - *inOutCoverage = fsName; - } -} -} - -void GrGLProgram::genGeometryShader(GrGLShaderBuilder* builder) const { -#if GR_GL_EXPERIMENTAL_GS - // TODO: The builder should add all this glue code. - if (fDesc.fExperimentalGS) { - GrAssert(fContext.info().glslGeneration() >= k150_GrGLSLGeneration); - builder->fGSHeader.append("layout(triangles) in;\n" - "layout(triangle_strip, max_vertices = 6) out;\n"); - builder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n" - "\t\tgl_Position = gl_in[i].gl_Position;\n"); - if (fDesc.fEmitsPointSize) { - builder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n"); - } - GrAssert(builder->fGSInputs.count() == builder->fGSOutputs.count()); - int count = builder->fGSInputs.count(); - for (int i = 0; i < count; ++i) { - builder->gsCodeAppendf("\t\t%s = %s[i];\n", - builder->fGSOutputs[i].getName().c_str(), - builder->fGSInputs[i].getName().c_str()); - } - builder->gsCodeAppend("\t\tEmitVertex();\n" - "\t}\n" - "\tEndPrimitive();\n"); - } -#endif -} - -const char* GrGLProgram::adjustInColor(const SkString& inColor) const { - if (inColor.size()) { - return inColor.c_str(); - } else { - if (GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.fColorInput) { - return GrGLSLOnesVecf(4); - } else { - return GrGLSLZerosVecf(4); - } - } -} - -namespace { -// prints a shader using params similar to glShaderSource -void print_shader(GrGLint stringCnt, - const GrGLchar** strings, - GrGLint* stringLengths) { - for (int i = 0; i < stringCnt; ++i) { - if (NULL == stringLengths || stringLengths[i] < 0) { - GrPrintf(strings[i]); - } else { - GrPrintf("%.*s", stringLengths[i], strings[i]); - } - } -} - -// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource -GrGLuint compile_shader(const GrGLContext& gl, - GrGLenum type, - int stringCnt, - const char** strings, - int* stringLengths) { - SK_TRACE_EVENT1("GrGLProgram::CompileShader", - "stringCount", SkStringPrintf("%i", stringCnt).c_str()); - - GrGLuint shader; - GR_GL_CALL_RET(gl.interface(), shader, CreateShader(type)); - if (0 == shader) { - return 0; - } - - const GrGLInterface* gli = gl.interface(); - GrGLint compiled = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths)); - GR_GL_CALL(gli, CompileShader(shader)); - GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); - - if (!compiled) { - GrGLint infoLen = GR_GL_INIT_ZERO; - GR_GL_CALL(gli, GetShaderiv(shader, 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; - GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1, - &length, (char*)log.get())); - print_shader(stringCnt, strings, stringLengths); - GrPrintf("\n%s", log.get()); - } - GrAssert(!"Shader compilation failed!"); - GR_GL_CALL(gli, DeleteShader(shader)); - return 0; - } - return shader; -} - -// helper version of above for when shader is already flattened into a single SkString -GrGLuint compile_shader(const GrGLContext& gl, GrGLenum type, const SkString& shader) { - const GrGLchar* str = shader.c_str(); - int length = shader.size(); - return compile_shader(gl, type, 1, &str, &length); -} - -} - -// compiles all the shaders from builder and stores the shader IDs -bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) { - - SkString shader; - - builder.getShader(GrGLShaderBuilder::kVertex_ShaderType, &shader); - if (c_PrintShaders) { - GrPrintf(shader.c_str()); - GrPrintf("\n"); - } - - if (!(fVShaderID = compile_shader(fContext, GR_GL_VERTEX_SHADER, shader))) { - return false; - } - - fGShaderID = 0; -#if GR_GL_EXPERIMENTAL_GS - if (fDesc.fExperimentalGS) { - builder.getShader(GrGLShaderBuilder::kGeometry_ShaderType, &shader); - if (c_PrintShaders) { - GrPrintf(shader.c_str()); - GrPrintf("\n"); - } - if (!(fGShaderID = compile_shader(fContext, GR_GL_GEOMETRY_SHADER, shader))) { - return false; - } - } -#endif - - builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); - if (c_PrintShaders) { - GrPrintf(shader.c_str()); - GrPrintf("\n"); - } - if (!(fFShaderID = compile_shader(fContext, GR_GL_FRAGMENT_SHADER, shader))) { - return false; - } - - return true; -} - -bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { - GrAssert(0 == fProgramID); - - GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc); - - SkXfermode::Coeff colorCoeff, uniformCoeff; - // The rest of transfer mode color filters have not been implemented - if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) { - GR_DEBUGCODE(bool success =) - SkXfermode::ModeAsCoeff(static_cast - (fDesc.fColorFilterXfermode), - &uniformCoeff, &colorCoeff); - GR_DEBUGASSERT(success); - } else { - colorCoeff = SkXfermode::kOne_Coeff; - uniformCoeff = SkXfermode::kZero_Coeff; - } - - // no need to do the color filter if coverage is 0. The output color is scaled by the coverage. - // All the dual source outputs are scaled by the coverage as well. - if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput) { - colorCoeff = SkXfermode::kZero_Coeff; - uniformCoeff = SkXfermode::kZero_Coeff; - } - - // If we know the final color is going to be all zeros then we can - // simplify the color filter coefficients. needComputedColor will then - // come out false below. - if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fColorInput) { - colorCoeff = SkXfermode::kZero_Coeff; - if (SkXfermode::kDC_Coeff == uniformCoeff || - SkXfermode::kDA_Coeff == uniformCoeff) { - uniformCoeff = SkXfermode::kZero_Coeff; - } else if (SkXfermode::kIDC_Coeff == uniformCoeff || - SkXfermode::kIDA_Coeff == uniformCoeff) { - uniformCoeff = SkXfermode::kOne_Coeff; - } - } - - bool needColorFilterUniform; - bool needComputedColor; - need_blend_inputs(uniformCoeff, colorCoeff, - &needColorFilterUniform, &needComputedColor); - - // the dual source output has no canonical var name, have to - // declare an output, which is incompatible with gl_FragColor/gl_FragData. - bool dualSourceOutputWritten = false; - - GrGLShaderVar colorOutput; - bool isColorDeclared = GrGLSLSetupFSColorOuput(fContext.info().glslGeneration(), - declared_color_output_name(), - &colorOutput); - if (isColorDeclared) { - builder.fFSOutputs.push_back(colorOutput); - } - - const char* viewMName; - fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, - kMat33f_GrSLType, "ViewM", &viewMName); - - - builder.vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" - "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n", - viewMName, builder.positionAttribute().getName().c_str()); - - // incoming color to current stage being processed. - SkString inColor; - - if (needComputedColor) { - this->genInputColor(&builder, &inColor); - } - - // we output point size in the GS if present - if (fDesc.fEmitsPointSize -#if GR_GL_EXPERIMENTAL_GS - && !fDesc.fExperimentalGS -#endif - ) { - builder.vsCodeAppend("\tgl_PointSize = 1.0;\n"); - } - - /////////////////////////////////////////////////////////////////////////// - // compute the final color - - // if we have color stages string them together, feeding the output color - // of each to the next and generating code for each stage. - if (needComputedColor) { - SkString outColor; - for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) { - if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) { - // create var to hold stage result - outColor = "color"; - outColor.appendS32(s); - builder.fsCodeAppendf("\tvec4 %s;\n", outColor.c_str()); - - builder.setCurrentStage(s); - fEffects[s] = builder.createAndEmitGLEffect(*stages[s], - fDesc.fEffectKeys[s], - inColor.size() ? inColor.c_str() : NULL, - outColor.c_str(), - &fUniformHandles.fEffectSamplerUnis[s]); - builder.setNonStage(); - inColor = outColor; - } - } - } - - // if have all ones or zeros for the "dst" input to the color filter then we - // may be able to make additional optimizations. - if (needColorFilterUniform && needComputedColor && !inColor.size()) { - GrAssert(GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.fColorInput); - bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || - SkXfermode::kIDA_Coeff == uniformCoeff; - if (uniformCoeffIsZero) { - uniformCoeff = SkXfermode::kZero_Coeff; - bool bogus; - need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff, - &needColorFilterUniform, &bogus); - } - } - const char* colorFilterColorUniName = NULL; - if (needColorFilterUniform) { - fUniformHandles.fColorFilterUni = builder.addUniform( - GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "FilterColor", - &colorFilterColorUniName); - } - bool wroteFragColorZero = false; - if (SkXfermode::kZero_Coeff == uniformCoeff && - SkXfermode::kZero_Coeff == colorCoeff) { - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4)); - wroteFragColorZero = true; - } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { - builder.fsCodeAppend("\tvec4 filteredColor;\n"); - const char* color = adjustInColor(inColor); - add_color_filter(&builder, "filteredColor", uniformCoeff, - colorCoeff, colorFilterColorUniName, color); - inColor = "filteredColor"; - } - - /////////////////////////////////////////////////////////////////////////// - // compute the partial coverage (coverage stages and edge aa) - - SkString inCoverage; - bool coverageIsZero = GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput; - // we don't need to compute coverage at all if we know the final shader - // output will be zero and we don't have a dual src blend output. - if (!wroteFragColorZero || GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { - - if (!coverageIsZero) { - switch (fDesc.fCoverageInput) { - case GrGLProgramDesc::kSolidWhite_ColorInput: - // empty string implies solid white - break; - case GrGLProgramDesc::kAttribute_ColorInput: - gen_attribute_coverage(&builder, &inCoverage); - break; - case GrGLProgramDesc::kUniform_ColorInput: - this->genUniformCoverage(&builder, &inCoverage); - break; - default: - GrCrash("Unexpected input coverage."); - } - - SkString outCoverage; - const int& startStage = fDesc.fFirstCoverageStage; - for (int s = startStage; s < GrDrawState::kNumStages; ++s) { - if (fDesc.fEffectKeys[s]) { - // create var to hold stage output - outCoverage = "coverage"; - outCoverage.appendS32(s); - builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str()); - - builder.setCurrentStage(s); - fEffects[s] = builder.createAndEmitGLEffect( - *stages[s], - fDesc.fEffectKeys[s], - inCoverage.size() ? inCoverage.c_str() : NULL, - outCoverage.c_str(), - &fUniformHandles.fEffectSamplerUnis[s]); - builder.setNonStage(); - inCoverage = outCoverage; - } - } - - // discard if coverage is zero - if (fDesc.fDiscardIfZeroCoverage && !outCoverage.isEmpty()) { - builder.fsCodeAppendf( - "\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n", - outCoverage.c_str()); - } - } - - if (GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) { - builder.fFSOutputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - dual_source_output_name()); - bool outputIsZero = coverageIsZero; - SkString coeff; - if (!outputIsZero && - GrGLProgramDesc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) { - if (!inColor.size()) { - outputIsZero = true; - } else { - if (GrGLProgramDesc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) { - coeff.printf("(1 - %s.a)", inColor.c_str()); - } else { - coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); - } - } - } - if (outputIsZero) { - builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), GrGLSLZerosVecf(4)); - } else { - SkString modulate; - GrGLSLModulate4f(&modulate, coeff.c_str(), inCoverage.c_str()); - builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str()); - } - dualSourceOutputWritten = true; - } - } - - /////////////////////////////////////////////////////////////////////////// - // combine color and coverage as frag color - - if (!wroteFragColorZero) { - if (coverageIsZero) { - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4)); - } else { - SkString modulate; - GrGLSLModulate4f(&modulate, inColor.c_str(), inCoverage.c_str()); - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str()); - } - } - - /////////////////////////////////////////////////////////////////////////// - // insert GS -#if GR_DEBUG - this->genGeometryShader(&builder); -#endif - - /////////////////////////////////////////////////////////////////////////// - // compile and setup attribs and unis - - if (!this->compileShaders(builder)) { - return false; - } - - if (!this->bindOutputsAttribsAndLinkProgram(builder, - isColorDeclared, - dualSourceOutputWritten)) { - return false; - } - - builder.finished(fProgramID); - fUniformHandles.fRTHeightUni = builder.getRTHeightUniform(); - fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform(); - fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform(); - fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform(); - // This must be called after we set fDstCopySamplerUni above. - this->initSamplerUniforms(); - - return true; -} - -bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder, - bool bindColorOut, - bool bindDualSrcOut) { - GL_CALL_RET(fProgramID, CreateProgram()); - if (!fProgramID) { - return false; - } - - GL_CALL(AttachShader(fProgramID, fVShaderID)); - if (fGShaderID) { - GL_CALL(AttachShader(fProgramID, fGShaderID)); - } - GL_CALL(AttachShader(fProgramID, fFShaderID)); - - if (bindColorOut) { - GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name())); - } - if (bindDualSrcOut) { - GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name())); - } - - // Bind the attrib locations to same values for all shaders - GL_CALL(BindAttribLocation(fProgramID, - fDesc.fPositionAttributeIndex, - builder.positionAttribute().c_str())); - if (-1 != fDesc.fLocalCoordAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, - fDesc.fLocalCoordAttributeIndex, - builder.localCoordsAttribute().c_str())); - } - if (-1 != fDesc.fColorAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, fDesc.fColorAttributeIndex, COL_ATTR_NAME)); - } - if (-1 != fDesc.fCoverageAttributeIndex) { - GL_CALL(BindAttribLocation(fProgramID, fDesc.fCoverageAttributeIndex, COV_ATTR_NAME)); - } - - const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end(); - for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin(); - attrib != attribEnd; - ++attrib) { - GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str())); - } - - GL_CALL(LinkProgram(fProgramID)); - - GrGLint linked = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked)); - if (!linked) { - GrGLint infoLen = GR_GL_INIT_ZERO; - GL_CALL(GetProgramiv(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(fProgramID, - infoLen+1, - &length, - (char*)log.get())); - GrPrintf((char*)log.get()); - } - GrAssert(!"Error linking program"); - GL_CALL(DeleteProgram(fProgramID)); - fProgramID = 0; - return false; - } - return true; -} - -void GrGLProgram::initSamplerUniforms() { - GL_CALL(UseProgram(fProgramID)); - // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes - // this behavior. - GrGLint texUnitIdx = 0; - if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopySamplerUni) { - fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx); - ++texUnitIdx; - } - - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count(); - for (int u = 0; u < numSamplers; ++u) { - UniformHandle handle = fUniformHandles.fEffectSamplerUnis[s][u]; - if (GrGLUniformManager::kInvalidUniformHandle != handle) { - fUniformManager.setSampler(handle, texUnitIdx); - ++texUnitIdx; - } - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void GrGLProgram::setData(GrGpuGL* gpu, - GrColor color, - GrColor coverage, - const GrDeviceCoordTexture* dstCopy, - SharedGLState* sharedState) { - const GrDrawState& drawState = gpu->getDrawState(); - - this->setColor(drawState, color, sharedState); - this->setCoverage(drawState, coverage, sharedState); - this->setMatrixAndRenderTargetHeight(drawState); - - // Setup the SkXfermode::Mode-based colorfilter uniform if necessary - if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fColorFilterUni && - fColorFilterColor != drawState.getColorFilterColor()) { - GrGLfloat c[4]; - GrColorToRGBAFloat(drawState.getColorFilterColor(), c); - fUniformManager.set4fv(fUniformHandles.fColorFilterUni, 0, 1, c); - fColorFilterColor = drawState.getColorFilterColor(); - } - - GrGLint texUnitIdx = 0; - if (NULL != dstCopy) { - if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopyTopLeftUni) { - GrAssert(GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fDstCopyScaleUni); - GrAssert(GrGLUniformManager::kInvalidUniformHandle != - fUniformHandles.fDstCopySamplerUni); - fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni, - static_cast(dstCopy->offset().fX), - static_cast(dstCopy->offset().fY)); - fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni, - 1.f / dstCopy->texture()->width(), - 1.f / dstCopy->texture()->height()); - GrGLTexture* texture = static_cast(dstCopy->texture()); - static GrTextureParams kParams; // the default is clamp, nearest filtering. - gpu->bindTexture(texUnitIdx, kParams, texture); - ++texUnitIdx; - } else { - GrAssert(GrGLUniformManager::kInvalidUniformHandle == - fUniformHandles.fDstCopyScaleUni); - GrAssert(GrGLUniformManager::kInvalidUniformHandle == - fUniformHandles.fDstCopySamplerUni); - } - } else { - GrAssert(GrGLUniformManager::kInvalidUniformHandle == - fUniformHandles.fDstCopyTopLeftUni); - GrAssert(GrGLUniformManager::kInvalidUniformHandle == - fUniformHandles.fDstCopyScaleUni); - GrAssert(GrGLUniformManager::kInvalidUniformHandle == - fUniformHandles.fDstCopySamplerUni); - } - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (NULL != fEffects[s]) { - const GrEffectStage& stage = drawState.getStage(s); - GrAssert(NULL != stage.getEffect()); - - bool explicitLocalCoords = -1 != fDesc.fLocalCoordAttributeIndex; - GrDrawEffect drawEffect(stage, explicitLocalCoords); - fEffects[s]->setData(fUniformManager, drawEffect); - int numSamplers = fUniformHandles.fEffectSamplerUnis[s].count(); - for (int u = 0; u < numSamplers; ++u) { - UniformHandle handle = fUniformHandles.fEffectSamplerUnis[s][u]; - if (GrGLUniformManager::kInvalidUniformHandle != handle) { - const GrTextureAccess& access = (*stage.getEffect())->textureAccess(u); - GrGLTexture* texture = static_cast(access.getTexture()); - gpu->bindTexture(texUnitIdx, access.getParams(), texture); - ++texUnitIdx; - } - } - } - } -} - -void GrGLProgram::setColor(const GrDrawState& drawState, - GrColor color, - SharedGLState* sharedState) { - if (!drawState.hasColorVertexAttribute()) { - switch (fDesc.fColorInput) { - case GrGLProgramDesc::kAttribute_ColorInput: - GrAssert(-1 != fDesc.fColorAttributeIndex); - if (sharedState->fConstAttribColor != color || - sharedState->fConstAttribColorIndex != fDesc.fColorAttributeIndex) { - // OpenGL ES only supports the float varieties of glVertexAttrib - GrGLfloat c[4]; - GrColorToRGBAFloat(color, c); - GL_CALL(VertexAttrib4fv(fDesc.fColorAttributeIndex, c)); - sharedState->fConstAttribColor = color; - sharedState->fConstAttribColorIndex = fDesc.fColorAttributeIndex; - } - break; - case GrGLProgramDesc::kUniform_ColorInput: - if (fColor != color) { - // OpenGL ES doesn't support unsigned byte varieties of glUniform - GrGLfloat c[4]; - GrColorToRGBAFloat(color, c); - GrAssert(GrGLUniformManager::kInvalidUniformHandle != - fUniformHandles.fColorUni); - fUniformManager.set4fv(fUniformHandles.fColorUni, 0, 1, c); - fColor = color; - } - sharedState->fConstAttribColorIndex = -1; - break; - case GrGLProgramDesc::kSolidWhite_ColorInput: - case GrGLProgramDesc::kTransBlack_ColorInput: - sharedState->fConstAttribColorIndex = -1; - break; - default: - GrCrash("Unknown color type."); - } - } else { - sharedState->fConstAttribColorIndex = -1; - } -} - -void GrGLProgram::setCoverage(const GrDrawState& drawState, - GrColor coverage, - SharedGLState* sharedState) { - if (!drawState.hasCoverageVertexAttribute()) { - switch (fDesc.fCoverageInput) { - case GrGLProgramDesc::kAttribute_ColorInput: - if (sharedState->fConstAttribCoverage != coverage || - sharedState->fConstAttribCoverageIndex != fDesc.fCoverageAttributeIndex) { - // OpenGL ES only supports the float varieties of glVertexAttrib - GrGLfloat c[4]; - GrColorToRGBAFloat(coverage, c); - GL_CALL(VertexAttrib4fv(fDesc.fCoverageAttributeIndex, c)); - sharedState->fConstAttribCoverage = coverage; - sharedState->fConstAttribCoverageIndex = fDesc.fCoverageAttributeIndex; - } - break; - case GrGLProgramDesc::kUniform_ColorInput: - if (fCoverage != coverage) { - // OpenGL ES doesn't support unsigned byte varieties of glUniform - GrGLfloat c[4]; - GrColorToRGBAFloat(coverage, c); - GrAssert(GrGLUniformManager::kInvalidUniformHandle != - fUniformHandles.fCoverageUni); - fUniformManager.set4fv(fUniformHandles.fCoverageUni, 0, 1, c); - fCoverage = coverage; - } - sharedState->fConstAttribCoverageIndex = -1; - break; - case GrGLProgramDesc::kSolidWhite_ColorInput: - case GrGLProgramDesc::kTransBlack_ColorInput: - sharedState->fConstAttribCoverageIndex = -1; - break; - default: - GrCrash("Unknown coverage type."); - } - } else { - sharedState->fConstAttribCoverageIndex = -1; - } -} - -void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) { - const GrRenderTarget* rt = drawState.getRenderTarget(); - SkISize size; - size.set(rt->width(), rt->height()); - - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. - if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni && - fMatrixState.fRenderTargetSize.fHeight != size.fHeight) { - fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight)); - } - - if (fMatrixState.fRenderTargetOrigin != rt->origin() || - !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) || - fMatrixState.fRenderTargetSize != size) { - SkMatrix m; - if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { - m.setAll( - SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1, - 0,-SkIntToScalar(2) / size.fHeight, SK_Scalar1, - 0, 0, SkMatrix::I()[8]); - } else { - m.setAll( - SkIntToScalar(2) / size.fWidth, 0, -SK_Scalar1, - 0, SkIntToScalar(2) / size.fHeight,-SK_Scalar1, - 0, 0, SkMatrix::I()[8]); - } - m.setConcat(m, drawState.getViewMatrix()); - - // ES doesn't allow you to pass true to the transpose param so we do our own transpose. - GrGLfloat mt[] = { - SkScalarToFloat(m[SkMatrix::kMScaleX]), - SkScalarToFloat(m[SkMatrix::kMSkewY]), - SkScalarToFloat(m[SkMatrix::kMPersp0]), - SkScalarToFloat(m[SkMatrix::kMSkewX]), - SkScalarToFloat(m[SkMatrix::kMScaleY]), - SkScalarToFloat(m[SkMatrix::kMPersp1]), - SkScalarToFloat(m[SkMatrix::kMTransX]), - SkScalarToFloat(m[SkMatrix::kMTransY]), - SkScalarToFloat(m[SkMatrix::kMPersp2]) - }; - fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, mt); - fMatrixState.fViewMatrix = drawState.getViewMatrix(); - fMatrixState.fRenderTargetSize = size; - fMatrixState.fRenderTargetOrigin = rt->origin(); - } -} diff --git a/gfx/skia/src/gpu/gl/GrGLProgramDesc.cpp b/gfx/skia/src/gpu/gl/GrGLProgramDesc.cpp deleted file mode 100644 index 73846b8df380..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLProgramDesc.cpp +++ /dev/null @@ -1,191 +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 "GrGLProgramDesc.h" -#include "GrBackendEffectFactory.h" -#include "GrDrawEffect.h" -#include "GrEffect.h" -#include "GrGLShaderBuilder.h" -#include "GrGpuGL.h" - -void GrGLProgramDesc::Build(const GrDrawState& drawState, - bool isPoints, - GrDrawState::BlendOptFlags blendOpts, - GrBlendCoeff srcCoeff, - GrBlendCoeff dstCoeff, - const GrGpuGL* gpu, - const GrDeviceCoordTexture* dstCopy, - GrGLProgramDesc* desc) { - - // This should already have been caught - GrAssert(!(GrDrawState::kSkipDraw_BlendOptFlag & blendOpts)); - - bool skipCoverage = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); - - bool skipColor = SkToBool(blendOpts & (GrDrawState::kEmitTransBlack_BlendOptFlag | - GrDrawState::kEmitCoverage_BlendOptFlag)); - - // The descriptor is used as a cache key. Thus when a field of the - // descriptor will not affect program generation (because of the attribute - // bindings in use or other descriptor field settings) it should be set - // to a canonical value to avoid duplicate programs with different keys. - - - desc->fEmitsPointSize = isPoints; - - bool requiresColorAttrib = !skipColor && drawState.hasColorVertexAttribute(); - bool requiresCoverageAttrib = !skipCoverage && drawState.hasCoverageVertexAttribute(); - // we only need the local coords if we're actually going to generate effect code - bool requiresLocalCoordAttrib = !(skipCoverage && skipColor) && - drawState.hasLocalCoordAttribute(); - - // fColorInput/fCoverageInput records how colors are specified for the program so we strip the - // bits from the bindings to avoid false negatives when searching for an existing program in the - // cache. - - desc->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode(); - - - bool colorIsTransBlack = SkToBool(blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag); - bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) || - (!requiresColorAttrib && 0xffffffff == drawState.getColor()); - if (colorIsTransBlack) { - desc->fColorInput = kTransBlack_ColorInput; - } else if (colorIsSolidWhite) { - desc->fColorInput = kSolidWhite_ColorInput; - } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresColorAttrib) { - desc->fColorInput = kUniform_ColorInput; - } else { - desc->fColorInput = kAttribute_ColorInput; - } - - bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage(); - - if (skipCoverage) { - desc->fCoverageInput = kTransBlack_ColorInput; - } else if (covIsSolidWhite) { - desc->fCoverageInput = kSolidWhite_ColorInput; - } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresCoverageAttrib) { - desc->fCoverageInput = kUniform_ColorInput; - } else { - desc->fCoverageInput = kAttribute_ColorInput; - } - - bool readsDst = false; - int lastEnabledStage = -1; - - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - - bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage; - if (!skip && drawState.isStageEnabled(s)) { - lastEnabledStage = s; - const GrEffectRef& effect = *drawState.getStage(s).getEffect(); - const GrBackendEffectFactory& factory = effect->getFactory(); - GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib); - desc->fEffectKeys[s] = factory.glEffectKey(drawEffect, gpu->glCaps()); - if (effect->willReadDst()) { - readsDst = true; - } - } else { - desc->fEffectKeys[s] = 0; - } - } - - if (readsDst) { - GrAssert(NULL != dstCopy); - desc->fDstRead = GrGLShaderBuilder::KeyForDstRead(dstCopy->texture(), gpu->glCaps()); - GrAssert(0 != desc->fDstRead); - } else { - desc->fDstRead = 0; - } - - desc->fDualSrcOutput = kNone_DualSrcOutput; - - // 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). -#if GR_GL_EXPERIMENTAL_GS -#if 0 - desc->fExperimentalGS = gpu->caps().geometryShaderSupport(); -#else - desc->fExperimentalGS = false; -#endif -#endif - - // We leave this set to kNumStages until we discover that the coverage/color distinction is - // material to the generated program. We do this to avoid distinct keys that generate equivalent - // programs. - desc->fFirstCoverageStage = GrDrawState::kNumStages; - // This tracks the actual first coverage stage. - int firstCoverageStage = GrDrawState::kNumStages; - desc->fDiscardIfZeroCoverage = false; // Enabled below if stenciling and there is coverage. - bool hasCoverage = false; - // If we're rendering coverage-as-color then it's as though there are no coverage stages. - if (!drawState.isCoverageDrawing()) { - // We can have coverage either through a stage or coverage vertex attributes. - if (drawState.getFirstCoverageStage() <= lastEnabledStage) { - firstCoverageStage = drawState.getFirstCoverageStage(); - hasCoverage = true; - } else { - hasCoverage = requiresCoverageAttrib; - } - } - - if (hasCoverage) { - // color filter is applied between color/coverage computation - if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { - desc->fFirstCoverageStage = firstCoverageStage; - } - - // If we're stenciling then we want to discard samples that have zero coverage - if (drawState.getStencil().doesWrite()) { - desc->fDiscardIfZeroCoverage = true; - desc->fFirstCoverageStage = firstCoverageStage; - } - - if (gpu->caps()->dualSourceBlendingSupport() && - !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag | - GrDrawState::kCoverageAsAlpha_BlendOptFlag))) { - if (kZero_GrBlendCoeff == dstCoeff) { - // write the coverage value to second color - desc->fDualSrcOutput = kCoverage_DualSrcOutput; - desc->fFirstCoverageStage = firstCoverageStage; - } else if (kSA_GrBlendCoeff == dstCoeff) { - // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. - desc->fDualSrcOutput = kCoverageISA_DualSrcOutput; - desc->fFirstCoverageStage = firstCoverageStage; - } else if (kSC_GrBlendCoeff == dstCoeff) { - // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. - desc->fDualSrcOutput = kCoverageISC_DualSrcOutput; - desc->fFirstCoverageStage = firstCoverageStage; - } - } - } - - desc->fPositionAttributeIndex = drawState.positionAttributeIndex(); - desc->fLocalCoordAttributeIndex = drawState.localCoordAttributeIndex(); - - // For constant color and coverage we need an attribute with an index beyond those already set - int availableAttributeIndex = drawState.getVertexAttribCount(); - if (requiresColorAttrib) { - desc->fColorAttributeIndex = drawState.colorVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fColorInput) { - GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - desc->fColorAttributeIndex = availableAttributeIndex; - availableAttributeIndex++; - } else { - desc->fColorAttributeIndex = -1; - } - - if (requiresCoverageAttrib) { - desc->fCoverageAttributeIndex = drawState.coverageVertexAttributeIndex(); - } else if (GrGLProgramDesc::kAttribute_ColorInput == desc->fCoverageInput) { - GrAssert(availableAttributeIndex < GrDrawState::kMaxVertexAttribCnt); - desc->fCoverageAttributeIndex = availableAttributeIndex; - } else { - desc->fCoverageAttributeIndex = -1; - } -} diff --git a/gfx/skia/src/gpu/gl/GrGLProgramDesc.h b/gfx/skia/src/gpu/gl/GrGLProgramDesc.h deleted file mode 100644 index d2167c758b01..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLProgramDesc.h +++ /dev/null @@ -1,115 +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 GrGLProgramDesc_DEFINED -#define GrGLProgramDesc_DEFINED - -#include "GrGLEffect.h" -#include "GrDrawState.h" -#include "GrGLShaderBuilder.h" - -class GrGpuGL; - -// optionally compile the experimental GS code. Set to GR_DEBUG so that debug build bots will -// execute the code. -#define GR_GL_EXPERIMENTAL_GS GR_DEBUG - - -/** This class describes a program to generate. It also serves as a program cache key. Very little - of this is GL-specific. There is the generation of GrGLEffect::EffectKeys and the dst-read part - of the key set by GrGLShaderBuilder. If the interfaces that set those portions were abstracted - to be API-neutral then so could this class. */ -class GrGLProgramDesc { -public: - GrGLProgramDesc() { - // since we use this as part of a key we can't have any uninitialized padding - memset(this, 0, sizeof(GrGLProgramDesc)); - } - - // Returns this as a uint32_t array to be used as a key in the program cache - const uint32_t* asKey() const { - return reinterpret_cast(this); - } - - // For unit testing. - void setRandom(SkMWCRandom*, - const GrGpuGL* gpu, - const GrTexture* dummyDstTexture, - const GrEffectStage stages[GrDrawState::kNumStages], - int currAttribIndex); - - /** - * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the - * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs. - */ - static void Build(const GrDrawState&, - bool isPoints, - GrDrawState::BlendOptFlags, - GrBlendCoeff srcCoeff, - GrBlendCoeff dstCoeff, - const GrGpuGL* gpu, - const GrDeviceCoordTexture* dstCopy, - GrGLProgramDesc* outDesc); - -private: - // Specifies where the initial color comes from before the stages are applied. - enum ColorInput { - kSolidWhite_ColorInput, - kTransBlack_ColorInput, - kAttribute_ColorInput, - kUniform_ColorInput, - - kColorInputCnt - }; - // Dual-src blending makes use of a secondary output color that can be - // used as a per-pixel blend coefficient. This controls whether a - // secondary source is output and what value it holds. - enum DualSrcOutput { - kNone_DualSrcOutput, - kCoverage_DualSrcOutput, - kCoverageISA_DualSrcOutput, - kCoverageISC_DualSrcOutput, - - kDualSrcOutputCnt - }; - - /** Non-zero if this stage has an effect */ - GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; - - // To enable experimental geometry shader code (not for use in - // production) -#if GR_GL_EXPERIMENTAL_GS - bool fExperimentalGS; -#endif - - GrGLShaderBuilder::DstReadKey fDstRead; // set by GrGLShaderBuilder if there - // are effects that must read the dst. - // Otherwise, 0. - - // should the FS discard if the coverage is zero (to avoid stencil manipulation) - SkBool8 fDiscardIfZeroCoverage; - - uint8_t fColorInput; // casts to enum ColorInput - uint8_t fCoverageInput; // casts to enum ColorInput - uint8_t fDualSrcOutput; // casts to enum DualSrcOutput - - int8_t fFirstCoverageStage; - SkBool8 fEmitsPointSize; - uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode - - int8_t fPositionAttributeIndex; - int8_t fLocalCoordAttributeIndex; - int8_t fColorAttributeIndex; - int8_t fCoverageAttributeIndex; - - // GrGLProgram and GrGLShaderBuilder read the private fields to generate code. TODO: Move all - // code generation to GrGLShaderBuilder (and maybe add getters rather than friending). - friend class GrGLProgram; - friend class GrGLShaderBuilder; -}; - -#endif diff --git a/gfx/skia/src/gpu/gl/GrGLSL.cpp b/gfx/skia/src/gpu/gl/GrGLSL.cpp deleted file mode 100644 index 3ec7fc45b215..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLSL.cpp +++ /dev/null @@ -1,202 +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 "GrGLSL.h" -#include "GrGLShaderVar.h" -#include "SkString.h" - -GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, const GrGLInterface* gl) { - GrGLSLVersion ver = GrGLGetGLSLVersion(gl); - switch (binding) { - case kDesktop_GrGLBinding: - GrAssert(ver >= GR_GLSL_VER(1,10)); - if (ver >= GR_GLSL_VER(1,50)) { - return k150_GrGLSLGeneration; - } else if (ver >= GR_GLSL_VER(1,40)) { - return k140_GrGLSLGeneration; - } else if (ver >= GR_GLSL_VER(1,30)) { - return k130_GrGLSLGeneration; - } else { - return k110_GrGLSLGeneration; - } - case kES2_GrGLBinding: - // version 1.00 of ES GLSL based on ver 1.20 of desktop GLSL - GrAssert(ver >= GR_GL_VER(1,00)); - return k110_GrGLSLGeneration; - default: - GrCrash("Unknown GL Binding"); - return k110_GrGLSLGeneration; // suppress warning - } -} - -const char* GrGetGLSLVersionDecl(GrGLBinding binding, GrGLSLGeneration gen) { - switch (gen) { - case k110_GrGLSLGeneration: - if (kES2_GrGLBinding == binding) { - // ES2s shader language is based on version 1.20 but is version - // 1.00 of the ES language. - return "#version 100\n"; - } else { - GrAssert(kDesktop_GrGLBinding == binding); - return "#version 110\n"; - } - case k130_GrGLSLGeneration: - GrAssert(kDesktop_GrGLBinding == binding); - return "#version 130\n"; - case k140_GrGLSLGeneration: - GrAssert(kDesktop_GrGLBinding == binding); - return "#version 140\n"; - case k150_GrGLSLGeneration: - GrAssert(kDesktop_GrGLBinding == binding); - return "#version 150\n"; - default: - GrCrash("Unknown GL version."); - return ""; // suppress warning - } -} - -bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, GrGLShaderVar* var) { - bool declaredOutput = k110_GrGLSLGeneration != gen; - var->set(kVec4f_GrSLType, - GrGLShaderVar::kOut_TypeModifier, - declaredOutput ? nameIfDeclared : "gl_FragColor"); - return declaredOutput; -} - -const char* GrGLSLVectorHomogCoord(int count) { - static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"}; - GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS)); - return HOMOGS[count]; -} - -const char* GrGLSLVectorHomogCoord(GrSLType type) { - return GrGLSLVectorHomogCoord(GrSLTypeToVecLength(type)); -} - -const char* GrGLSLVectorNonhomogCoords(int count) { - static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"}; - GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS)); - return NONHOMOGS[count]; -} - -const char* GrGLSLVectorNonhomogCoords(GrSLType type) { - return GrGLSLVectorNonhomogCoords(GrSLTypeToVecLength(type)); -} - -GrSLConstantVec GrGLSLModulate4f(SkString* outAppend, - const char* in0, - const char* in1, - GrSLConstantVec default0, - GrSLConstantVec default1) { - GrAssert(NULL != outAppend); - - bool has0 = NULL != in0 && '\0' != *in0; - bool has1 = NULL != in1 && '\0' != *in1; - - GrAssert(has0 || kNone_GrSLConstantVec != default0); - GrAssert(has1 || kNone_GrSLConstantVec != default1); - - if (!has0 && !has1) { - GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0); - GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1); - if (kZeros_GrSLConstantVec == default0 || kZeros_GrSLConstantVec == default1) { - outAppend->append(GrGLSLZerosVecf(4)); - return kZeros_GrSLConstantVec; - } else { - // both inputs are ones vectors - outAppend->append(GrGLSLOnesVecf(4)); - return kOnes_GrSLConstantVec; - } - } else if (!has0) { - GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0); - if (kZeros_GrSLConstantVec == default0) { - outAppend->append(GrGLSLZerosVecf(4)); - return kZeros_GrSLConstantVec; - } else { - outAppend->appendf("vec4(%s)", in1); - return kNone_GrSLConstantVec; - } - } else if (!has1) { - GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1); - if (kZeros_GrSLConstantVec == default1) { - outAppend->append(GrGLSLZerosVecf(4)); - return kZeros_GrSLConstantVec; - } else { - outAppend->appendf("vec4(%s)", in0); - return kNone_GrSLConstantVec; - } - } else { - outAppend->appendf("vec4(%s * %s)", in0, in1); - return kNone_GrSLConstantVec; - } -} - -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); - outAppend->append(kTabs, cnt); - tabCnt -= cnt; - } -} -} - -GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend, - int tabCnt, - const char* vec4VarName, - const char* mulFactor, - GrSLConstantVec mulFactorDefault) { - bool haveFactor = NULL != mulFactor && '\0' != *mulFactor; - - GrAssert(NULL != outAppend); - GrAssert(NULL != vec4VarName); - GrAssert(kNone_GrSLConstantVec != mulFactorDefault || haveFactor); - - if (!haveFactor) { - if (kOnes_GrSLConstantVec == mulFactorDefault) { - return kNone_GrSLConstantVec; - } else { - GrAssert(kZeros_GrSLConstantVec == mulFactorDefault); - append_tabs(outAppend, tabCnt); - outAppend->appendf("%s = vec4(0, 0, 0, 0);\n", vec4VarName); - return kZeros_GrSLConstantVec; - } - } - append_tabs(outAppend, tabCnt); - outAppend->appendf("%s *= %s;\n", vec4VarName, mulFactor); - return kNone_GrSLConstantVec; -} - -GrSLConstantVec GrGLSLAdd4f(SkString* outAppend, - const char* in0, - const char* in1, - GrSLConstantVec default0, - GrSLConstantVec default1) { - GrAssert(NULL != outAppend); - - bool has0 = NULL != in0 && '\0' != *in0; - bool has1 = NULL != in1 && '\0' != *in1; - - if (!has0 && !has1) { - GrAssert(kZeros_GrSLConstantVec == default0); - GrAssert(kZeros_GrSLConstantVec == default1); - outAppend->append(GrGLSLZerosVecf(4)); - return kZeros_GrSLConstantVec; - } else if (!has0) { - GrAssert(kZeros_GrSLConstantVec == default0); - outAppend->appendf("vec4(%s)", in1); - return kNone_GrSLConstantVec; - } else if (!has1) { - GrAssert(kZeros_GrSLConstantVec == default1); - outAppend->appendf("vec4(%s)", in0); - return kNone_GrSLConstantVec; - } else { - outAppend->appendf("(vec4(%s) + vec4(%s))", in0, in1); - return kNone_GrSLConstantVec; - } -} diff --git a/gfx/skia/src/gpu/gl/GrGLSL.h b/gfx/skia/src/gpu/gl/GrGLSL.h deleted file mode 100644 index 940501cd3e7d..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLSL.h +++ /dev/null @@ -1,165 +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 GrGLSL_DEFINED -#define GrGLSL_DEFINED - -#include "gl/GrGLInterface.h" -#include "GrTypesPriv.h" - -class GrGLShaderVar; -class SkString; - -// Limited set of GLSL versions we build shaders for. Caller should round -// down the GLSL version to one of these enums. -enum GrGLSLGeneration { - /** - * Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20) - */ - k110_GrGLSLGeneration, - /** - * Desktop GLSL 1.30 - */ - k130_GrGLSLGeneration, - /** - * Desktop GLSL 1.40 - */ - k140_GrGLSLGeneration, - /** - * Desktop GLSL 1.50 - */ - k150_GrGLSLGeneration, -}; - -enum GrSLConstantVec { - kZeros_GrSLConstantVec, - kOnes_GrSLConstantVec, - kNone_GrSLConstantVec, -}; - -namespace { -static inline int GrSLTypeToVecLength(GrSLType type) { - static const int kVecLengths[] = { - 0, // kVoid_GrSLType - 1, // kFloat_GrSLType - 2, // kVec2f_GrSLType - 3, // kVec3f_GrSLType - 4, // kVec4f_GrSLType - 1, // kMat33f_GrSLType - 1, // kMat44f_GrSLType - 1, // kSampler2D_GrSLType - }; - GrAssert((size_t) type < GR_ARRAY_COUNT(kVecLengths)); - return kVecLengths[type]; -} - -static inline const char* GrGLSLOnesVecf(int count) { - static const char* kONESVEC[] = {"ERROR", "1.0", "vec2(1,1)", - "vec3(1,1,1)", "vec4(1,1,1,1)"}; - GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(kONESVEC)); - return kONESVEC[count]; -} - -static inline const char* GrGLSLZerosVecf(int count) { - static const char* kZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)", - "vec3(0,0,0)", "vec4(0,0,0,0)"}; - GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(kZEROSVEC)); - return kZEROSVEC[count]; -} -} - -/** - * Gets the most recent GLSL Generation compatible with the OpenGL context. - */ -GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, - const GrGLInterface* gl); - -/** - * Returns a string to include at the beginning of a shader to declare the GLSL - * version. - */ -const char* GrGetGLSLVersionDecl(GrGLBinding binding, - GrGLSLGeneration v); - -/** - * Depending on the GLSL version being emitted there may be an assumed output - * variable from the fragment shader for the color. Otherwise, the shader must - * declare an output variable for the color. If this function returns true: - * * Parameter var's name will be set to nameIfDeclared - * * The variable must be declared in the fragment shader - * * The variable has to be bound as the color output - * (using glBindFragDataLocation) - * If the function returns false: - * * Parameter var's name will be set to the GLSL built-in color output name. - * * Do not declare the variable in the shader. - * * Do not use glBindFragDataLocation to bind the variable - * In either case var is initialized to represent the color output in the - * shader. - */ -bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, - const char* nameIfDeclared, - GrGLShaderVar* var); - -/** Convert a count of 1..n floats into the corresponding type enum, - e.g. 1 -> kFloat_GrSLType, 2 -> kVec2_GrSLType, ... */ -GrSLType GrSLFloatVectorType(int count); - -/** Return the GLSL swizzle operator for a homogenous component of a vector - with the given number of coordinates, e.g. 2 -> ".y", 3 -> ".z" */ -const char* GrGLSLVectorHomogCoord(int count); -const char* GrGLSLVectorHomogCoord(GrSLType type); - -/** Return the GLSL swizzle operator for a nonhomogenous components of a vector - with the given number of coordinates, e.g. 2 -> ".x", 3 -> ".xy" */ -const char* GrGLSLVectorNonhomogCoords(int count); -const char* GrGLSLVectorNonhomogCoords(GrSLType type); - -/** - * Produces a string that is the result of modulating two inputs. The inputs must be vec4 or - * float. The result is always a vec4. The inputs may be expressions, not just identifier names. - * Either can be NULL or "" in which case the default params control whether vec4(1,1,1,1) or - * vec4(0,0,0,0) is assumed. It is an error to pass kNone for default if in is NULL or "". - * Note that when if function determines that the result is a zeros or ones vec then any expression - * represented by in0 or in1 will not be emitted. The return value indicates whether a zeros, ones - * or neither was appended. - */ -GrSLConstantVec GrGLSLModulate4f(SkString* outAppend, - const char* in0, - const char* in1, - GrSLConstantVec default0 = kOnes_GrSLConstantVec, - GrSLConstantVec default1 = kOnes_GrSLConstantVec); - -/** - * Does an inplace mul, *=, of vec4VarName by mulFactor. If mulFactorDefault is not kNone then - * mulFactor may be either "" or NULL. In this case either nothing will be appended (kOnes) or an - * assignment of vec(0,0,0,0) will be appended (kZeros). The assignment is prepended by tabCnt tabs. - * A semicolon and newline are added after the assignment. (TODO: Remove tabCnt when we auto-insert - * tabs to GrGLEffect-generated lines.) If a zeros vec is assigned then the return value is - * kZeros, otherwise kNone. - */ -GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend, - int tabCnt, - const char* vec4VarName, - const char* mulFactor, - GrSLConstantVec mulFactorDefault = kOnes_GrSLConstantVec); - -/** - * Produces a string that is the result of adding two inputs. The inputs must be vec4 or float. - * The result is always a vec4. The inputs may be expressions, not just identifier names. Either - * can be NULL or "" in which case if the default is kZeros then vec4(0,0,0,0) is assumed. It is an - * error to pass kOnes for either default or to pass kNone for default if in is NULL or "". - * Note that if the function determines that the result is a zeros vec any expression represented - * by in0 or in1 will not be emitted. The return value indicates whether a zeros vec was appended - * or not. - */ -GrSLConstantVec GrGLSLAdd4f(SkString* outAppend, - const char* in0, - const char* in1, - GrSLConstantVec default0 = kZeros_GrSLConstantVec, - GrSLConstantVec default1 = kZeros_GrSLConstantVec); - -#endif diff --git a/gfx/skia/src/gpu/gl/GrGLShaderBuilder.cpp b/gfx/skia/src/gpu/gl/GrGLShaderBuilder.cpp deleted file mode 100644 index f7ecf367cf09..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLShaderBuilder.cpp +++ /dev/null @@ -1,657 +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 "gl/GrGLShaderBuilder.h" -#include "gl/GrGLProgram.h" -#include "gl/GrGLUniformHandle.h" -#include "GrDrawEffect.h" -#include "GrTexture.h" - -// number of each input/output type in a single allocation block -static const int kVarsPerBlock = 8; - -// except FS outputs where we expect 2 at most. -static const int kMaxFSOutputs = 2; - -// ES2 FS only guarantees mediump and lowp support -static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; - -typedef GrGLUniformManager::UniformHandle UniformHandle; -/////////////////////////////////////////////////////////////////////////////// - -namespace { - -inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { - if (kVec2f_GrSLType == type) { - return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; - } else { - GrAssert(kVec3f_GrSLType == type); - return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; - } -} - -/** - * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are - * present in the texture's config. swizzleComponentMask indicates the channels present in the - * shader swizzle. - */ -inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, - uint32_t configComponentMask, - uint32_t swizzleComponentMask) { - if (caps.textureSwizzleSupport()) { - // Any remapping is handled using texture swizzling not shader modifications. - return false; - } - // check if the texture is alpha-only - if (kA_GrColorComponentFlag == configComponentMask) { - if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { - // we must map the swizzle 'a's to 'r'. - return true; - } - if (kRGB_GrColorComponentFlags & swizzleComponentMask) { - // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that - // alpha-only textures smear alpha across all four channels when read. - return true; - } - } - return false; -} - -void append_swizzle(SkString* outAppend, - const GrGLShaderBuilder::TextureSampler& texSampler, - const GrGLCaps& caps) { - const char* swizzle = texSampler.swizzle(); - char mangledSwizzle[5]; - - // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle - // is available. - if (!caps.textureSwizzleSupport() && - (kA_GrColorComponentFlag == texSampler.configComponentMask())) { - char alphaChar = caps.textureRedSupport() ? 'r' : 'a'; - int i; - for (i = 0; '\0' != swizzle[i]; ++i) { - mangledSwizzle[i] = alphaChar; - } - mangledSwizzle[i] ='\0'; - swizzle = mangledSwizzle; - } - // For shader prettiness we omit the swizzle rather than appending ".rgba". - if (memcmp(swizzle, "rgba", 4)) { - outAppend->appendf(".%s", swizzle); - } -} - -} - -static const char kDstColorName[] = "_dstColor"; - -/////////////////////////////////////////////////////////////////////////////// - -GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo, - GrGLUniformManager& uniformManager, - const GrGLProgramDesc& desc) - : fUniforms(kVarsPerBlock) - , fVSAttrs(kVarsPerBlock) - , fVSOutputs(kVarsPerBlock) - , fGSInputs(kVarsPerBlock) - , fGSOutputs(kVarsPerBlock) - , fFSInputs(kVarsPerBlock) - , fFSOutputs(kMaxFSOutputs) - , fCtxInfo(ctxInfo) - , fUniformManager(uniformManager) - , fCurrentStageIdx(kNonStageIdx) - , fFSFeaturesAddedMask(0) -#if GR_GL_EXPERIMENTAL_GS - , fUsesGS(desc.fExperimentalGS) -#else - , fUsesGS(false) -#endif - , fSetupFragPosition(false) - , fRTHeightUniform(GrGLUniformManager::kInvalidUniformHandle) - , fDstCopyTopLeftUniform (GrGLUniformManager::kInvalidUniformHandle) - , fDstCopyScaleUniform (GrGLUniformManager::kInvalidUniformHandle) { - - fPositionVar = &fVSAttrs.push_back(); - fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition"); - if (-1 != desc.fLocalCoordAttributeIndex) { - fLocalCoordsVar = &fVSAttrs.push_back(); - fLocalCoordsVar->set(kVec2f_GrSLType, - GrGLShaderVar::kAttribute_TypeModifier, - "aLocalCoords"); - } else { - fLocalCoordsVar = fPositionVar; - } - if (kNoDstRead_DstReadKey != desc.fDstRead) { - bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & desc.fDstRead); - const char* dstCopyTopLeftName; - const char* dstCopyCoordScaleName; - uint32_t configMask; - if (SkToBool(kUseAlphaConfig_DstReadKeyBit & desc.fDstRead)) { - configMask = kA_GrColorComponentFlag; - } else { - configMask = kRGBA_GrColorComponentFlags; - } - fDstCopySampler.init(this, configMask, "rgba", 0); - - fDstCopyTopLeftUniform = this->addUniform(kFragment_ShaderType, - kVec2f_GrSLType, - "DstCopyUpperLeft", - &dstCopyTopLeftName); - fDstCopyScaleUniform = this->addUniform(kFragment_ShaderType, - 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", - fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); - if (!topDown) { - this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); - } - this->fsCodeAppendf("\tvec4 %s = ", kDstColorName); - this->appendTextureLookup(kFragment_ShaderType, fDstCopySampler, "_dstTexCoord"); - this->fsCodeAppend(";\n\n"); - } -} - -bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) { - switch (feature) { - case kStandardDerivatives_GLSLFeature: - if (!fCtxInfo.caps()->shaderDerivativeSupport()) { - return false; - } - if (kES2_GrGLBinding == fCtxInfo.binding()) { - this->addFSFeature(1 << kStandardDerivatives_GLSLFeature, - "GL_OES_standard_derivatives"); - } - return true; - default: - GrCrash("Unexpected GLSLFeature requested."); - return false; - } -} - -bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) { - switch (feature) { - case kFragCoordConventions_GLSLPrivateFeature: - if (!fCtxInfo.caps()->fragCoordConventionsSupport()) { - return false; - } - if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) { - this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, - "GL_ARB_fragment_coord_conventions"); - } - return true; - default: - GrCrash("Unexpected GLSLPrivateFeature requested."); - return false; - } -} - -void GrGLShaderBuilder::addFSFeature(uint32_t featureBit, const char* extensionName) { - if (!(featureBit & fFSFeaturesAddedMask)) { - fFSExtensions.appendf("#extension %s: require\n", extensionName); - fFSFeaturesAddedMask |= featureBit; - } -} - -const char* GrGLShaderBuilder::dstColor() const { - if (fDstCopySampler.isInitialized()) { - return kDstColorName; - } else { - return NULL; - } -} - -void GrGLShaderBuilder::codeAppendf(ShaderType type, const char format[], va_list args) { - SkString* string = NULL; - switch (type) { - case kVertex_ShaderType: - string = &fVSCode; - break; - case kGeometry_ShaderType: - string = &fGSCode; - break; - case kFragment_ShaderType: - string = &fFSCode; - break; - default: - GrCrash("Invalid shader type"); - } - string->appendf(format, args); -} - -void GrGLShaderBuilder::codeAppend(ShaderType type, const char* str) { - SkString* string = NULL; - switch (type) { - case kVertex_ShaderType: - string = &fVSCode; - break; - case kGeometry_ShaderType: - string = &fGSCode; - break; - case kFragment_ShaderType: - string = &fFSCode; - break; - default: - GrCrash("Invalid shader type"); - } - string->append(str); -} - -void GrGLShaderBuilder::appendTextureLookup(SkString* out, - const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) const { - GrAssert(NULL != coordName); - - out->appendf("%s(%s, %s)", - sample_function_name(varyingType, fCtxInfo.glslGeneration()), - this->getUniformCStr(sampler.fSamplerUniform), - coordName); - append_swizzle(out, sampler, *fCtxInfo.caps()); -} - -void GrGLShaderBuilder::appendTextureLookup(ShaderType type, - const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) { - GrAssert(kFragment_ShaderType == type); - this->appendTextureLookup(&fFSCode, sampler, coordName, varyingType); -} - -void GrGLShaderBuilder::appendTextureLookupAndModulate( - ShaderType type, - const char* modulation, - const GrGLShaderBuilder::TextureSampler& sampler, - const char* coordName, - GrSLType varyingType) { - GrAssert(kFragment_ShaderType == type); - SkString lookup; - this->appendTextureLookup(&lookup, sampler, coordName, varyingType); - GrGLSLModulate4f(&fFSCode, modulation, lookup.c_str()); -} - -GrBackendEffectFactory::EffectKey GrGLShaderBuilder::KeyForTextureAccess( - const GrTextureAccess& access, - const GrGLCaps& caps) { - uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); - if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { - return 1; - } else { - return 0; - } -} - -GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, - const GrGLCaps& caps) { - uint32_t key = kYesDstRead_DstReadKeyBit; - if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { - // The fact that the config is alpha-only must be considered when generating code. - key |= kUseAlphaConfig_DstReadKeyBit; - } - if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { - key |= kTopLeftOrigin_DstReadKeyBit; - } - GrAssert(static_cast(key) == key); - return static_cast(key); -} - -const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { - if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { - if (caps.textureRedSupport()) { - static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; - return gRedSmear; - } else { - static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, - GR_GL_ALPHA, GR_GL_ALPHA }; - return gAlphaSmear; - } - } else { - static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; - return gStraight; - } -} - -GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, - GrSLType type, - const char* name, - int count, - const char** outName) { - GrAssert(name && strlen(name)); - SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType); - GrAssert(0 == (~kVisibilityMask & visibility)); - GrAssert(0 != visibility); - - BuilderUniform& uni = fUniforms.push_back(); - UniformHandle h = index_to_handle(fUniforms.count() - 1); - GR_DEBUGCODE(UniformHandle h2 =) - 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. - GrAssert(h2 == h); - uni.fVariable.setType(type); - uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); - SkString* uniName = uni.fVariable.accessName(); - if (kNonStageIdx == fCurrentStageIdx) { - uniName->printf("u%s", name); - } else { - uniName->printf("u%s%d", name, fCurrentStageIdx); - } - uni.fVariable.setArrayCount(count); - uni.fVisibility = visibility; - - // If it is visible in both the VS and FS, the precision must match. - // We declare a default FS precision, but not a default VS. So set the var - // to use the default FS precision. - if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { - // the fragment and vertex precisions must match - uni.fVariable.setPrecision(kDefaultFragmentPrecision); - } - - if (NULL != outName) { - *outName = uni.fVariable.c_str(); - } - - return h; -} - -const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const { - return fUniforms[handle_to_index(u)].fVariable; -} - -bool GrGLShaderBuilder::addAttribute(GrSLType type, - const char* name) { - for (int i = 0; i < fVSAttrs.count(); ++i) { - const GrGLShaderVar& attr = fVSAttrs[i]; - // if attribute already added, don't add it again - if (attr.getName().equals(name)) { - GrAssert(attr.getType() == type); - return false; - } - } - fVSAttrs.push_back().set(type, - GrGLShaderVar::kAttribute_TypeModifier, - name); - return true; -} - -void GrGLShaderBuilder::addVarying(GrSLType type, - const char* name, - const char** vsOutName, - const char** fsInName) { - fVSOutputs.push_back(); - fVSOutputs.back().setType(type); - fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); - if (kNonStageIdx == fCurrentStageIdx) { - fVSOutputs.back().accessName()->printf("v%s", name); - } else { - fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStageIdx); - } - if (vsOutName) { - *vsOutName = fVSOutputs.back().getName().c_str(); - } - // input to FS comes either from VS or GS - const SkString* fsName; - if (fUsesGS) { - // if we have a GS take each varying in as an array - // and output as non-array. - fGSInputs.push_back(); - fGSInputs.back().setType(type); - fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); - fGSInputs.back().setUnsizedArray(); - *fGSInputs.back().accessName() = fVSOutputs.back().getName(); - fGSOutputs.push_back(); - fGSOutputs.back().setType(type); - fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); - if (kNonStageIdx == fCurrentStageIdx) { - fGSOutputs.back().accessName()->printf("g%s", name); - } else { - fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStageIdx); - } - fsName = fGSOutputs.back().accessName(); - } else { - fsName = fVSOutputs.back().accessName(); - } - fFSInputs.push_back(); - fFSInputs.back().setType(type); - fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); - fFSInputs.back().setName(*fsName); - if (fsInName) { - *fsInName = fsName->c_str(); - } -} - -const char* GrGLShaderBuilder::fragmentPosition() { -#if 1 - if (fCtxInfo.caps()->fragCoordConventionsSupport()) { - if (!fSetupFragPosition) { - SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); - fFSInputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kIn_TypeModifier, - "gl_FragCoord", - GrGLShaderVar::kDefault_Precision, - GrGLShaderVar::kUpperLeft_Origin); - fSetupFragPosition = true; - } - return "gl_FragCoord"; - } else { - static const char* kCoordName = "fragCoordYDown"; - if (!fSetupFragPosition) { - GrAssert(GrGLUniformManager::kInvalidUniformHandle == fRTHeightUniform); - const char* rtHeightName; - - // temporarily change the stage index because we're inserting a uniform whose name - // shouldn't be mangled to be stage-specific. - int oldStageIdx = fCurrentStageIdx; - fCurrentStageIdx = kNonStageIdx; - fRTHeightUniform = this->addUniform(kFragment_ShaderType, - kFloat_GrSLType, - "RTHeight", - &rtHeightName); - fCurrentStageIdx = oldStageIdx; - - this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", - kCoordName, rtHeightName); - fSetupFragPosition = true; - } - GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform); - return kCoordName; - } -#else - // This is the path we'll need to use once we have support for TopLeft - // render targets. - if (!fSetupFragPosition) { - fFSInputs.push_back().set(kVec4f_GrSLType, - GrGLShaderVar::kIn_TypeModifier, - "gl_FragCoord", - GrGLShaderVar::kDefault_Precision); - fSetupFragPosition = true; - } - return "gl_FragCoord"; -#endif -} - - -void GrGLShaderBuilder::emitFunction(ShaderType shader, - GrSLType returnType, - const char* name, - int argCnt, - const GrGLShaderVar* args, - const char* body, - SkString* outName) { - GrAssert(kFragment_ShaderType == shader); - fFSFunctions.append(GrGLShaderVar::TypeString(returnType)); - if (kNonStageIdx != fCurrentStageIdx) { - outName->printf(" %s_%d", name, fCurrentStageIdx); - } else { - *outName = name; - } - fFSFunctions.append(*outName); - fFSFunctions.append("("); - for (int i = 0; i < argCnt; ++i) { - args[i].appendDecl(fCtxInfo, &fFSFunctions); - if (i < argCnt - 1) { - fFSFunctions.append(", "); - } - } - fFSFunctions.append(") {\n"); - fFSFunctions.append(body); - fFSFunctions.append("}\n\n"); -} - -namespace { - -inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, - GrGLBinding binding, - SkString* str) { - // Desktop GLSL has added precision qualifiers but they don't do anything. - if (kES2_GrGLBinding == binding) { - switch (p) { - case GrGLShaderVar::kHigh_Precision: - str->append("precision highp float;\n"); - break; - case GrGLShaderVar::kMedium_Precision: - str->append("precision mediump float;\n"); - break; - case GrGLShaderVar::kLow_Precision: - str->append("precision lowp float;\n"); - break; - case GrGLShaderVar::kDefault_Precision: - GrCrash("Default precision now allowed."); - default: - GrCrash("Unknown precision value."); - } - } -} -} - -void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { - for (int i = 0; i < vars.count(); ++i) { - vars[i].appendDecl(fCtxInfo, out); - out->append(";\n"); - } -} - -void GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const { - for (int i = 0; i < fUniforms.count(); ++i) { - if (fUniforms[i].fVisibility & stype) { - fUniforms[i].fVariable.appendDecl(fCtxInfo, out); - out->append(";\n"); - } - } -} - -void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { - const char* version = GrGetGLSLVersionDecl(fCtxInfo.binding(), fCtxInfo.glslGeneration()); - - switch (type) { - case kVertex_ShaderType: - *shaderStr = version; - this->appendUniformDecls(kVertex_ShaderType, shaderStr); - this->appendDecls(fVSAttrs, shaderStr); - this->appendDecls(fVSOutputs, shaderStr); - shaderStr->append("void main() {\n"); - shaderStr->append(fVSCode); - shaderStr->append("}\n"); - break; - case kGeometry_ShaderType: - if (fUsesGS) { - *shaderStr = version; - shaderStr->append(fGSHeader); - this->appendDecls(fGSInputs, shaderStr); - this->appendDecls(fGSOutputs, shaderStr); - shaderStr->append("void main() {\n"); - shaderStr->append(fGSCode); - shaderStr->append("}\n"); - } else { - shaderStr->reset(); - } - break; - case kFragment_ShaderType: - *shaderStr = version; - shaderStr->append(fFSExtensions); - append_default_precision_qualifier(kDefaultFragmentPrecision, - fCtxInfo.binding(), - shaderStr); - this->appendUniformDecls(kFragment_ShaderType, shaderStr); - this->appendDecls(fFSInputs, shaderStr); - // We shouldn't have declared outputs on 1.10 - GrAssert(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty()); - this->appendDecls(fFSOutputs, shaderStr); - shaderStr->append(fFSFunctions); - shaderStr->append("void main() {\n"); - shaderStr->append(fFSCode); - shaderStr->append("}\n"); - break; - } - } - -void GrGLShaderBuilder::finished(GrGLuint programID) { - fUniformManager.getUniformLocations(programID, fUniforms); -} - -GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect( - const GrEffectStage& stage, - GrGLEffect::EffectKey key, - const char* fsInColor, - const char* fsOutColor, - SkTArray* samplerHandles) { - GrAssert(NULL != stage.getEffect()); - - const GrEffectRef& effect = *stage.getEffect(); - int numTextures = effect->numTextures(); - SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; - textureSamplers.push_back_n(numTextures); - for (int i = 0; i < numTextures; ++i) { - textureSamplers[i].init(this, &effect->textureAccess(i), i); - samplerHandles->push_back(textureSamplers[i].fSamplerUniform); - } - GrDrawEffect drawEffect(stage, this->hasExplicitLocalCoords()); - - int numAttributes = stage.getVertexAttribIndexCount(); - const int* attributeIndices = stage.getVertexAttribIndices(); - SkSTArray attributeNames; - for (int i = 0; i < numAttributes; ++i) { - SkString attributeName("aAttr"); - attributeName.appendS32(attributeIndices[i]); - - if (this->addAttribute(effect->vertexAttribType(i), attributeName.c_str())) { - fEffectAttributes.push_back().set(attributeIndices[i], attributeName); - } - } - - GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); - - // Enclose custom code in a block to avoid namespace conflicts - this->fVSCode.appendf("\t{ // %s\n", glEffect->name()); - this->fFSCode.appendf("\t{ // %s \n", glEffect->name()); - - glEffect->emitCode(this, - drawEffect, - key, - fsOutColor, - fsInColor, - textureSamplers); - this->fVSCode.appendf("\t}\n"); - this->fFSCode.appendf("\t}\n"); - - return glEffect; -} - -const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const { - const AttributePair* attribEnd = this->getEffectAttributes().end(); - for (const AttributePair* attrib = this->getEffectAttributes().begin(); - attrib != attribEnd; - ++attrib) { - if (attrib->fIndex == attributeIndex) { - return &attrib->fName; - } - } - - return NULL; -} diff --git a/gfx/skia/src/gpu/gl/GrGLShaderBuilder.h b/gfx/skia/src/gpu/gl/GrGLShaderBuilder.h deleted file mode 100644 index ab093fb050dc..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLShaderBuilder.h +++ /dev/null @@ -1,392 +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 GrGLShaderBuilder_DEFINED -#define GrGLShaderBuilder_DEFINED - -#include "GrAllocator.h" -#include "GrBackendEffectFactory.h" -#include "GrColor.h" -#include "GrEffect.h" -#include "gl/GrGLSL.h" -#include "gl/GrGLUniformManager.h" - -#include - -class GrGLContextInfo; -class GrEffectStage; -class GrGLProgramDesc; - -/** - Contains all the incremental state of a shader as it is being built,as well as helpers to - manipulate that state. -*/ -class GrGLShaderBuilder { -public: - /** - * Passed to GrGLEffects to add texture reads to their shader code. - */ - class TextureSampler { - public: - TextureSampler() - : fConfigComponentMask(0) - , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) { - // we will memcpy the first 4 bytes from passed in swizzle. This ensures the string is - // terminated. - fSwizzle[4] = '\0'; - } - - TextureSampler(const TextureSampler& other) { *this = other; } - - TextureSampler& operator= (const TextureSampler& other) { - GrAssert(0 == fConfigComponentMask); - GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform); - - fConfigComponentMask = other.fConfigComponentMask; - fSamplerUniform = other.fSamplerUniform; - return *this; - } - - // bitfield of GrColorComponentFlags present in the texture's config. - uint32_t configComponentMask() const { return fConfigComponentMask; } - - const char* swizzle() const { return fSwizzle; } - - bool isInitialized() const { return 0 != fConfigComponentMask; } - - private: - // The idx param is used to ensure multiple samplers within a single effect have unique - // uniform names. swizzle is a four char max string made up of chars 'r', 'g', 'b', and 'a'. - void init(GrGLShaderBuilder* builder, - uint32_t configComponentMask, - const char* swizzle, - int idx) { - GrAssert(!this->isInitialized()); - GrAssert(0 != configComponentMask); - GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform); - - GrAssert(NULL != builder); - SkString name; - name.printf("Sampler%d_", idx); - fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kSampler2D_GrSLType, - name.c_str()); - GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform); - - fConfigComponentMask = configComponentMask; - memcpy(fSwizzle, swizzle, 4); - } - - void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) { - GrAssert(NULL != access); - this->init(builder, - GrPixelConfigComponentMask(access->getTexture()->config()), - access->getSwizzle(), - idx); - } - - uint32_t fConfigComponentMask; - char fSwizzle[5]; - GrGLUniformManager::UniformHandle fSamplerUniform; - - friend class GrGLShaderBuilder; // to call init(). - }; - - typedef SkTArray TextureSamplerArray; - - enum ShaderType { - kVertex_ShaderType = 0x1, - kGeometry_ShaderType = 0x2, - kFragment_ShaderType = 0x4, - }; - - GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&); - - /** - * Use of these features may require a GLSL extension to be enabled. Shaders may not compile - * if code is added that uses one of these features without calling enableFeature() - */ - enum GLSLFeature { - kStandardDerivatives_GLSLFeature = 0, - - kLastGLSLFeature = kStandardDerivatives_GLSLFeature - }; - - /** - * If the feature is supported then true is returned and any necessary #extension declarations - * are added to the shaders. If the feature is not supported then false will be returned. - */ - bool enableFeature(GLSLFeature); - - /** - * Called by GrGLEffects to add code to one of the shaders. - */ - void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - this->codeAppendf(kVertex_ShaderType, format, args); - va_end(args); - } - - void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - this->codeAppendf(kGeometry_ShaderType, format, args); - va_end(args); - } - - void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) { - va_list args; - va_start(args, format); - this->codeAppendf(kFragment_ShaderType, format, args); - va_end(args); - } - - void vsCodeAppend(const char* str) { this->codeAppend(kVertex_ShaderType, str); } - void gsCodeAppend(const char* str) { this->codeAppend(kGeometry_ShaderType, str); } - void fsCodeAppend(const char* str) { this->codeAppend(kFragment_ShaderType, str); } - - /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or - Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle - order of the result depends on the GrTextureAccess associated with the TextureSampler. */ - void appendTextureLookup(SkString* out, - const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType) const; - - /** Version of above that appends the result to the shader code rather than an SkString. - Currently the shader type must be kFragment */ - void appendTextureLookup(ShaderType, - const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType); - - - /** Does the work of appendTextureLookup and modulates the result by modulation. The result is - always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or - float. If modulation is "" or NULL it this function acts as though appendTextureLookup were - called. */ - void appendTextureLookupAndModulate(ShaderType, - const char* modulation, - const TextureSampler&, - const char* coordName, - GrSLType coordType = kVec2f_GrSLType); - - /** Emits a helper function outside of main(). Currently ShaderType must be - kFragment_ShaderType. */ - void emitFunction(ShaderType shader, - GrSLType returnType, - const char* name, - int argCnt, - const GrGLShaderVar* args, - const char* body, - SkString* outName); - - /** Generates a EffectKey for the shader code based on the texture access parameters and the - capabilities of the GL context. This is useful for keying the shader programs that may - have multiple representations, based on the type/format of textures used. */ - static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&, - const GrGLCaps&); - - typedef uint8_t DstReadKey; - - /** Returns a key for adding code to read the copy-of-dst color in service of effects that - require reading the dst. It must not return 0 because 0 indicates that there is no dst - copy read at all. */ - static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&); - - /** If texture swizzling is available using tex parameters then it is preferred over mangling - the generated shader code. This potentially allows greater reuse of cached shaders. */ - static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps); - - /** Add a uniform variable to the current program, that has visibility in one or more shaders. - visibility is a bitfield of ShaderType values indicating from which shaders the 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. - */ - GrGLUniformManager::UniformHandle addUniform(uint32_t visibility, - GrSLType type, - const char* name, - const char** outName = NULL) { - return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName); - } - GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility, - GrSLType type, - const char* name, - int arrayCount, - const char** outName = NULL); - - const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const; - - /** - * Shortcut for getUniformVariable(u).c_str() - */ - const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const { - return this->getUniformVariable(u).c_str(); - } - - /** Add a vertex attribute to the current program that is passed in from the vertex data. - Returns false if the attribute was already there, true otherwise. */ - bool addAttribute(GrSLType type, const char* name); - - /** Add a varying variable to the current program to pass values between vertex and fragment - shaders. If the last two parameters are non-NULL, they are filled in with the name - generated. */ - void addVarying(GrSLType type, - const char* name, - const char** vsOutName = NULL, - const char** fsInName = NULL); - - /** Returns a variable name that represents the position of the fragment in the FS. The position - is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */ - const char* fragmentPosition(); - - /** Returns a vertex attribute that represents the vertex position in the VS. This is the - pre-matrix position and is commonly used by effects to compute texture coords via a matrix. - */ - const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } - - /** Returns a vertex attribute that represents the local coords in the VS. This may be the same - as positionAttribute() or it may not be. It depends upon whether the rendering code - specified explicit local coords or not in the GrDrawState. */ - const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; } - - /** Returns the color of the destination pixel. This may be NULL if no effect advertised - that it will read the destination. */ - const char* dstColor() const; - - /** - * Are explicit local coordinates provided as input to the vertex shader. - */ - bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); } - - /** - * Interfaces used by GrGLProgram. - * TODO: Hide these from the GrEffects using friend or splitting this into two related classes. - * Also, GrGLProgram's shader string construction should be moved to this class. - */ - - /** Called after building is complete to get the final shader string. */ - void getShader(ShaderType, SkString*) const; - - void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; } - void setNonStage() { fCurrentStageIdx = kNonStageIdx; } - // TODO: move remainder of shader code generation to this class and call this privately - // Handles of sampler uniforms generated for the effect are appended to samplerHandles. - GrGLEffect* createAndEmitGLEffect( - const GrEffectStage& stage, - GrBackendEffectFactory::EffectKey key, - const char* fsInColor, // NULL means no incoming color - const char* fsOutColor, - SkTArray* samplerHandles); - - GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; } - GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const { - return fDstCopyTopLeftUniform; - } - GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const { - return fDstCopyScaleUniform; - } - GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const { - return fDstCopySampler.fSamplerUniform; - } - - struct AttributePair { - void set(int index, const SkString& name) { - fIndex = index; fName = name; - } - int fIndex; - SkString fName; - }; - const SkTArray& getEffectAttributes() const { - return fEffectAttributes; - } - const SkString* getEffectAttributeName(int attributeIndex) const; - - // TODO: Make this do all the compiling, linking, etc. - void finished(GrGLuint programID); - - const GrGLContextInfo& ctxInfo() const { return fCtxInfo; } - -private: - void codeAppendf(ShaderType type, const char format[], va_list args); - void codeAppend(ShaderType type, const char* str); - - typedef GrTAllocator VarArray; - - void appendDecls(const VarArray&, SkString*) const; - void appendUniformDecls(ShaderType, SkString*) const; - - typedef GrGLUniformManager::BuilderUniform BuilderUniform; - GrGLUniformManager::BuilderUniformArray fUniforms; - - // TODO: Everything below here private. -public: - - VarArray fVSAttrs; - VarArray fVSOutputs; - VarArray fGSInputs; - VarArray fGSOutputs; - VarArray fFSInputs; - SkString fGSHeader; // layout qualifiers specific to GS - VarArray fFSOutputs; - -private: - enum { - kNonStageIdx = -1, - }; - - /** - * Features that should only be enabled by GrGLShaderBuilder itself. - */ - enum GLSLPrivateFeature { - kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1 - }; - bool enablePrivateFeature(GLSLPrivateFeature); - - // If we ever have VS/GS features we can expand this to take a bitmask of ShaderType and track - // the enables separately for each shader. - void addFSFeature(uint32_t featureBit, const char* extensionName); - - // 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. - }; - - const GrGLContextInfo& fCtxInfo; - GrGLUniformManager& fUniformManager; - int fCurrentStageIdx; - uint32_t fFSFeaturesAddedMask; - SkString fFSFunctions; - SkString fFSExtensions; - - bool fUsesGS; - - SkString fFSCode; - SkString fVSCode; - SkString fGSCode; - - bool fSetupFragPosition; - TextureSampler fDstCopySampler; - - GrGLUniformManager::UniformHandle fRTHeightUniform; - GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform; - GrGLUniformManager::UniformHandle fDstCopyScaleUniform; - - SkSTArray<10, AttributePair, true> fEffectAttributes; - - GrGLShaderVar* fPositionVar; - GrGLShaderVar* fLocalCoordsVar; - -}; - -#endif diff --git a/gfx/skia/src/gpu/gl/GrGLUniformManager.cpp b/gfx/skia/src/gpu/gl/GrGLUniformManager.cpp deleted file mode 100644 index da6726bb244d..000000000000 --- a/gfx/skia/src/gpu/gl/GrGLUniformManager.cpp +++ /dev/null @@ -1,269 +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 "gl/GrGLShaderBuilder.h" -#include "gl/GrGLProgram.h" -#include "gl/GrGLUniformHandle.h" -#include "SkMatrix.h" - -#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, OFFSET, COUNT) \ - GrAssert(offset + arrayCount <= uni.fArrayCount || \ - (0 == offset && 1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount)) - -GrGLUniformManager::UniformHandle GrGLUniformManager::appendUniform(GrSLType type, int arrayCount) { - int idx = fUniforms.count(); - Uniform& uni = fUniforms.push_back(); - GrAssert(GrGLShaderVar::kNonArray == arrayCount || arrayCount > 0); - uni.fArrayCount = arrayCount; - uni.fType = type; - uni.fVSLocation = kUnusedUniform; - uni.fFSLocation = kUnusedUniform; - return index_to_handle(idx); -} - -void GrGLUniformManager::setSampler(UniformHandle u, GrGLint texUnit) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kSampler2D_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - // FIXME: We still insert a single sampler uniform for every stage. If the shader does not - // reference the sampler then the compiler may have optimized it out. Uncomment this assert - // once stages insert their own samplers. - // GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1i(uni.fFSLocation, texUnit)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1i(uni.fVSLocation, texUnit)); - } -} - -void GrGLUniformManager::set1f(UniformHandle u, GrGLfloat v0) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kFloat_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1f(uni.fFSLocation, v0)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1f(uni.fVSLocation, v0)); - } -} - -void GrGLUniformManager::set1fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat v[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kFloat_GrSLType); - GrAssert(arrayCount > 0); - ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, offset, arrayCount); - // This assert fires in some instances of the two-pt gradient for its VSParams. - // Once the uniform manager is responsible for inserting the duplicate uniform - // arrays in VS and FS driver bug workaround, this can be enabled. - //GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1fv(uni.fFSLocation + offset, arrayCount, v)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform1fv(uni.fVSLocation + offset, arrayCount, v)); - } -} - -void GrGLUniformManager::set2f(UniformHandle u, GrGLfloat v0, GrGLfloat v1) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec2f_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform2f(uni.fFSLocation, v0, v1)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform2f(uni.fVSLocation, v0, v1)); - } -} - -void GrGLUniformManager::set2fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat v[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec2f_GrSLType); - GrAssert(arrayCount > 0); - ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, offset, arrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform2fv(uni.fFSLocation + offset, arrayCount, v)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform2fv(uni.fVSLocation + offset, arrayCount, v)); - } -} - -void GrGLUniformManager::set3f(UniformHandle u, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec3f_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform3f(uni.fFSLocation, v0, v1, v2)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform3f(uni.fVSLocation, v0, v1, v2)); - } -} - -void GrGLUniformManager::set3fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat v[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec3f_GrSLType); - GrAssert(arrayCount > 0); - ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, offset, arrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform3fv(uni.fFSLocation + offset, arrayCount, v)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform3fv(uni.fVSLocation + offset, arrayCount, v)); - } -} - -void GrGLUniformManager::set4f(UniformHandle u, - GrGLfloat v0, - GrGLfloat v1, - GrGLfloat v2, - GrGLfloat v3) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec4f_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform4f(uni.fFSLocation, v0, v1, v2, v3)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform4f(uni.fVSLocation, v0, v1, v2, v3)); - } -} - -void GrGLUniformManager::set4fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat v[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kVec4f_GrSLType); - GrAssert(arrayCount > 0); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform4fv(uni.fFSLocation + offset, arrayCount, v)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), Uniform4fv(uni.fVSLocation + offset, arrayCount, v)); - } -} - -void GrGLUniformManager::setMatrix3f(UniformHandle u, const GrGLfloat matrix[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kMat33f_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - // TODO: Re-enable this assert once texture matrices aren't forced on all effects - // GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), UniformMatrix3fv(uni.fFSLocation, 1, false, matrix)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), UniformMatrix3fv(uni.fVSLocation, 1, false, matrix)); - } -} - -void GrGLUniformManager::setMatrix4f(UniformHandle u, const GrGLfloat matrix[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kMat44f_GrSLType); - GrAssert(GrGLShaderVar::kNonArray == uni.fArrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), UniformMatrix4fv(uni.fFSLocation, 1, false, matrix)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), UniformMatrix4fv(uni.fVSLocation, 1, false, matrix)); - } -} - -void GrGLUniformManager::setMatrix3fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat matrices[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kMat33f_GrSLType); - GrAssert(arrayCount > 0); - ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, offset, arrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), - UniformMatrix3fv(uni.fFSLocation + offset, arrayCount, false, matrices)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), - UniformMatrix3fv(uni.fVSLocation + offset, arrayCount, false, matrices)); - } -} - -void GrGLUniformManager::setMatrix4fv(UniformHandle u, - int offset, - int arrayCount, - const GrGLfloat matrices[]) const { - const Uniform& uni = fUniforms[handle_to_index(u)]; - GrAssert(uni.fType == kMat44f_GrSLType); - GrAssert(arrayCount > 0); - ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, offset, arrayCount); - GrAssert(kUnusedUniform != uni.fFSLocation || kUnusedUniform != uni.fVSLocation); - if (kUnusedUniform != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), - UniformMatrix4fv(uni.fFSLocation + offset, arrayCount, false, matrices)); - } - if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { - GR_GL_CALL(fContext.interface(), - UniformMatrix4fv(uni.fVSLocation + offset, arrayCount, false, matrices)); - } -} - -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), - matrix.get(SkMatrix::kMPersp0), - matrix.get(SkMatrix::kMSkewX), - matrix.get(SkMatrix::kMScaleY), - matrix.get(SkMatrix::kMPersp1), - matrix.get(SkMatrix::kMTransX), - matrix.get(SkMatrix::kMTransY), - matrix.get(SkMatrix::kMPersp2), - }; - this->setMatrix3f(u, mt); -} - - -void GrGLUniformManager::getUniformLocations(GrGLuint programID, const BuilderUniformArray& uniforms) { - GrAssert(uniforms.count() == fUniforms.count()); - int count = fUniforms.count(); - for (int i = 0; i < count; ++i) { - GrAssert(uniforms[i].fVariable.getType() == fUniforms[i].fType); - GrAssert(uniforms[i].fVariable.getArrayCount() == fUniforms[i].fArrayCount); - GrGLint location; - // TODO: Move the Xoom uniform array in both FS and VS bug workaround here. - GR_GL_CALL_RET(fContext.interface(), location, - GetUniformLocation(programID, uniforms[i].fVariable.c_str())); - if (GrGLShaderBuilder::kVertex_ShaderType & uniforms[i].fVisibility) { - fUniforms[i].fVSLocation = location; - } - if (GrGLShaderBuilder::kFragment_ShaderType & uniforms[i].fVisibility) { - fUniforms[i].fFSLocation = location; - } - } -} diff --git a/gfx/skia/src/gpu/gl/GrGpuGL_program.cpp b/gfx/skia/src/gpu/gl/GrGpuGL_program.cpp deleted file mode 100644 index 833d81158855..000000000000 --- a/gfx/skia/src/gpu/gl/GrGpuGL_program.cpp +++ /dev/null @@ -1,315 +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 "GrGpuGL.h" - -#include "GrEffect.h" -#include "GrGLEffect.h" - -typedef GrGLUniformManager::UniformHandle UniformHandle; -static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; - -#define SKIP_CACHE_CHECK true -#define GR_UINT32_MAX static_cast(-1) - -GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl) - : fCount(0) - , fCurrLRUStamp(0) - , fGL(gl) -#ifdef PROGRAM_CACHE_STATS - , fTotalRequests(0) - , fCacheMisses(0) -#endif -{ -} - -GrGpuGL::ProgramCache::~ProgramCache() { - // dump stats -#ifdef PROGRAM_CACHE_STATS - SkDebugf("--- Program Cache ---\n"); - SkDebugf("Total requests: %d\n", fTotalRequests); - SkDebugf("Cache misses: %d\n", fCacheMisses); - SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) - ? (float)fCacheMisses/(float)fTotalRequests : 0.0f); - SkDebugf("---------------------\n"); -#endif -} - -void GrGpuGL::ProgramCache::abandon() { - for (int i = 0; i < fCount; ++i) { - GrAssert(NULL != fEntries[i].fProgram.get()); - fEntries[i].fProgram->abandon(); - fEntries[i].fProgram.reset(NULL); - } - fCount = 0; -} - -GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, - const GrEffectStage* stages[]) { - Entry newEntry; - newEntry.fKey.setKeyData(desc.asKey()); -#ifdef PROGRAM_CACHE_STATS - ++fTotalRequests; -#endif - - Entry* entry = fHashCache.find(newEntry.fKey); - if (NULL == entry) { -#ifdef PROGRAM_CACHE_STATS - ++fCacheMisses; -#endif - newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages)); - if (NULL == newEntry.fProgram.get()) { - return NULL; - } - if (fCount < kMaxEntries) { - entry = fEntries + fCount; - ++fCount; - } else { - GrAssert(kMaxEntries == fCount); - entry = fEntries; - for (int i = 1; i < kMaxEntries; ++i) { - if (fEntries[i].fLRUStamp < entry->fLRUStamp) { - entry = fEntries + i; - } - } - fHashCache.remove(entry->fKey, entry); - } - *entry = newEntry; - fHashCache.insert(entry->fKey, entry); - } - - entry->fLRUStamp = fCurrLRUStamp; - if (GR_UINT32_MAX == fCurrLRUStamp) { - // wrap around! just trash our LRU, one time hit. - for (int i = 0; i < fCount; ++i) { - fEntries[i].fLRUStamp = 0; - } - } - ++fCurrLRUStamp; - return entry->fProgram; -} - -//////////////////////////////////////////////////////////////////////////////// - -void GrGpuGL::abandonResources(){ - INHERITED::abandonResources(); - fProgramCache->abandon(); - fHWProgramID = 0; -} - -//////////////////////////////////////////////////////////////////////////////// - -#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) - -void GrGpuGL::flushPathStencilMatrix() { - const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix(); - const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); - SkISize size; - size.set(rt->width(), rt->height()); - const SkMatrix& vm = this->getDrawState().getViewMatrix(); - - if (fHWPathStencilMatrixState.fRenderTargetOrigin != rt->origin() || - fHWPathStencilMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) || - fHWPathStencilMatrixState.fRenderTargetSize!= size) { - // rescale the coords from skia's "device" coords to GL's normalized coords, - // and perform a y-flip if required. - SkMatrix m; - if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { - m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height()); - m.postTranslate(-SK_Scalar1, SK_Scalar1); - } else { - m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height()); - m.postTranslate(-SK_Scalar1, -SK_Scalar1); - } - m.preConcat(vm); - - // GL wants a column-major 4x4. - GrGLfloat mv[] = { - // col 0 - SkScalarToFloat(m[SkMatrix::kMScaleX]), - SkScalarToFloat(m[SkMatrix::kMSkewY]), - 0, - SkScalarToFloat(m[SkMatrix::kMPersp0]), - - // col 1 - SkScalarToFloat(m[SkMatrix::kMSkewX]), - SkScalarToFloat(m[SkMatrix::kMScaleY]), - 0, - SkScalarToFloat(m[SkMatrix::kMPersp1]), - - // col 2 - 0, 0, 0, 0, - - // col3 - SkScalarToFloat(m[SkMatrix::kMTransX]), - SkScalarToFloat(m[SkMatrix::kMTransY]), - 0.0f, - SkScalarToFloat(m[SkMatrix::kMPersp2]) - }; - GL_CALL(MatrixMode(GR_GL_PROJECTION)); - GL_CALL(LoadMatrixf(mv)); - fHWPathStencilMatrixState.fViewMatrix = vm; - fHWPathStencilMatrixState.fRenderTargetSize = size; - fHWPathStencilMatrixState.fRenderTargetOrigin = rt->origin(); - } -} - -bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) { - const GrDrawState& drawState = this->getDrawState(); - - // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true. - GrAssert(NULL != drawState.getRenderTarget()); - - if (kStencilPath_DrawType == type) { - this->flushPathStencilMatrix(); - } else { - this->flushMiscFixedFunctionState(); - - GrBlendCoeff srcCoeff; - GrBlendCoeff dstCoeff; - GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &srcCoeff, &dstCoeff); - if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { - return false; - } - - const GrEffectStage* stages[GrDrawState::kNumStages]; - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL; - } - GrGLProgramDesc desc; - GrGLProgramDesc::Build(this->getDrawState(), - kDrawPoints_DrawType == type, - blendOpts, - srcCoeff, - dstCoeff, - this, - dstCopy, - &desc); - - fCurrentProgram.reset(fProgramCache->getProgram(desc, stages)); - if (NULL == fCurrentProgram.get()) { - GrAssert(!"Failed to create program!"); - return false; - } - fCurrentProgram.get()->ref(); - - GrGLuint programID = fCurrentProgram->programID(); - if (fHWProgramID != programID) { - GL_CALL(UseProgram(programID)); - fHWProgramID = programID; - } - - fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); - this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); - - GrColor color; - GrColor coverage; - if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) { - color = 0; - coverage = 0; - } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) { - color = 0xffffffff; - coverage = drawState.getCoverage(); - } else { - color = drawState.getColor(); - coverage = drawState.getCoverage(); - } - fCurrentProgram->setData(this, color, coverage, dstCopy, &fSharedGLProgramState); - } - this->flushStencil(type); - this->flushScissor(); - this->flushAAState(type); - - GrIRect* devRect = NULL; - GrIRect devClipBounds; - if (drawState.isClipState()) { - this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); - devRect = &devClipBounds; - } - // This must come after textures are flushed because a texture may need - // to be msaa-resolved (which will modify bound FBO state). - this->flushRenderTarget(devRect); - - return true; -} - -void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { - - GrGLsizei stride = this->getDrawState().getVertexSize(); - - size_t vertexOffsetInBytes = stride * info.startVertex(); - - const GeometryPoolState& geoPoolState = this->getGeomPoolState(); - - GrGLVertexBuffer* vbuf; - switch (this->getGeomSrc().fVertexSrc) { - case kBuffer_GeometrySrcType: - vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer; - break; - case kArray_GeometrySrcType: - case kReserved_GeometrySrcType: - this->finalizeReservedVertices(); - vertexOffsetInBytes += geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize; - vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer; - break; - default: - vbuf = NULL; // suppress warning - GrCrash("Unknown geometry src type!"); - } - - GrAssert(NULL != vbuf); - GrAssert(!vbuf->isLocked()); - vertexOffsetInBytes += vbuf->baseOffset(); - - GrGLIndexBuffer* ibuf = NULL; - if (info.isIndexed()) { - GrAssert(NULL != indexOffsetInBytes); - - switch (this->getGeomSrc().fIndexSrc) { - case kBuffer_GeometrySrcType: - *indexOffsetInBytes = 0; - ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; - break; - case kArray_GeometrySrcType: - case kReserved_GeometrySrcType: - this->finalizeReservedIndices(); - *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); - ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; - break; - default: - ibuf = NULL; // suppress warning - GrCrash("Unknown geometry src type!"); - } - - GrAssert(NULL != ibuf); - GrAssert(!ibuf->isLocked()); - *indexOffsetInBytes += ibuf->baseOffset(); - } - GrGLAttribArrayState* attribState = - fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); - - uint32_t usedAttribArraysMask = 0; - const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); - int vertexAttribCount = this->getDrawState().getVertexAttribCount(); - for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount; - ++vertexAttribIndex, ++vertexAttrib) { - - usedAttribArraysMask |= (1 << vertexAttribIndex); - GrVertexAttribType attribType = vertexAttrib->fType; - attribState->set(this, - vertexAttribIndex, - vbuf, - GrGLAttribTypeToLayout(attribType).fCount, - GrGLAttribTypeToLayout(attribType).fType, - GrGLAttribTypeToLayout(attribType).fNormalized, - stride, - reinterpret_cast( - vertexOffsetInBytes + vertexAttrib->fOffset)); - } - - attribState->disableUnusedAttribArrays(this, usedAttribArraysMask); -} diff --git a/gfx/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/gfx/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp deleted file mode 100644 index 6f81cab41cd5..000000000000 --- a/gfx/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Modified from chromium/src/webkit/glue/gl_bindings_skia_cmd_buffer.cc - -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gl/GrGLInterface.h" - -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES -#endif - -#include -#include - -#include - -const GrGLInterface* GrGLCreateNativeInterface() { - static SkAutoTUnref glInterface; - if (!glInterface.get()) { - GrGLInterface* interface = new GrGLInterface; - glInterface.reset(interface); - interface->fBindingsExported = kES2_GrGLBinding; - 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->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->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; - interface->fGetUniformLocation = glGetUniformLocation; - interface->fLineWidth = glLineWidth; - interface->fLinkProgram = glLinkProgram; - interface->fPixelStorei = glPixelStorei; - interface->fReadPixels = glReadPixels; - interface->fScissor = glScissor; -#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE - interface->fShaderSource = (GrGLShaderSourceProc) glShaderSource; -#else - interface->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; -#if GL_ARB_texture_storage - interface->fTexStorage2D = glTexStorage2D; -#elif GL_EXT_texture_storage - interface->fTexStorage2D = glTexStorage2DEXT; -#else - interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT"); -#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 GL_IMG_multisampled_render_to_texture - interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG; - interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleIMG; -#endif - 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; -#else - interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES"); - interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES"); -#endif - } - glInterface.get()->ref(); - return glInterface.get(); -} diff --git a/gfx/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp b/gfx/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp deleted file mode 100644 index f21eed866610..000000000000 --- a/gfx/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp +++ /dev/null @@ -1,104 +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 "gl/SkNativeGLContext.h" - -SkNativeGLContext::AutoContextRestore::AutoContextRestore() { - fOldEGLContext = eglGetCurrentContext(); - fOldDisplay = eglGetCurrentDisplay(); - fOldSurface = eglGetCurrentSurface(EGL_DRAW); - -} - -SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { - if (NULL != fOldDisplay) { - eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -SkNativeGLContext::SkNativeGLContext() - : fContext(EGL_NO_CONTEXT) - , fDisplay(EGL_NO_DISPLAY) - , fSurface(EGL_NO_SURFACE) { -} - -SkNativeGLContext::~SkNativeGLContext() { - this->destroyGLContext(); -} - -void SkNativeGLContext::destroyGLContext() { - if (fDisplay) { - eglMakeCurrent(fDisplay, 0, 0, 0); - - if (fContext) { - eglDestroyContext(fDisplay, fContext); - fContext = EGL_NO_CONTEXT; - } - - if (fSurface) { - eglDestroySurface(fDisplay, fSurface); - fSurface = EGL_NO_SURFACE; - } - - //TODO should we close the display? - fDisplay = EGL_NO_DISPLAY; - } -} - -const GrGLInterface* SkNativeGLContext::createGLContext() { - fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - EGLint majorVersion; - EGLint minorVersion; - eglInitialize(fDisplay, &majorVersion, &minorVersion); - - EGLint numConfigs; - static const EGLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_NONE - }; - - EGLConfig surfaceConfig; - eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs); - - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, contextAttribs); - - - static const EGLint surfaceAttribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs); - - eglMakeCurrent(fDisplay, fSurface, fSurface, fContext); - - const GrGLInterface* interface = GrGLCreateNativeInterface(); - if (!interface) { - SkDebugf("Failed to create gl interface"); - this->destroyGLContext(); - return NULL; - } - return interface; -} - -void SkNativeGLContext::makeCurrent() const { - if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { - SkDebugf("Could not set the context.\n"); - } -} diff --git a/gfx/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp b/gfx/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp deleted file mode 100644 index 059713d8e4ed..000000000000 --- a/gfx/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp +++ /dev/null @@ -1,159 +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 "gl/GrGLInterface.h" - -#ifndef GL_GLEXT_PROTOTYPES -#define GL_GLEXT_PROTOTYPES -#endif - -#include "GLES2/gl2.h" -#include "GLES2/gl2ext.h" -#include "EGL/egl.h" - -#define GR_GET_PROC(procType, baseName) \ - interface->f ## baseName = (procType) GetProcAddress(ghANGLELib, "gl" #baseName); - -const GrGLInterface* GrGLCreateANGLEInterface() { - - static SkAutoTUnref glInterface; - static HMODULE ghANGLELib = NULL; - - if (NULL == ghANGLELib) { - // We load the ANGLE library and never let it go - ghANGLELib = LoadLibrary("libGLESv2.dll"); - } - if (NULL == ghANGLELib) { - // We can't setup the interface correctly w/o the DLL - return NULL; - } - - if (!glInterface.get()) { - GrGLInterface* interface = new GrGLInterface; - glInterface.reset(interface); - interface->fBindingsExported = kES2_GrGLBinding; - - GR_GET_PROC(GrGLActiveTextureProc, ActiveTexture); - GR_GET_PROC(GrGLAttachShaderProc, AttachShader); - GR_GET_PROC(GrGLBindAttribLocationProc, BindAttribLocation); - GR_GET_PROC(GrGLBindBufferProc, BindBuffer); - GR_GET_PROC(GrGLBindTextureProc, BindTexture); - interface->fBindVertexArray = - (GrGLBindVertexArrayProc) eglGetProcAddress("glBindVertexArrayOES"); - GR_GET_PROC(GrGLBlendColorProc, BlendColor); - GR_GET_PROC(GrGLBlendFuncProc, BlendFunc); - GR_GET_PROC(GrGLBufferDataProc, BufferData); - GR_GET_PROC(GrGLBufferSubDataProc, BufferSubData); - GR_GET_PROC(GrGLClearProc, Clear); - GR_GET_PROC(GrGLClearColorProc, ClearColor); - GR_GET_PROC(GrGLClearStencilProc, ClearStencil); - GR_GET_PROC(GrGLColorMaskProc, ColorMask); - GR_GET_PROC(GrGLCompileShaderProc, CompileShader); - GR_GET_PROC(GrGLCompressedTexImage2DProc, CompressedTexImage2D); - GR_GET_PROC(GrGLCreateProgramProc, CreateProgram); - GR_GET_PROC(GrGLCreateShaderProc, CreateShader); - GR_GET_PROC(GrGLCullFaceProc, CullFace); - GR_GET_PROC(GrGLDeleteBuffersProc, DeleteBuffers); - GR_GET_PROC(GrGLDeleteProgramProc, DeleteProgram); - GR_GET_PROC(GrGLDeleteShaderProc, DeleteShader); - GR_GET_PROC(GrGLDeleteTexturesProc, DeleteTextures); - interface->fDeleteVertexArrays = - (GrGLDeleteVertexArraysProc) eglGetProcAddress("glDeleteVertexArraysOES"); - GR_GET_PROC(GrGLDepthMaskProc, DepthMask); - GR_GET_PROC(GrGLDisableProc, Disable); - GR_GET_PROC(GrGLDisableVertexAttribArrayProc, DisableVertexAttribArray); - GR_GET_PROC(GrGLDrawArraysProc, DrawArrays); - GR_GET_PROC(GrGLDrawElementsProc, DrawElements); - GR_GET_PROC(GrGLEnableProc, Enable); - GR_GET_PROC(GrGLEnableVertexAttribArrayProc, EnableVertexAttribArray); - GR_GET_PROC(GrGLFinishProc, Finish); - GR_GET_PROC(GrGLFlushProc, Flush); - GR_GET_PROC(GrGLFrontFaceProc, FrontFace); - GR_GET_PROC(GrGLGenBuffersProc, GenBuffers); - GR_GET_PROC(GrGLGenTexturesProc, GenTextures); - interface->fGenVertexArrays = - (GrGLGenVertexArraysProc) eglGetProcAddress("glGenVertexArraysOES"); - GR_GET_PROC(GrGLGetBufferParameterivProc, GetBufferParameteriv); - GR_GET_PROC(GrGLGetErrorProc, GetError); - GR_GET_PROC(GrGLGetIntegervProc, GetIntegerv); - GR_GET_PROC(GrGLGetProgramInfoLogProc, GetProgramInfoLog); - GR_GET_PROC(GrGLGetProgramivProc, GetProgramiv); - GR_GET_PROC(GrGLGetShaderInfoLogProc, GetShaderInfoLog); - GR_GET_PROC(GrGLGetShaderivProc, GetShaderiv); - GR_GET_PROC(GrGLGetStringProc, GetString); - GR_GET_PROC(GrGLGetUniformLocationProc, GetUniformLocation); - GR_GET_PROC(GrGLLineWidthProc, LineWidth); - GR_GET_PROC(GrGLLinkProgramProc, LinkProgram); - GR_GET_PROC(GrGLPixelStoreiProc, PixelStorei); - GR_GET_PROC(GrGLReadPixelsProc, ReadPixels); - GR_GET_PROC(GrGLScissorProc, Scissor); - GR_GET_PROC(GrGLShaderSourceProc, ShaderSource); - GR_GET_PROC(GrGLStencilFuncProc, StencilFunc); - GR_GET_PROC(GrGLStencilFuncSeparateProc, StencilFuncSeparate); - GR_GET_PROC(GrGLStencilMaskProc, StencilMask); - GR_GET_PROC(GrGLStencilMaskSeparateProc, StencilMaskSeparate); - GR_GET_PROC(GrGLStencilOpProc, StencilOp); - GR_GET_PROC(GrGLStencilOpSeparateProc, StencilOpSeparate); - GR_GET_PROC(GrGLTexImage2DProc, TexImage2D); - GR_GET_PROC(GrGLTexParameteriProc, TexParameteri); - GR_GET_PROC(GrGLTexParameterivProc, TexParameteriv); - GR_GET_PROC(GrGLTexSubImage2DProc, TexSubImage2D); -#if GL_ARB_texture_storage - GR_GET_PROC(GrGLTexStorage2DProc, TexStorage2D); -#elif GL_EXT_texture_storage - interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT"); -#endif - GR_GET_PROC(GrGLUniform1fProc, Uniform1f); - GR_GET_PROC(GrGLUniform1iProc, Uniform1i); - GR_GET_PROC(GrGLUniform1fvProc, Uniform1fv); - GR_GET_PROC(GrGLUniform1ivProc, Uniform1iv); - - GR_GET_PROC(GrGLUniform2fProc, Uniform2f); - GR_GET_PROC(GrGLUniform2iProc, Uniform2i); - GR_GET_PROC(GrGLUniform2fvProc, Uniform2fv); - GR_GET_PROC(GrGLUniform2ivProc, Uniform2iv); - - GR_GET_PROC(GrGLUniform3fProc, Uniform3f); - GR_GET_PROC(GrGLUniform3iProc, Uniform3i); - GR_GET_PROC(GrGLUniform3fvProc, Uniform3fv); - GR_GET_PROC(GrGLUniform3ivProc, Uniform3iv); - - GR_GET_PROC(GrGLUniform4fProc, Uniform4f); - GR_GET_PROC(GrGLUniform4iProc, Uniform4i); - GR_GET_PROC(GrGLUniform4fvProc, Uniform4fv); - GR_GET_PROC(GrGLUniform4ivProc, Uniform4iv); - - GR_GET_PROC(GrGLUniformMatrix2fvProc, UniformMatrix2fv); - GR_GET_PROC(GrGLUniformMatrix3fvProc, UniformMatrix3fv); - GR_GET_PROC(GrGLUniformMatrix4fvProc, UniformMatrix4fv); - GR_GET_PROC(GrGLUseProgramProc, UseProgram); - GR_GET_PROC(GrGLVertexAttrib4fvProc, VertexAttrib4fv); - GR_GET_PROC(GrGLVertexAttribPointerProc, VertexAttribPointer); - GR_GET_PROC(GrGLViewportProc, Viewport); - GR_GET_PROC(GrGLBindFramebufferProc, BindFramebuffer); - GR_GET_PROC(GrGLBindRenderbufferProc, BindRenderbuffer); - GR_GET_PROC(GrGLCheckFramebufferStatusProc, CheckFramebufferStatus); - GR_GET_PROC(GrGLDeleteFramebuffersProc, DeleteFramebuffers); - GR_GET_PROC(GrGLDeleteRenderbuffersProc, DeleteRenderbuffers); - GR_GET_PROC(GrGLFramebufferRenderbufferProc, FramebufferRenderbuffer); - GR_GET_PROC(GrGLFramebufferTexture2DProc, FramebufferTexture2D); - GR_GET_PROC(GrGLGenFramebuffersProc, GenFramebuffers); - GR_GET_PROC(GrGLGenRenderbuffersProc, GenRenderbuffers); - GR_GET_PROC(GrGLGetFramebufferAttachmentParameterivProc, - GetFramebufferAttachmentParameteriv); - GR_GET_PROC(GrGLGetRenderbufferParameterivProc, - GetRenderbufferParameteriv); - GR_GET_PROC(GrGLRenderbufferStorageProc, RenderbufferStorage); - - interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES"); - interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES"); - } - glInterface.get()->ref(); - return glInterface.get(); -} diff --git a/gfx/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp b/gfx/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp deleted file mode 100644 index 5492e197149e..000000000000 --- a/gfx/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp +++ /dev/null @@ -1,147 +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 "gl/GrGLInterface.h" - -#import -#import - -const GrGLInterface* GrGLCreateNativeInterface() { - static SkAutoTUnref glInterface; - if (!glInterface.get()) { - GrGLInterface* interface = SkNEW(GrGLInterface); - glInterface.reset(interface); - - 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->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->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; -#if GL_ARB_texture_storage - interface->fTexStorage2D = glTexStorage2D; -#elif GL_EXT_texture_storage - interface->fTexStorage2D = glTexStorage2DEXT; -#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; - -#if GL_OES_mapbuffer - interface->fMapBuffer = glMapBufferOES; - interface->fUnmapBuffer = glUnmapBufferOES; -#endif - -#if GL_APPLE_framebuffer_multisample - interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleAPPLE; - interface->fResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE; -#endif - -#if GL_OES_vertex_array_object - interface->fBindVertexArray = glBindVertexArrayOES; - interface->fDeleteVertexArrays = glDeleteVertexArraysOES; - interface->fGenVertexArrays = glGenVertexArraysOES; -#endif - - interface->fBindingsExported = kES2_GrGLBinding; - } - glInterface.get()->ref(); - return glInterface.get(); -} diff --git a/gfx/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp b/gfx/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp deleted file mode 100644 index 75cec63d7c24..000000000000 --- a/gfx/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp +++ /dev/null @@ -1,239 +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 "gl/GrGLInterface.h" -#include "gl/GrGLExtensions.h" -#include "../GrGLUtil.h" - -#include - -// 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() { - fLibrary = dlopen( - "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", - RTLD_LAZY); - } - ~GLLoader() { - if (NULL != fLibrary) { - dlclose(fLibrary); - } - } - void* handle() { - 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 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); - } - - 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(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(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(MapBuffer); - 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 (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(Viewport); - - 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); - } - - 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); - } - - 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(); -} diff --git a/gfx/skia/src/gpu/gr_unittests.cpp b/gfx/skia/src/gpu/gr_unittests.cpp deleted file mode 100644 index 618d412bb5a8..000000000000 --- a/gfx/skia/src/gpu/gr_unittests.cpp +++ /dev/null @@ -1,80 +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 "GrBinHashKey.h" -#include "GrDrawTarget.h" -#include "SkMatrix.h" -#include "GrRedBlackTree.h" - -// FIXME: needs to be in a header -void gr_run_unittests(); - -// If we aren't inheriting these as #defines from elsewhere, -// clang demands they be declared before we #include the template -// that relies on them. -#if GR_DEBUG -static bool LT(const int& elem, int value) { - return elem < value; -} -static bool EQ(const int& elem, int value) { - return elem == value; -} -#include "GrTBSearch.h" - -static void test_bsearch() { - const int array[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99 - }; - - for (size_t n = 0; n < GR_ARRAY_COUNT(array); n++) { - for (size_t i = 0; i < n; i++) { - int index = GrTBSearch(array, n, array[i]); - GrAssert(index == (int) i); - index = GrTBSearch(array, n, -array[i]); - GrAssert(index < 0); - } - } -} -#endif - -// bogus empty class for GrBinHashKey -class BogusEntry {}; - -static void test_binHashKey() -{ - const char* testStringA_ = "abcdABCD"; - const char* testStringB_ = "abcdBBCD"; - const uint32_t* testStringA = reinterpret_cast(testStringA_); - const uint32_t* testStringB = reinterpret_cast(testStringB_); - enum { - kDataLenUsedForKey = 8 - }; - - GrTBinHashKey keyA; - keyA.setKeyData(testStringA); - // test copy constructor and comparison - GrTBinHashKey keyA2(keyA); - GrAssert(keyA.compare(keyA2) == 0); - GrAssert(keyA.getHash() == keyA2.getHash()); - // test re-init - keyA2.setKeyData(testStringA); - GrAssert(keyA.compare(keyA2) == 0); - GrAssert(keyA.getHash() == keyA2.getHash()); - // test sorting - GrTBinHashKey keyB; - keyB.setKeyData(testStringB); - GrAssert(keyA.compare(keyB) < 0); - GrAssert(keyA.getHash() != keyB.getHash()); -} - - -void gr_run_unittests() { - GR_DEBUGCODE(test_bsearch();) - test_binHashKey(); - GrRedBlackTree::UnitTest(); -} diff --git a/gfx/skia/src/image/SkImage.cpp b/gfx/skia/src/image/SkImage.cpp deleted file mode 100644 index b388d58a3b44..000000000000 --- a/gfx/skia/src/image/SkImage.cpp +++ /dev/null @@ -1,33 +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 "SkBitmap.h" -#include "SkCanvas.h" - -SK_DEFINE_INST_COUNT(SkImage) - -static SkImage_Base* asIB(SkImage* image) { - return static_cast(image); -} - -uint32_t SkImage::NextUniqueID() { - static int32_t gUniqueID; - - // never return 0; - uint32_t id; - do { - id = sk_atomic_inc(&gUniqueID) + 1; - } while (0 == id); - return id; -} - -void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, - const SkPaint* paint) { - asIB(this)->onDraw(canvas, x, y, paint); -} diff --git a/gfx/skia/src/image/SkImagePriv.cpp b/gfx/skia/src/image/SkImagePriv.cpp deleted file mode 100644 index c44e439b72c8..000000000000 --- a/gfx/skia/src/image/SkImagePriv.cpp +++ /dev/null @@ -1,143 +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 "SkImagePriv.h" -#include "SkCanvas.h" -#include "SkPicture.h" - -SkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info& info, - bool* isOpaque) { - switch (info.fColorType) { - case SkImage::kAlpha_8_ColorType: - switch (info.fAlphaType) { - case SkImage::kIgnore_AlphaType: - // makes no sense - return SkBitmap::kNo_Config; - - case SkImage::kOpaque_AlphaType: - *isOpaque = true; - return SkBitmap::kA8_Config; - - case SkImage::kPremul_AlphaType: - case SkImage::kUnpremul_AlphaType: - *isOpaque = false; - return SkBitmap::kA8_Config; - } - break; - - case SkImage::kRGB_565_ColorType: - // we ignore fAlpahType, though some would not make sense - *isOpaque = true; - return SkBitmap::kRGB_565_Config; - - case SkImage::kRGBA_8888_ColorType: - case SkImage::kBGRA_8888_ColorType: - // not supported yet - return SkBitmap::kNo_Config; - - case SkImage::kPMColor_ColorType: - switch (info.fAlphaType) { - case SkImage::kIgnore_AlphaType: - case SkImage::kUnpremul_AlphaType: - // not supported yet - return SkBitmap::kNo_Config; - case SkImage::kOpaque_AlphaType: - *isOpaque = true; - return SkBitmap::kARGB_8888_Config; - case SkImage::kPremul_AlphaType: - *isOpaque = false; - return SkBitmap::kARGB_8888_Config; - } - break; - } - SkASSERT(!"how did we get here"); - return SkBitmap::kNo_Config; -} - -int SkImageBytesPerPixel(SkImage::ColorType ct) { - static const uint8_t gColorTypeBytesPerPixel[] = { - 1, // kAlpha_8_ColorType - 2, // kRGB_565_ColorType - 4, // kRGBA_8888_ColorType - 4, // kBGRA_8888_ColorType - 4, // kPMColor_ColorType - }; - - SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel)); - return gColorTypeBytesPerPixel[ct]; -} - -bool SkBitmapToImageInfo(const SkBitmap& bm, SkImage::Info* info) { - switch (bm.config()) { - case SkBitmap::kA8_Config: - info->fColorType = SkImage::kAlpha_8_ColorType; - break; - - case SkBitmap::kRGB_565_Config: - info->fColorType = SkImage::kRGB_565_ColorType; - break; - - case SkBitmap::kARGB_8888_Config: - info->fColorType = SkImage::kPMColor_ColorType; - break; - - default: - return false; - } - - info->fWidth = bm.width(); - info->fHeight = bm.height(); - info->fAlphaType = bm.isOpaque() ? SkImage::kOpaque_AlphaType : - SkImage::kPremul_AlphaType; - return true; -} - -SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) { - SkImage::Info info; - if (!SkBitmapToImageInfo(bm, &info)) { - return NULL; - } - - SkImage* image = NULL; - if (canSharePixelRef || bm.isImmutable()) { - image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes()); - } else { - bm.lockPixels(); - if (bm.getPixels()) { - image = SkImage::NewRasterCopy(info, bm.getPixels(), bm.rowBytes()); - } - bm.unlockPixels(); - } - 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); -} diff --git a/gfx/skia/src/image/SkImage_Base.h b/gfx/skia/src/image/SkImage_Base.h deleted file mode 100644 index 2687025a81b6..000000000000 --- a/gfx/skia/src/image/SkImage_Base.h +++ /dev/null @@ -1,23 +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 SkImage_Base_DEFINED -#define SkImage_Base_DEFINED - -#include "SkImage.h" - -class SkImage_Base : public SkImage { -public: - SkImage_Base(int width, int height) : INHERITED(width, height) {} - - virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) = 0; - -private: - typedef SkImage INHERITED; -}; - -#endif diff --git a/gfx/skia/src/image/SkSurface_Gpu.cpp b/gfx/skia/src/image/SkSurface_Gpu.cpp deleted file mode 100644 index 1ed68e50b1ba..000000000000 --- a/gfx/skia/src/image/SkSurface_Gpu.cpp +++ /dev/null @@ -1,146 +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 "SkImagePriv.h" -#include "SkCanvas.h" -#include "SkGpuDevice.h" - -class SkSurface_Gpu : public SkSurface_Base { -public: - SK_DECLARE_INST_COUNT(SkSurface_Gpu) - - SkSurface_Gpu(GrContext*, const SkImage::Info&, int sampleCount); - SkSurface_Gpu(GrContext*, GrRenderTarget*); - virtual ~SkSurface_Gpu(); - - virtual SkCanvas* onNewCanvas() SK_OVERRIDE; - virtual SkSurface* onNewSurface(const SkImage::Info&) SK_OVERRIDE; - virtual SkImage* onNewImageShapshot() SK_OVERRIDE; - virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, - const SkPaint*) SK_OVERRIDE; - virtual void onCopyOnWrite(SkImage*, SkCanvas*) SK_OVERRIDE; - -private: - SkGpuDevice* fDevice; - - typedef SkSurface_Base INHERITED; -}; - -SK_DEFINE_INST_COUNT(SkSurface_Gpu) - -/////////////////////////////////////////////////////////////////////////////// - -SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImage::Info& info, - int sampleCount) - : INHERITED(info.fWidth, info.fHeight) { - bool isOpaque; - SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); - - fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount)); - - if (!isOpaque) { - fDevice->clear(0x0); - } -} - -SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget) - : INHERITED(renderTarget->width(), renderTarget->height()) { - fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget)); - - if (kRGB_565_GrPixelConfig != renderTarget->config()) { - fDevice->clear(0x0); - } -} - -SkSurface_Gpu::~SkSurface_Gpu() { - SkSafeUnref(fDevice); -} - -SkCanvas* SkSurface_Gpu::onNewCanvas() { - return SkNEW_ARGS(SkCanvas, (fDevice)); -} - -SkSurface* SkSurface_Gpu::onNewSurface(const SkImage::Info& info) { - GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget(); - int sampleCount = rt->numSamples(); - return SkSurface::NewRenderTarget(fDevice->context(), info, sampleCount); -} - -SkImage* SkSurface_Gpu::onNewImageShapshot() { - - GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget(); - - return SkImage::NewTexture(rt->asTexture()); -} - -void SkSurface_Gpu::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, - const SkPaint* paint) { - canvas->drawBitmap(fDevice->accessBitmap(false), x, y, paint); -} - -// Copy the contents of the SkGpuDevice into a new texture and give that -// texture to the SkImage. Note that this flushes the SkGpuDevice but -// doesn't force an OpenGL flush. -void SkSurface_Gpu::onCopyOnWrite(SkImage* image, SkCanvas*) { - GrRenderTarget* rt = (GrRenderTarget*) fDevice->accessRenderTarget(); - - // are we sharing our render target with the image? - if (rt->asTexture() == SkTextureImageGetTexture(image)) { - GrTextureDesc desc; - // copyTexture requires a render target as the destination - desc.fFlags = kRenderTarget_GrTextureFlagBit; - desc.fWidth = fDevice->width(); - desc.fHeight = fDevice->height(); - desc.fConfig = SkBitmapConfig2GrPixelConfig(fDevice->config()); - desc.fSampleCnt = 0; - - SkAutoTUnref tex(fDevice->context()->createUncachedTexture(desc, NULL, 0)); - if (NULL == tex) { - SkTextureImageSetTexture(image, NULL); - return; - } - - fDevice->context()->copyTexture(rt->asTexture(), tex->asRenderTarget()); - - SkTextureImageSetTexture(image, tex); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx, - GrRenderTarget* target) { - if (NULL == ctx || NULL == target) { - return NULL; - } - - return SkNEW_ARGS(SkSurface_Gpu, (ctx, target)); -} - -SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImage::Info& info, int sampleCount) { - if (NULL == ctx) { - return NULL; - } - - bool isOpaque; - SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); - - GrTextureDesc desc; - desc.fFlags = kRenderTarget_GrTextureFlagBit; - desc.fWidth = info.fWidth; - desc.fHeight = info.fHeight; - desc.fConfig = SkBitmapConfig2GrPixelConfig(config); - desc.fSampleCnt = sampleCount; - - SkAutoTUnref tex(ctx->createUncachedTexture(desc, NULL, 0)); - if (NULL == tex) { - return NULL; - } - - return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget())); -} diff --git a/gfx/skia/src/images/SkBitmapRegionDecoder.cpp b/gfx/skia/src/images/SkBitmapRegionDecoder.cpp deleted file mode 100644 index 4cf1cca45c98..000000000000 --- a/gfx/skia/src/images/SkBitmapRegionDecoder.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkBitmapRegionDecoder.h" - -bool SkBitmapRegionDecoder::decodeRegion(SkBitmap* bitmap, const SkIRect& rect, - SkBitmap::Config pref, int sampleSize) { - fDecoder->setSampleSize(sampleSize); - return fDecoder->decodeRegion(bitmap, rect, pref); -} diff --git a/gfx/skia/src/images/SkImageDecoder_Factory.cpp b/gfx/skia/src/images/SkImageDecoder_Factory.cpp deleted file mode 100644 index c276a3d4ebe7..000000000000 --- a/gfx/skia/src/images/SkImageDecoder_Factory.cpp +++ /dev/null @@ -1,63 +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 "SkImageDecoder.h" -#include "SkMovie.h" -#include "SkStream.h" -#include "SkTRegistry.h" - -typedef SkTRegistry DecodeReg; - -// N.B. You can't use "DecodeReg::gHead here" due to complex C++ -// corner cases. -template DecodeReg* SkTRegistry::gHead; - -SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) { - SkImageDecoder* codec = NULL; - const DecodeReg* curr = DecodeReg::Head(); - while (curr) { - codec = curr->factory()(stream); - // we rewind here, because we promise later when we call "decode", that - // the stream will be at its beginning. - bool rewindSuceeded = stream->rewind(); - - // our image decoder's require that rewind is supported so we fail early - // if we are given a stream that does not support rewinding. - if (!rewindSuceeded) { - SkDEBUGF(("Unable to rewind the image stream.")); - SkDELETE(codec); - return NULL; - } - - if (codec) { - return codec; - } - curr = curr->next(); - } - return NULL; -} - -///////////////////////////////////////////////////////////////////////// - -typedef SkTRegistry MovieReg; - -SkMovie* SkMovie::DecodeStream(SkStream* stream) { - const MovieReg* curr = MovieReg::Head(); - while (curr) { - SkMovie* movie = curr->factory()(stream); - if (movie) { - return movie; - } - // we must rewind only if we got NULL, since we gave the stream to the - // movie, who may have already started reading from it - stream->rewind(); - curr = curr->next(); - } - return NULL; -} diff --git a/gfx/skia/src/images/SkImageDecoder_libgif.cpp b/gfx/skia/src/images/SkImageDecoder_libgif.cpp deleted file mode 100644 index 3e4cda8a0bac..000000000000 --- a/gfx/skia/src/images/SkImageDecoder_libgif.cpp +++ /dev/null @@ -1,382 +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 "SkImageDecoder.h" -#include "SkColor.h" -#include "SkColorPriv.h" -#include "SkStream.h" -#include "SkTemplates.h" -#include "SkPackBits.h" - -#include "gif_lib.h" - -class SkGIFImageDecoder : public SkImageDecoder { -public: - virtual Format getFormat() const SK_OVERRIDE { - return kGIF_Format; - } - -protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE; - -private: - typedef SkImageDecoder INHERITED; -}; - -static const uint8_t gStartingIterlaceYValue[] = { - 0, 4, 2, 1 -}; -static const uint8_t gDeltaIterlaceYValue[] = { - 8, 8, 4, 2 -}; - -/* Implement the GIF interlace algorithm in an iterator. - 1) grab every 8th line beginning at 0 - 2) grab every 8th line beginning at 4 - 3) grab every 4th line beginning at 2 - 4) grab every 2nd line beginning at 1 -*/ -class GifInterlaceIter { -public: - GifInterlaceIter(int height) : fHeight(height) { - fStartYPtr = gStartingIterlaceYValue; - fDeltaYPtr = gDeltaIterlaceYValue; - - fCurrY = *fStartYPtr++; - fDeltaY = *fDeltaYPtr++; - } - - int currY() const { - SkASSERT(fStartYPtr); - SkASSERT(fDeltaYPtr); - return fCurrY; - } - - void next() { - SkASSERT(fStartYPtr); - SkASSERT(fDeltaYPtr); - - int y = fCurrY + fDeltaY; - // We went from an if statement to a while loop so that we iterate - // through fStartYPtr until a valid row is found. This is so that images - // that are smaller than 5x5 will not trash memory. - while (y >= fHeight) { - if (gStartingIterlaceYValue + - SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) { - // we done - SkDEBUGCODE(fStartYPtr = NULL;) - SkDEBUGCODE(fDeltaYPtr = NULL;) - y = 0; - } else { - y = *fStartYPtr++; - fDeltaY = *fDeltaYPtr++; - } - } - fCurrY = y; - } - -private: - const int fHeight; - int fCurrY; - int fDeltaY; - const uint8_t* fStartYPtr; - const uint8_t* fDeltaYPtr; -}; - -/////////////////////////////////////////////////////////////////////////////// - -//#define GIF_STAMP "GIF" /* First chars in file - GIF stamp. */ -//#define GIF_STAMP_LEN (sizeof(GIF_STAMP) - 1) - -static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out, - int size) { - SkStream* stream = (SkStream*) fileType->UserData; - return (int) stream->read(out, size); -} - -void CheckFreeExtension(SavedImage* Image) { - if (Image->ExtensionBlocks) { -#if GIFLIB_MAJOR < 5 - FreeExtension(Image); -#else - GifFreeExtensions(&Image->ExtensionBlockCount, &Image->ExtensionBlocks); -#endif - } -} - -// return NULL on failure -static const ColorMapObject* find_colormap(const GifFileType* gif) { - const ColorMapObject* cmap = gif->Image.ColorMap; - if (NULL == cmap) { - cmap = gif->SColorMap; - } - - if (NULL == cmap) { - // no colormap found - return NULL; - } - // some sanity checks - if (cmap && ((unsigned)cmap->ColorCount > 256 || - cmap->ColorCount != (1 << cmap->BitsPerPixel))) { - cmap = NULL; - } - return cmap; -} - -// return -1 if not found (i.e. we're completely opaque) -static int find_transpIndex(const SavedImage& image, int colorCount) { - int transpIndex = -1; - for (int i = 0; i < image.ExtensionBlockCount; ++i) { - const ExtensionBlock* eb = image.ExtensionBlocks + i; - if (eb->Function == 0xF9 && eb->ByteCount == 4) { - if (eb->Bytes[0] & 1) { - transpIndex = (unsigned char)eb->Bytes[3]; - // check for valid transpIndex - if (transpIndex >= colorCount) { - transpIndex = -1; - } - break; - } - } - } - return transpIndex; -} - -static bool error_return(GifFileType* gif, const SkBitmap& bm, - const char msg[]) { -#if 0 - SkDebugf("libgif error <%s> bitmap [%d %d] pixels %p colortable %p\n", - msg, bm.width(), bm.height(), bm.getPixels(), bm.getColorTable()); -#endif - return false; -} - -bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { -#if GIFLIB_MAJOR < 5 - GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); -#else - GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL); -#endif - if (NULL == gif) { - return error_return(gif, *bm, "DGifOpen"); - } - - SkAutoTCallIProc acp(gif); - - SavedImage temp_save; - temp_save.ExtensionBlocks=NULL; - temp_save.ExtensionBlockCount=0; - SkAutoTCallVProc acp2(&temp_save); - - int width, height; - GifRecordType recType; - GifByteType *extData; -#if GIFLIB_MAJOR >= 5 - int extFunction; -#endif - int transpIndex = -1; // -1 means we don't have it (yet) - - do { - if (DGifGetRecordType(gif, &recType) == GIF_ERROR) { - return error_return(gif, *bm, "DGifGetRecordType"); - } - - switch (recType) { - case IMAGE_DESC_RECORD_TYPE: { - if (DGifGetImageDesc(gif) == GIF_ERROR) { - return error_return(gif, *bm, "IMAGE_DESC_RECORD_TYPE"); - } - - if (gif->ImageCount < 1) { // sanity check - return error_return(gif, *bm, "ImageCount < 1"); - } - - width = gif->SWidth; - height = gif->SHeight; - if (width <= 0 || height <= 0 || - !this->chooseFromOneChoice(SkBitmap::kIndex8_Config, - width, height)) { - return error_return(gif, *bm, "chooseFromOneChoice"); - } - - if (SkImageDecoder::kDecodeBounds_Mode == mode) { - bm->setConfig(SkBitmap::kIndex8_Config, width, height); - return true; - } - - // No Bitmap reuse supported for this format - if (!bm->isNull()) { - return false; - } - - bm->setConfig(SkBitmap::kIndex8_Config, width, height); - SavedImage* image = &gif->SavedImages[gif->ImageCount-1]; - const GifImageDesc& desc = image->ImageDesc; - - // check for valid descriptor - if ( (desc.Top | desc.Left) < 0 || - desc.Left + desc.Width > width || - desc.Top + desc.Height > height) { - return error_return(gif, *bm, "TopLeft"); - } - - // now we decode the colortable - int colorCount = 0; - { - const ColorMapObject* cmap = find_colormap(gif); - if (NULL == cmap) { - return error_return(gif, *bm, "null cmap"); - } - - colorCount = cmap->ColorCount; - SkColorTable* ctable = SkNEW_ARGS(SkColorTable, (colorCount)); - SkPMColor* colorPtr = ctable->lockColors(); - for (int index = 0; index < colorCount; index++) - colorPtr[index] = SkPackARGB32(0xFF, - cmap->Colors[index].Red, - cmap->Colors[index].Green, - cmap->Colors[index].Blue); - - transpIndex = find_transpIndex(temp_save, colorCount); - if (transpIndex < 0) - ctable->setFlags(ctable->getFlags() | SkColorTable::kColorsAreOpaque_Flag); - else - colorPtr[transpIndex] = 0; // ram in a transparent SkPMColor - ctable->unlockColors(true); - - SkAutoUnref aurts(ctable); - if (!this->allocPixelRef(bm, ctable)) { - return error_return(gif, *bm, "allocPixelRef"); - } - } - - SkAutoLockPixels alp(*bm); - - // time to decode the scanlines - // - uint8_t* scanline = bm->getAddr8(0, 0); - const int rowBytes = bm->rowBytes(); - const int innerWidth = desc.Width; - const int innerHeight = desc.Height; - - // abort if either inner dimension is <= 0 - if (innerWidth <= 0 || innerHeight <= 0) { - return error_return(gif, *bm, "non-pos inner width/height"); - } - - // are we only a subset of the total bounds? - if ((desc.Top | desc.Left) > 0 || - innerWidth < width || innerHeight < height) - { - int fill; - if (transpIndex >= 0) { - fill = transpIndex; - } else { - fill = gif->SBackGroundColor; - } - // check for valid fill index/color - if (static_cast(fill) >= - static_cast(colorCount)) { - fill = 0; - } - memset(scanline, fill, bm->getSize()); - // bump our starting address - scanline += desc.Top * rowBytes + desc.Left; - } - - // now decode each scanline - if (gif->Image.Interlace) - { - GifInterlaceIter iter(innerHeight); - for (int y = 0; y < innerHeight; y++) - { - uint8_t* row = scanline + iter.currY() * rowBytes; - if (DGifGetLine(gif, row, innerWidth) == GIF_ERROR) { - return error_return(gif, *bm, "interlace DGifGetLine"); - } - iter.next(); - } - } - else - { - // easy, non-interlace case - for (int y = 0; y < innerHeight; y++) { - if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) { - return error_return(gif, *bm, "DGifGetLine"); - } - scanline += rowBytes; - } - } - goto DONE; - } break; - - case EXTENSION_RECORD_TYPE: -#if GIFLIB_MAJOR < 5 - if (DGifGetExtension(gif, &temp_save.Function, - &extData) == GIF_ERROR) { -#else - if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) { -#endif - return error_return(gif, *bm, "DGifGetExtension"); - } - - while (extData != NULL) { - /* Create an extension block with our data */ -#if GIFLIB_MAJOR < 5 - if (AddExtensionBlock(&temp_save, extData[0], - &extData[1]) == GIF_ERROR) { -#else - if (GifAddExtensionBlock(&gif->ExtensionBlockCount, - &gif->ExtensionBlocks, - extFunction, - extData[0], - &extData[1]) == GIF_ERROR) { -#endif - return error_return(gif, *bm, "AddExtensionBlock"); - } - if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) { - return error_return(gif, *bm, "DGifGetExtensionNext"); - } -#if GIFLIB_MAJOR < 5 - temp_save.Function = 0; -#endif - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: /* Should be trapped by DGifGetRecordType */ - break; - } - } while (recType != TERMINATE_RECORD_TYPE); - -DONE: - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -DEFINE_DECODER_CREATOR(GIFImageDecoder); -/////////////////////////////////////////////////////////////////////////////// - -#include "SkTRegistry.h" - -static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) { - char buf[GIF_STAMP_LEN]; - if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { - if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 || - memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 || - memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) { - return SkNEW(SkGIFImageDecoder); - } - } - return NULL; -} - -static SkTRegistry gReg(sk_libgif_dfactory); diff --git a/gfx/skia/src/images/SkScaledBitmapSampler.cpp b/gfx/skia/src/images/SkScaledBitmapSampler.cpp deleted file mode 100644 index 25b32fd9b8e7..000000000000 --- a/gfx/skia/src/images/SkScaledBitmapSampler.cpp +++ /dev/null @@ -1,432 +0,0 @@ - -/* - * Copyright 2007 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "SkScaledBitmapSampler.h" -#include "SkBitmap.h" -#include "SkColorPriv.h" -#include "SkDither.h" - -// 8888 - -static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - unsigned alphaMask = 0xFF; - for (int x = 0; x < width; x++) { - unsigned alpha = src[3]; - dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); - src += deltaSrc; - alphaMask &= alpha; - } - return alphaMask != 0xFF; -} - -// 565 - -static bool Sample_Gray_D565(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); - src += deltaSrc; - } - return false; -} - -static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y, const SkPMColor[]) { - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - DITHER_565_SCAN(y); - for (int x = 0; x < width; x++) { - dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x)); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); - src += deltaSrc; - } - return false; -} - -static bool Sample_D565_D565(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src; - for (int x = 0; x < width; x++) { - dst[x] = castedSrc[0]; - castedSrc += deltaSrc >> 1; - } - return false; -} - -static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y, const SkPMColor[]) { - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - DITHER_565_SCAN(y); - for (int x = 0; x < width; x++) { - dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x)); - src += deltaSrc; - } - return false; -} - -// 4444 - -static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - for (int x = 0; x < width; x++) { - unsigned gray = src[0] >> 4; - dst[x] = SkPackARGB4444(0xF, gray, gray, gray); - src += deltaSrc; - } - return false; -} - -static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y, const SkPMColor[]) { - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - DITHER_4444_SCAN(y); - for (int x = 0; x < width; x++) { - dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0], - DITHER_VALUE(x)); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y, const SkPMColor[]) { - SkPMColor16* dst = (SkPMColor16*)dstRow; - DITHER_4444_SCAN(y); - - for (int x = 0; x < width; x++) { - dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2], - DITHER_VALUE(x)); - src += deltaSrc; - } - return false; -} - -static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - unsigned alphaMask = 0xFF; - - for (int x = 0; x < width; x++) { - unsigned alpha = src[3]; - SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); - dst[x] = SkPixel32ToPixel4444(c); - src += deltaSrc; - alphaMask &= alpha; - } - return alphaMask != 0xFF; -} - -static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y, const SkPMColor[]) { - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - unsigned alphaMask = 0xFF; - DITHER_4444_SCAN(y); - - for (int x = 0; x < width; x++) { - unsigned alpha = src[3]; - SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); - dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); - src += deltaSrc; - alphaMask &= alpha; - } - return alphaMask != 0xFF; -} - -// Index - -#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) - -static bool Sample_Index_D8888(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor ctable[]) { - - SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - SkPMColor cc = A32_MASK_IN_PLACE; - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[*src]; - cc &= c; - dst[x] = c; - src += deltaSrc; - } - return cc != A32_MASK_IN_PLACE; -} - -static bool Sample_Index_D565(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor ctable[]) { - - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPixel32ToPixel16(ctable[*src]); - src += deltaSrc; - } - return false; -} - -static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, int width, - int deltaSrc, int y, const SkPMColor ctable[]) { - - uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - DITHER_565_SCAN(y); - - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[*src]; - dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c), - SkGetPackedB32(c), DITHER_VALUE(x)); - src += deltaSrc; - } - return false; -} - -static bool Sample_Index_D4444(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, int width, - int deltaSrc, int y, const SkPMColor ctable[]) { - - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - SkPMColor cc = A32_MASK_IN_PLACE; - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[*src]; - cc &= c; - dst[x] = SkPixel32ToPixel4444(c); - src += deltaSrc; - } - return cc != A32_MASK_IN_PLACE; -} - -static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, int width, - int deltaSrc, int y, const SkPMColor ctable[]) { - - SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow; - SkPMColor cc = A32_MASK_IN_PLACE; - DITHER_4444_SCAN(y); - - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[*src]; - cc &= c; - dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x)); - src += deltaSrc; - } - return cc != A32_MASK_IN_PLACE; -} - -static bool Sample_Index_DI(void* SK_RESTRICT dstRow, - const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int, const SkPMColor[]) { - if (1 == deltaSrc) { - memcpy(dstRow, src, width); - } else { - uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = src[0]; - src += deltaSrc; - } - } - return false; -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkScaledBitmapSampler.h" - -SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, - int sampleSize) { - fCTable = NULL; - fDstRow = NULL; - fRowProc = NULL; - - if (width <= 0 || height <= 0) { - sk_throw(); - } - - if (sampleSize <= 1) { - fScaledWidth = width; - fScaledHeight = height; - fX0 = fY0 = 0; - fDX = fDY = 1; - return; - } - - int dx = SkMin32(sampleSize, width); - int dy = SkMin32(sampleSize, height); - - fScaledWidth = width / dx; - fScaledHeight = height / dy; - - SkASSERT(fScaledWidth > 0); - SkASSERT(fScaledHeight > 0); - - fX0 = dx >> 1; - fY0 = dy >> 1; - - SkASSERT(fX0 >= 0 && fX0 < width); - SkASSERT(fY0 >= 0 && fY0 < height); - - fDX = dx; - fDY = dy; - - SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width); - SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height); -} - -bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither, - const SkPMColor ctable[]) { - static const RowProc gProcs[] = { - // 8888 (no dither distinction) - Sample_Gray_D8888, Sample_Gray_D8888, - Sample_RGBx_D8888, Sample_RGBx_D8888, - Sample_RGBA_D8888, Sample_RGBA_D8888, - Sample_Index_D8888, Sample_Index_D8888, - NULL, NULL, - // 565 (no alpha distinction) - Sample_Gray_D565, Sample_Gray_D565_D, - Sample_RGBx_D565, Sample_RGBx_D565_D, - Sample_RGBx_D565, Sample_RGBx_D565_D, - Sample_Index_D565, Sample_Index_D565_D, - Sample_D565_D565, Sample_D565_D565, - // 4444 - Sample_Gray_D4444, Sample_Gray_D4444_D, - Sample_RGBx_D4444, Sample_RGBx_D4444_D, - Sample_RGBA_D4444, Sample_RGBA_D4444_D, - Sample_Index_D4444, Sample_Index_D4444_D, - NULL, NULL, - // Index8 - NULL, NULL, - NULL, NULL, - NULL, NULL, - Sample_Index_DI, Sample_Index_DI, - NULL, NULL, - }; - - fCTable = ctable; - - int index = 0; - if (dither) { - index += 1; - } - switch (sc) { - case SkScaledBitmapSampler::kGray: - fSrcPixelSize = 1; - index += 0; - break; - case SkScaledBitmapSampler::kRGB: - fSrcPixelSize = 3; - index += 2; - break; - case SkScaledBitmapSampler::kRGBX: - fSrcPixelSize = 4; - index += 2; - break; - case SkScaledBitmapSampler::kRGBA: - fSrcPixelSize = 4; - index += 4; - break; - case SkScaledBitmapSampler::kIndex: - fSrcPixelSize = 1; - index += 6; - break; - case SkScaledBitmapSampler::kRGB_565: - fSrcPixelSize = 2; - index += 8; - break; - default: - return false; - } - - switch (dst->config()) { - case SkBitmap::kARGB_8888_Config: - index += 0; - break; - case SkBitmap::kRGB_565_Config: - index += 10; - break; - case SkBitmap::kARGB_4444_Config: - index += 20; - break; - case SkBitmap::kIndex8_Config: - index += 30; - break; - default: - return false; - } - - fRowProc = gProcs[index]; - fDstRow = (char*)dst->getPixels(); - fDstRowBytes = dst->rowBytes(); - fCurrY = 0; - return fRowProc != NULL; -} - -bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) { - SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight); - - bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth, - fDX * fSrcPixelSize, fCurrY, fCTable); - fDstRow += fDstRowBytes; - fCurrY += 1; - return hadAlpha; -} diff --git a/gfx/skia/src/lazy/SkBitmapFactory.cpp b/gfx/skia/src/lazy/SkBitmapFactory.cpp deleted file mode 100644 index 60c4993e3cf0..000000000000 --- a/gfx/skia/src/lazy/SkBitmapFactory.cpp +++ /dev/null @@ -1,81 +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 "SkBitmapFactory.h" - -#include "SkBitmap.h" -#include "SkData.h" -#include "SkImageCache.h" -#include "SkImagePriv.h" -#include "SkLazyPixelRef.h" - -SkBitmapFactory::SkBitmapFactory(SkBitmapFactory::DecodeProc proc) - : fDecodeProc(proc) - , fImageCache(NULL) - , fCacheSelector(NULL) { - SkASSERT(fDecodeProc != NULL); -} - -SkBitmapFactory::~SkBitmapFactory() { - SkSafeUnref(fImageCache); - SkSafeUnref(fCacheSelector); -} - -void SkBitmapFactory::setImageCache(SkImageCache *cache) { - SkRefCnt_SafeAssign(fImageCache, cache); - if (cache != NULL) { - SkSafeUnref(fCacheSelector); - fCacheSelector = NULL; - } -} - -void SkBitmapFactory::setCacheSelector(CacheSelector* selector) { - SkRefCnt_SafeAssign(fCacheSelector, selector); - if (selector != NULL) { - SkSafeUnref(fImageCache); - fImageCache = NULL; - } -} - -bool SkBitmapFactory::installPixelRef(SkData* data, SkBitmap* dst) { - if (NULL == data || 0 == data->size() || dst == NULL) { - return false; - } - - SkImage::Info info; - if (!fDecodeProc(data->data(), data->size(), &info, NULL)) { - return false; - } - - bool isOpaque = false; - SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); - - Target target; - // FIMXE: There will be a problem if this rowbytes is calculated differently from - // in SkLazyPixelRef. - target.fRowBytes = SkImageMinRowBytes(info); - - dst->setConfig(config, info.fWidth, info.fHeight, target.fRowBytes); - dst->setIsOpaque(isOpaque); - - // fImageCache and fCacheSelector are mutually exclusive. - SkASSERT(NULL == fImageCache || NULL == fCacheSelector); - - SkImageCache* cache = NULL == fCacheSelector ? fImageCache : fCacheSelector->selectCache(info); - - if (cache != NULL) { - // Now set a new LazyPixelRef on dst. - SkAutoTUnref lazyRef(SkNEW_ARGS(SkLazyPixelRef, - (data, fDecodeProc, cache))); - dst->setPixelRef(lazyRef); - return true; - } else { - dst->allocPixels(); - target.fAddr = dst->getPixels(); - return fDecodeProc(data->data(), data->size(), &info, &target); - } -} diff --git a/gfx/skia/src/lazy/SkLazyPixelRef.cpp b/gfx/skia/src/lazy/SkLazyPixelRef.cpp deleted file mode 100644 index dc9aef9f062d..000000000000 --- a/gfx/skia/src/lazy/SkLazyPixelRef.cpp +++ /dev/null @@ -1,147 +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 "Sk64.h" -#include "SkLazyPixelRef.h" -#include "SkColorTable.h" -#include "SkData.h" -#include "SkImageCache.h" -#include "SkImagePriv.h" - -#if LAZY_CACHE_STATS -#include "SkThread.h" - -int32_t SkLazyPixelRef::gCacheHits; -int32_t SkLazyPixelRef::gCacheMisses; -#endif - -SkLazyPixelRef::SkLazyPixelRef(SkData* data, SkBitmapFactory::DecodeProc proc, SkImageCache* cache) - // Pass NULL for the Mutex so that the default (ring buffer) will be used. - : INHERITED(NULL) - , fDecodeProc(proc) - , fImageCache(cache) - , fCacheId(SkImageCache::UNINITIALIZED_ID) - , fRowBytes(0) { - SkASSERT(fDecodeProc != NULL); - if (NULL == data) { - fData = SkData::NewEmpty(); - fErrorInDecoding = true; - } else { - fData = data; - fData->ref(); - fErrorInDecoding = data->size() == 0; - } - SkASSERT(cache != NULL); - cache->ref(); - // Since this pixel ref bases its data on encoded data, it should never change. - this->setImmutable(); -} - -SkLazyPixelRef::~SkLazyPixelRef() { - SkASSERT(fData != NULL); - fData->unref(); - SkASSERT(fImageCache); - if (fCacheId != SkImageCache::UNINITIALIZED_ID) { - fImageCache->throwAwayCache(fCacheId); - } - fImageCache->unref(); -} - -static size_t ComputeMinRowBytesAndSize(const SkImage::Info& info, size_t* rowBytes) { - *rowBytes = SkImageMinRowBytes(info); - - Sk64 safeSize; - safeSize.setZero(); - if (info.fHeight > 0) { - safeSize.setMul(info.fHeight, SkToS32(*rowBytes)); - } - SkASSERT(!safeSize.isNeg()); - return safeSize.is32() ? safeSize.get32() : 0; -} - -void* SkLazyPixelRef::onLockPixels(SkColorTable**) { - if (fErrorInDecoding) { - return NULL; - } - SkBitmapFactory::Target target; - // Check to see if the pixels still exist in the cache. - if (SkImageCache::UNINITIALIZED_ID == fCacheId) { - target.fAddr = NULL; - } else { - SkImageCache::DataStatus status; - target.fAddr = fImageCache->pinCache(fCacheId, &status); - if (target.fAddr == NULL) { - fCacheId = SkImageCache::UNINITIALIZED_ID; - } else { - if (SkImageCache::kRetained_DataStatus == status) { -#if LAZY_CACHE_STATS - sk_atomic_inc(&gCacheHits); -#endif - return target.fAddr; - } - SkASSERT(SkImageCache::kUninitialized_DataStatus == status); - } - // Cache miss. Either pinCache returned NULL or it returned a memory address without the old - // data -#if LAZY_CACHE_STATS - sk_atomic_inc(&gCacheMisses); -#endif - } - SkImage::Info info; - SkASSERT(fData != NULL && fData->size() > 0); - if (NULL == target.fAddr) { - // Determine the size of the image in order to determine how much memory to allocate. - // FIXME: As an optimization, only do this part once. - fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL); - if (fErrorInDecoding) { - // We can only reach here if fCacheId was already set to UNINITIALIZED_ID, or if - // pinCache returned NULL, in which case it was reset to UNINITIALIZED_ID. - SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); - return NULL; - } - - size_t bytes = ComputeMinRowBytesAndSize(info, &target.fRowBytes); - target.fAddr = fImageCache->allocAndPinCache(bytes, &fCacheId); - if (NULL == target.fAddr) { - // Space could not be allocated. - // Just like the last assert, fCacheId must be UNINITIALIZED_ID. - SkASSERT(SkImageCache::UNINITIALIZED_ID == fCacheId); - return NULL; - } - } else { - // pinCache returned purged memory to which target.fAddr already points. Set - // target.fRowBytes properly. - target.fRowBytes = fRowBytes; - // Assume that the size is correct, since it was determined by this same function - // previously. - } - SkASSERT(target.fAddr != NULL); - SkASSERT(SkImageCache::UNINITIALIZED_ID != fCacheId); - fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, &target); - if (fErrorInDecoding) { - fImageCache->throwAwayCache(fCacheId); - fCacheId = SkImageCache::UNINITIALIZED_ID; - return NULL; - } - // Upon success, store fRowBytes so it can be used in case pinCache later returns purged memory. - fRowBytes = target.fRowBytes; - return target.fAddr; -} - -void SkLazyPixelRef::onUnlockPixels() { - if (fErrorInDecoding) { - return; - } - if (fCacheId != SkImageCache::UNINITIALIZED_ID) { - fImageCache->releaseCache(fCacheId); - } -} - -SkData* SkLazyPixelRef::onRefEncodedData() { - fData->ref(); - return fData; -} diff --git a/gfx/skia/src/lazy/SkLazyPixelRef.h b/gfx/skia/src/lazy/SkLazyPixelRef.h deleted file mode 100644 index fd41dd4682b0..000000000000 --- a/gfx/skia/src/lazy/SkLazyPixelRef.h +++ /dev/null @@ -1,81 +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 SkLazyPixelRef_DEFINED -#define SkLazyPixelRef_DEFINED - -#include "SkBitmapFactory.h" -#include "SkImage.h" -#include "SkPixelRef.h" -#include "SkFlattenable.h" - -class SkColorTable; -class SkData; -class SkImageCache; - -#ifdef SK_DEBUG - #define LAZY_CACHE_STATS 1 -#elif !defined(LAZY_CACHE_STATS) - #define LAZY_CACHE_STATS 0 -#endif - -/** - * PixelRef which defers decoding until SkBitmap::lockPixels() is called. - */ -class SkLazyPixelRef : public SkPixelRef { - -public: - /** - * Create a new SkLazyPixelRef. - * @param SkData Encoded data representing the pixels. - * @param DecodeProc Called to decode the pixels when needed. Must be non-NULL. - * @param SkImageCache Object that handles allocating and freeing the pixel memory, as needed. - * Must not be NULL. - */ - SkLazyPixelRef(SkData*, SkBitmapFactory::DecodeProc, SkImageCache*); - - virtual ~SkLazyPixelRef(); - -#ifdef SK_DEBUG - intptr_t getCacheId() const { return fCacheId; } -#endif - -#if LAZY_CACHE_STATS - static int32_t GetCacheHits() { return gCacheHits; } - static int32_t GetCacheMisses() { return gCacheMisses; } - static void ResetCacheStats() { gCacheHits = gCacheMisses = 0; } -#endif - - // No need to flatten this object. When flattening an SkBitmap, SkOrderedWriteBuffer will check - // the encoded data and write that instead. - // Future implementations of SkFlattenableWriteBuffer will need to special case for - // onRefEncodedData as well. - SK_DECLARE_UNFLATTENABLE_OBJECT() - -protected: - virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE; - virtual void onUnlockPixels() SK_OVERRIDE; - virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; } - virtual SkData* onRefEncodedData() SK_OVERRIDE; - -private: - bool fErrorInDecoding; - SkData* fData; - SkBitmapFactory::DecodeProc fDecodeProc; - SkImageCache* fImageCache; - intptr_t fCacheId; - size_t fRowBytes; - -#if LAZY_CACHE_STATS - static int32_t gCacheHits; - static int32_t gCacheMisses; -#endif - - typedef SkPixelRef INHERITED; -}; - -#endif // SkLazyPixelRef_DEFINED diff --git a/gfx/skia/src/lazy/SkLruImageCache.cpp b/gfx/skia/src/lazy/SkLruImageCache.cpp deleted file mode 100644 index 26f7ef54838b..000000000000 --- a/gfx/skia/src/lazy/SkLruImageCache.cpp +++ /dev/null @@ -1,203 +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 "SkLruImageCache.h" - -static intptr_t NextGenerationID() { - static intptr_t gNextID; - do { - gNextID++; - } while (SkImageCache::UNINITIALIZED_ID == gNextID); - return gNextID; -} - -class CachedPixels : public SkNoncopyable { - -public: - CachedPixels(size_t length) - : fLength(length) - , fID(NextGenerationID()) - , fLocked(false) { - fAddr = sk_malloc_throw(length); - } - - ~CachedPixels() { - sk_free(fAddr); - } - - void* getData() { return fAddr; } - - intptr_t getID() const { return fID; } - - size_t getLength() const { return fLength; } - - void lock() { SkASSERT(!fLocked); fLocked = true; } - - void unlock() { SkASSERT(fLocked); fLocked = false; } - - bool isLocked() const { return fLocked; } - -private: - void* fAddr; - size_t fLength; - const intptr_t fID; - bool fLocked; - SK_DECLARE_INTERNAL_LLIST_INTERFACE(CachedPixels); -}; - -//////////////////////////////////////////////////////////////////////////////////// - -SkLruImageCache::SkLruImageCache(size_t budget) - : fRamBudget(budget) - , fRamUsed(0) {} - -SkLruImageCache::~SkLruImageCache() { - // Don't worry about updating pointers. All will be deleted. - Iter iter; - CachedPixels* pixels = iter.init(fLRU, Iter::kTail_IterStart); - while (pixels != NULL) { - CachedPixels* prev = iter.prev(); - SkASSERT(!pixels->isLocked()); -#ifdef SK_DEBUG - fRamUsed -= pixels->getLength(); -#endif - SkDELETE(pixels); - pixels = prev; - } -#ifdef SK_DEBUG - SkASSERT(fRamUsed == 0); -#endif -} - -#ifdef SK_DEBUG -SkImageCache::MemoryStatus SkLruImageCache::getMemoryStatus(intptr_t ID) const { - if (SkImageCache::UNINITIALIZED_ID == ID) { - return SkImageCache::kFreed_MemoryStatus; - } - SkAutoMutexAcquire ac(&fMutex); - CachedPixels* pixels = this->findByID(ID); - if (NULL == pixels) { - return SkImageCache::kFreed_MemoryStatus; - } - if (pixels->isLocked()) { - return SkImageCache::kPinned_MemoryStatus; - } - return SkImageCache::kUnpinned_MemoryStatus; -} - -void SkLruImageCache::purgeAllUnpinnedCaches() { - SkAutoMutexAcquire ac(&fMutex); - this->purgeTilAtOrBelow(0); -} -#endif - -size_t SkLruImageCache::setImageCacheLimit(size_t newLimit) { - size_t oldLimit = fRamBudget; - SkAutoMutexAcquire ac(&fMutex); - fRamBudget = newLimit; - this->purgeIfNeeded(); - return oldLimit; -} - -void* SkLruImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) { - SkAutoMutexAcquire ac(&fMutex); - CachedPixels* pixels = SkNEW_ARGS(CachedPixels, (bytes)); - if (ID != NULL) { - *ID = pixels->getID(); - } - pixels->lock(); - fRamUsed += bytes; - fLRU.addToHead(pixels); - this->purgeIfNeeded(); - return pixels->getData(); -} - -void* SkLruImageCache::pinCache(intptr_t ID, SkImageCache::DataStatus* status) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&fMutex); - CachedPixels* pixels = this->findByID(ID); - if (NULL == pixels) { - return NULL; - } - if (pixels != fLRU.head()) { - fLRU.remove(pixels); - fLRU.addToHead(pixels); - } - SkASSERT(status != NULL); - // This cache will never return pinned memory whose data has been overwritten. - *status = SkImageCache::kRetained_DataStatus; - pixels->lock(); - return pixels->getData(); -} - -void SkLruImageCache::releaseCache(intptr_t ID) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&fMutex); - CachedPixels* pixels = this->findByID(ID); - SkASSERT(pixels != NULL); - pixels->unlock(); - this->purgeIfNeeded(); -} - -void SkLruImageCache::throwAwayCache(intptr_t ID) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&fMutex); - CachedPixels* pixels = this->findByID(ID); - if (pixels != NULL) { - if (pixels->isLocked()) { - pixels->unlock(); - } - this->removePixels(pixels); - } -} - -void SkLruImageCache::removePixels(CachedPixels* pixels) { - // Mutex is already locked. - SkASSERT(!pixels->isLocked()); - const size_t size = pixels->getLength(); - SkASSERT(size <= fRamUsed); - fLRU.remove(pixels); - SkDELETE(pixels); - fRamUsed -= size; -} - -CachedPixels* SkLruImageCache::findByID(intptr_t ID) const { - // Mutex is already locked. - Iter iter; - // Start from the head, most recently used. - CachedPixels* pixels = iter.init(fLRU, Iter::kHead_IterStart); - while (pixels != NULL) { - if (pixels->getID() == ID) { - return pixels; - } - pixels = iter.next(); - } - return NULL; -} - -void SkLruImageCache::purgeIfNeeded() { - // Mutex is already locked. - if (fRamBudget > 0) { - this->purgeTilAtOrBelow(fRamBudget); - } -} - -void SkLruImageCache::purgeTilAtOrBelow(size_t limit) { - // Mutex is already locked. - if (fRamUsed > limit) { - Iter iter; - // Start from the tail, least recently used. - CachedPixels* pixels = iter.init(fLRU, Iter::kTail_IterStart); - while (pixels != NULL && fRamUsed > limit) { - CachedPixels* prev = iter.prev(); - if (!pixels->isLocked()) { - this->removePixels(pixels); - } - pixels = prev; - } - } -} diff --git a/gfx/skia/src/lazy/SkPurgeableImageCache.cpp b/gfx/skia/src/lazy/SkPurgeableImageCache.cpp deleted file mode 100644 index 0f2c5e3c8e38..000000000000 --- a/gfx/skia/src/lazy/SkPurgeableImageCache.cpp +++ /dev/null @@ -1,159 +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 "SkThread.h" -#include "SkPurgeableImageCache.h" -#include "SkPurgeableMemoryBlock.h" - -#ifdef SK_DEBUG - #include "SkTSearch.h" -#endif - -SK_DECLARE_STATIC_MUTEX(gPurgeableImageMutex); - -SkImageCache* SkPurgeableImageCache::Create() { - if (!SkPurgeableMemoryBlock::IsSupported()) { - return NULL; - } - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - static SkPurgeableImageCache gCache; - gCache.ref(); - return &gCache; -} - -SkPurgeableImageCache::SkPurgeableImageCache() {} - -#ifdef SK_DEBUG -SkPurgeableImageCache::~SkPurgeableImageCache() { - SkASSERT(fRecs.count() == 0); -} -#endif - - -void* SkPurgeableImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) { - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - - SkPurgeableMemoryBlock* block = SkPurgeableMemoryBlock::Create(bytes); - if (NULL == block) { - return NULL; - } - - SkPurgeableMemoryBlock::PinResult pinResult; - void* data = block->pin(&pinResult); - if (NULL == data) { - SkDELETE(block); - return NULL; - } - - SkASSERT(ID != NULL); - *ID = reinterpret_cast(block); -#ifdef SK_DEBUG - // Insert into the array of all recs: - int index = this->findRec(*ID); - SkASSERT(index < 0); - fRecs.insert(~index, 1, ID); -#endif - return data; -} - -void* SkPurgeableImageCache::pinCache(intptr_t ID, SkImageCache::DataStatus* status) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - - SkASSERT(this->findRec(ID) >= 0); - SkPurgeableMemoryBlock* block = reinterpret_cast(ID); - SkPurgeableMemoryBlock::PinResult pinResult; - void* data = block->pin(&pinResult); - if (NULL == data) { - this->removeRec(ID); - return NULL; - } - - switch (pinResult) { - case SkPurgeableMemoryBlock::kRetained_PinResult: - *status = SkImageCache::kRetained_DataStatus; - break; - - case SkPurgeableMemoryBlock::kUninitialized_PinResult: - *status = SkImageCache::kUninitialized_DataStatus; - break; - - default: - // Invalid value. Treat as a failure to pin. - SkASSERT(false); - this->removeRec(ID); - return NULL; - } - - return data; -} - -void SkPurgeableImageCache::releaseCache(intptr_t ID) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - - SkASSERT(this->findRec(ID) >= 0); - SkPurgeableMemoryBlock* block = reinterpret_cast(ID); - block->unpin(); -} - -void SkPurgeableImageCache::throwAwayCache(intptr_t ID) { - SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - - this->removeRec(ID); -} - -#ifdef SK_DEBUG -SkImageCache::MemoryStatus SkPurgeableImageCache::getMemoryStatus(intptr_t ID) const { - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - if (SkImageCache::UNINITIALIZED_ID == ID || this->findRec(ID) < 0) { - return SkImageCache::kFreed_MemoryStatus; - } - - SkPurgeableMemoryBlock* block = reinterpret_cast(ID); - if (block->isPinned()) { - return SkImageCache::kPinned_MemoryStatus; - } - return SkImageCache::kUnpinned_MemoryStatus; -} - -void SkPurgeableImageCache::purgeAllUnpinnedCaches() { - SkAutoMutexAcquire ac(&gPurgeableImageMutex); - if (SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks()) { - SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks(); - } else { - // Go through the blocks, and purge them individually. - // Rather than deleting the blocks, which would interfere with further calls, purge them - // and keep them around. - for (int i = 0; i < fRecs.count(); i++) { - SkPurgeableMemoryBlock* block = reinterpret_cast(fRecs[i]); - if (!block->isPinned()) { - if (!block->purge()) { - // FIXME: This should be more meaningful (which one, etc...) - SkDebugf("Failed to purge\n"); - } - } - } - } -} - -int SkPurgeableImageCache::findRec(intptr_t rec) const { - return SkTSearch(fRecs.begin(), fRecs.count(), rec, sizeof(intptr_t)); -} -#endif - -void SkPurgeableImageCache::removeRec(intptr_t ID) { -#ifdef SK_DEBUG - int index = this->findRec(ID); - SkASSERT(index >= 0); - fRecs.remove(index); -#endif - SkPurgeableMemoryBlock* block = reinterpret_cast(ID); - SkASSERT(!block->isPinned()); - SkDELETE(block); -} diff --git a/gfx/skia/src/opts/SkBitmapProcState_arm_neon.cpp b/gfx/skia/src/opts/SkBitmapProcState_arm_neon.cpp deleted file mode 100644 index d50707dce0c7..000000000000 --- a/gfx/skia/src/opts/SkBitmapProcState_arm_neon.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 "SkBitmapProcState.h" -#include "SkBitmapProcState_filter.h" -#include "SkColorPriv.h" -#include "SkFilterProc.h" -#include "SkPaint.h" -#include "SkShader.h" // for tilemodes -#include "SkUtilsArm.h" - -// Required to ensure the table is part of the final binary. -extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; -extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; - -#define NAME_WRAP(x) x ## _neon -#include "SkBitmapProcState_filter_neon.h" -#include "SkBitmapProcState_procs.h" - -const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[] = { - S32_opaque_D32_nofilter_DXDY_neon, - S32_alpha_D32_nofilter_DXDY_neon, - S32_opaque_D32_nofilter_DX_neon, - S32_alpha_D32_nofilter_DX_neon, - S32_opaque_D32_filter_DXDY_neon, - S32_alpha_D32_filter_DXDY_neon, - S32_opaque_D32_filter_DX_neon, - S32_alpha_D32_filter_DX_neon, - - S16_opaque_D32_nofilter_DXDY_neon, - S16_alpha_D32_nofilter_DXDY_neon, - S16_opaque_D32_nofilter_DX_neon, - S16_alpha_D32_nofilter_DX_neon, - S16_opaque_D32_filter_DXDY_neon, - S16_alpha_D32_filter_DXDY_neon, - S16_opaque_D32_filter_DX_neon, - S16_alpha_D32_filter_DX_neon, - - SI8_opaque_D32_nofilter_DXDY_neon, - SI8_alpha_D32_nofilter_DXDY_neon, - SI8_opaque_D32_nofilter_DX_neon, - SI8_alpha_D32_nofilter_DX_neon, - SI8_opaque_D32_filter_DXDY_neon, - SI8_alpha_D32_filter_DXDY_neon, - SI8_opaque_D32_filter_DX_neon, - SI8_alpha_D32_filter_DX_neon, - - S4444_opaque_D32_nofilter_DXDY_neon, - S4444_alpha_D32_nofilter_DXDY_neon, - S4444_opaque_D32_nofilter_DX_neon, - S4444_alpha_D32_nofilter_DX_neon, - S4444_opaque_D32_filter_DXDY_neon, - S4444_alpha_D32_filter_DXDY_neon, - S4444_opaque_D32_filter_DX_neon, - S4444_alpha_D32_filter_DX_neon, - - // A8 treats alpha/opauqe the same (equally efficient) - SA8_alpha_D32_nofilter_DXDY_neon, - SA8_alpha_D32_nofilter_DXDY_neon, - SA8_alpha_D32_nofilter_DX_neon, - SA8_alpha_D32_nofilter_DX_neon, - SA8_alpha_D32_filter_DXDY_neon, - SA8_alpha_D32_filter_DXDY_neon, - SA8_alpha_D32_filter_DX_neon, - SA8_alpha_D32_filter_DX_neon -}; - -const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[] = { - S32_D16_nofilter_DXDY_neon, - S32_D16_nofilter_DX_neon, - S32_D16_filter_DXDY_neon, - S32_D16_filter_DX_neon, - - S16_D16_nofilter_DXDY_neon, - S16_D16_nofilter_DX_neon, - S16_D16_filter_DXDY_neon, - S16_D16_filter_DX_neon, - - SI8_D16_nofilter_DXDY_neon, - SI8_D16_nofilter_DX_neon, - SI8_D16_filter_DXDY_neon, - SI8_D16_filter_DX_neon, - - // Don't support 4444 -> 565 - NULL, NULL, NULL, NULL, - // Don't support A8 -> 565 - NULL, NULL, NULL, NULL -}; diff --git a/gfx/skia/src/opts/SkBitmapProcState_filter_neon.h b/gfx/skia/src/opts/SkBitmapProcState_filter_neon.h deleted file mode 100644 index 699f856d16b7..000000000000 --- a/gfx/skia/src/opts/SkBitmapProcState_filter_neon.h +++ /dev/null @@ -1,88 +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. - */ - - -#include "SkColorPriv.h" - -/* - Filter_32_opaque - - There is no hard-n-fast rule that the filtering must produce - 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) { - asm volatile( - "vdup.8 d0, %[y] \n\t" // duplicate y into d0 - "vmov.u8 d16, #16 \n\t" // set up constant in d16 - "vsub.u8 d1, d16, d0 \n\t" // d1 = 16-y - - "vdup.32 d4, %[a00] \n\t" // duplicate a00 into d4 - "vdup.32 d5, %[a10] \n\t" // duplicate a10 into d5 - "vmov.32 d4[1], %[a01] \n\t" // set top of d4 to a01 - "vmov.32 d5[1], %[a11] \n\t" // set top of d5 to a11 - - "vmull.u8 q3, d4, d1 \n\t" // q3 = [a01|a00] * (16-y) - "vmull.u8 q0, d5, d0 \n\t" // q0 = [a11|a10] * y - - "vdup.16 d5, %[x] \n\t" // duplicate x into d5 - "vmov.u16 d16, #16 \n\t" // set up constant in d16 - "vsub.u16 d3, d16, d5 \n\t" // d3 = 16-x - - "vmul.i16 d4, d7, d5 \n\t" // d4 = a01 * x - "vmla.i16 d4, d1, d5 \n\t" // d4 += a11 * x - "vmla.i16 d4, d6, d3 \n\t" // d4 += a00 * (16-x) - "vmla.i16 d4, d0, d3 \n\t" // d4 += a10 * (16-x) - "vshrn.i16 d0, q2, #8 \n\t" // shift down result by 8 - "vst1.32 {d0[0]}, [%[dst]] \n\t" // store result - : - : [x] "r" (x), [y] "r" (y), [a00] "r" (a00), [a01] "r" (a01), [a10] "r" (a10), [a11] "r" (a11), [dst] "r" (dst) - : "cc", "memory", "r4", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16" - ); -} - -static inline void Filter_32_alpha_neon(unsigned x, unsigned y, - SkPMColor a00, SkPMColor a01, - SkPMColor a10, SkPMColor a11, - SkPMColor *dst, uint16_t scale) { - asm volatile( - "vdup.8 d0, %[y] \n\t" // duplicate y into d0 - "vmov.u8 d16, #16 \n\t" // set up constant in d16 - "vsub.u8 d1, d16, d0 \n\t" // d1 = 16-y - - "vdup.32 d4, %[a00] \n\t" // duplicate a00 into d4 - "vdup.32 d5, %[a10] \n\t" // duplicate a10 into d5 - "vmov.32 d4[1], %[a01] \n\t" // set top of d4 to a01 - "vmov.32 d5[1], %[a11] \n\t" // set top of d5 to a11 - - "vmull.u8 q3, d4, d1 \n\t" // q3 = [a01|a00] * (16-y) - "vmull.u8 q0, d5, d0 \n\t" // q0 = [a11|a10] * y - - "vdup.16 d5, %[x] \n\t" // duplicate x into d5 - "vmov.u16 d16, #16 \n\t" // set up constant in d16 - "vsub.u16 d3, d16, d5 \n\t" // d3 = 16-x - - "vmul.i16 d4, d7, d5 \n\t" // d4 = a01 * x - "vmla.i16 d4, d1, d5 \n\t" // d4 += a11 * x - "vmla.i16 d4, d6, d3 \n\t" // d4 += a00 * (16-x) - "vmla.i16 d4, d0, d3 \n\t" // d4 += a10 * (16-x) - "vdup.16 d3, %[scale] \n\t" // duplicate scale into d3 - "vshr.u16 d4, d4, #8 \n\t" // shift down result by 8 - "vmul.i16 d4, d4, d3 \n\t" // multiply result by scale - "vshrn.i16 d0, q2, #8 \n\t" // shift down result by 8 - "vst1.32 {d0[0]}, [%[dst]] \n\t" // store result - : - : [x] "r" (x), [y] "r" (y), [a00] "r" (a00), [a01] "r" (a01), [a10] "r" (a10), [a11] "r" (a11), [dst] "r" (dst), [scale] "r" (scale) - : "cc", "memory", "r4", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16" - ); -} diff --git a/gfx/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp b/gfx/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp deleted file mode 100644 index 7d75143e20bd..000000000000 --- a/gfx/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp +++ /dev/null @@ -1,144 +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. - */ - -#include "SkBitmapProcState.h" -#include "SkPerspIter.h" -#include "SkShader.h" -#include "SkUtilsArm.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); - -static unsigned SK_USHIFT16(unsigned x) { - return x >> 16; -} - -#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) -#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" - - -void decal_nofilter_scale_neon(uint32_t dst[], SkFixed fx, SkFixed dx, int count) -{ - int i; - - 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; - uint16_t *dst16 = (uint16_t *)dst; - - fx1 = fx+dx; - fx2 = fx1+dx; - fx3 = fx2+dx; - - /* avoid an '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)); - - /* take upper 16 of each, store, and bump everything */ - do { - int32x4_t lout, hout; - uint16x8_t hi16; - - lout = lbase; - hout = hbase; - /* gets hi's of all louts then hi's of all houts */ - asm ("vuzpq.16 %q0, %q1" : "+w" (lout), "+w" (hout)); - hi16 = vreinterpretq_u16_s32(hout); - vst1q_u16(dst16, hi16); - - /* 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); - dst = (uint32_t *) dst16; - } - - uint16_t* xx = (uint16_t*)dst; - for (i = count; i > 0; --i) { - *xx++ = SkToU16(fx >> 16); fx += dx; - } -} - -void decal_filter_scale_neon(uint32_t dst[], SkFixed fx, SkFixed dx, int count) -{ - if (count >= 8) { - int32x4_t wide_fx; - int32x4_t wide_fx2; - int32x4_t wide_dx8 = vdupq_n_s32(dx*8); - - 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_fx2 = vaddq_s32(wide_fx, vdupq_n_s32(dx+dx+dx+dx)); - - while (count >= 8) { - int32x4_t wide_out; - int32x4_t wide_out2; - - wide_out = vshlq_n_s32(vshrq_n_s32(wide_fx, 12), 14); - wide_out = vorrq_s32(wide_out, - vaddq_s32(vshrq_n_s32(wide_fx,16), vdupq_n_s32(1))); - - wide_out2 = vshlq_n_s32(vshrq_n_s32(wide_fx2, 12), 14); - wide_out2 = vorrq_s32(wide_out2, - vaddq_s32(vshrq_n_s32(wide_fx2,16), vdupq_n_s32(1))); - - vst1q_u32(dst, vreinterpretq_u32_s32(wide_out)); - vst1q_u32(dst+4, vreinterpretq_u32_s32(wide_out2)); - - dst += 8; - fx += dx*8; - wide_fx = vaddq_s32(wide_fx, wide_dx8); - wide_fx2 = vaddq_s32(wide_fx2, wide_dx8); - count -= 8; - } - } - - if (count & 1) - { - SkASSERT((fx >> (16 + 14)) == 0); - *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1); - fx += dx; - } - while ((count -= 2) >= 0) - { - SkASSERT((fx >> (16 + 14)) == 0); - *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1); - fx += dx; - - *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1); - fx += dx; - } -} diff --git a/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp b/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp deleted file mode 100644 index e044ad812947..000000000000 --- a/gfx/skia/src/opts/SkBitmapProcState_opts_arm.cpp +++ /dev/null @@ -1,220 +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.h" -#include "SkColorPriv.h" -#include "SkTypes.h" -#include "SkUtils.h" - -#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN) -void SI8_D16_nofilter_DX_arm( - const SkBitmapProcState& s, - const uint32_t* SK_RESTRICT xy, - int count, - uint16_t* SK_RESTRICT colors) SK_ATTRIBUTE_OPTIMIZE_O1; - -void SI8_D16_nofilter_DX_arm(const SkBitmapProcState& s, - const uint32_t* SK_RESTRICT xy, - int count, uint16_t* SK_RESTRICT colors) { - SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); - SkASSERT(s.fDoFilter == false); - - const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->lock16BitCache(); - const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels(); - - // buffer is y32, x16, x16, x16, x16, x16 - // bump srcAddr to the proper row, since we're told Y never changes - SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height()); - srcAddr = (const uint8_t*)((const char*)srcAddr + - xy[0] * s.fBitmap->rowBytes()); - - uint8_t src; - - if (1 == s.fBitmap->width()) { - src = srcAddr[0]; - uint16_t dstValue = table[src]; - sk_memset16(colors, dstValue, count); - } else { - int i; - int count8 = count >> 3; - const uint16_t* SK_RESTRICT xx = (const uint16_t*)(xy + 1); - - asm volatile ( - "cmp %[count8], #0 \n\t" // compare loop counter with 0 - "beq 2f \n\t" // if loop counter == 0, exit - "1: \n\t" - "ldmia %[xx]!, {r5, r7, r9, r11} \n\t" // load ptrs to pixels 0-7 - "subs %[count8], %[count8], #1 \n\t" // decrement loop counter - "uxth r4, r5 \n\t" // extract ptr 0 - "mov r5, r5, lsr #16 \n\t" // extract ptr 1 - "uxth r6, r7 \n\t" // extract ptr 2 - "mov r7, r7, lsr #16 \n\t" // extract ptr 3 - "ldrb r4, [%[srcAddr], r4] \n\t" // load pixel 0 from image - "uxth r8, r9 \n\t" // extract ptr 4 - "ldrb r5, [%[srcAddr], r5] \n\t" // load pixel 1 from image - "mov r9, r9, lsr #16 \n\t" // extract ptr 5 - "ldrb r6, [%[srcAddr], r6] \n\t" // load pixel 2 from image - "uxth r10, r11 \n\t" // extract ptr 6 - "ldrb r7, [%[srcAddr], r7] \n\t" // load pixel 3 from image - "mov r11, r11, lsr #16 \n\t" // extract ptr 7 - "ldrb r8, [%[srcAddr], r8] \n\t" // load pixel 4 from image - "add r4, r4, r4 \n\t" // double pixel 0 for RGB565 lookup - "ldrb r9, [%[srcAddr], r9] \n\t" // load pixel 5 from image - "add r5, r5, r5 \n\t" // double pixel 1 for RGB565 lookup - "ldrb r10, [%[srcAddr], r10] \n\t" // load pixel 6 from image - "add r6, r6, r6 \n\t" // double pixel 2 for RGB565 lookup - "ldrb r11, [%[srcAddr], r11] \n\t" // load pixel 7 from image - "add r7, r7, r7 \n\t" // double pixel 3 for RGB565 lookup - "ldrh r4, [%[table], r4] \n\t" // load pixel 0 RGB565 from colmap - "add r8, r8, r8 \n\t" // double pixel 4 for RGB565 lookup - "ldrh r5, [%[table], r5] \n\t" // load pixel 1 RGB565 from colmap - "add r9, r9, r9 \n\t" // double pixel 5 for RGB565 lookup - "ldrh r6, [%[table], r6] \n\t" // load pixel 2 RGB565 from colmap - "add r10, r10, r10 \n\t" // double pixel 6 for RGB565 lookup - "ldrh r7, [%[table], r7] \n\t" // load pixel 3 RGB565 from colmap - "add r11, r11, r11 \n\t" // double pixel 7 for RGB565 lookup - "ldrh r8, [%[table], r8] \n\t" // load pixel 4 RGB565 from colmap - "ldrh r9, [%[table], r9] \n\t" // load pixel 5 RGB565 from colmap - "ldrh r10, [%[table], r10] \n\t" // load pixel 6 RGB565 from colmap - "ldrh r11, [%[table], r11] \n\t" // load pixel 7 RGB565 from colmap - "pkhbt r5, r4, r5, lsl #16 \n\t" // pack pixels 0 and 1 - "pkhbt r6, r6, r7, lsl #16 \n\t" // pack pixels 2 and 3 - "pkhbt r8, r8, r9, lsl #16 \n\t" // pack pixels 4 and 5 - "pkhbt r10, r10, r11, lsl #16 \n\t" // pack pixels 6 and 7 - "stmia %[colors]!, {r5, r6, r8, r10} \n\t" // store last 8 pixels - "bgt 1b \n\t" // loop if counter > 0 - "2: \n\t" - : [xx] "+r" (xx), [count8] "+r" (count8), [colors] "+r" (colors) - : [table] "r" (table), [srcAddr] "r" (srcAddr) - : "memory", "cc", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" - ); - - for (i = (count & 7); i > 0; --i) { - src = srcAddr[*xx++]; *colors++ = table[src]; - } - } - - s.fBitmap->getColorTable()->unlock16BitCache(); -} - -void SI8_opaque_D32_nofilter_DX_arm( - const SkBitmapProcState& s, - const uint32_t* SK_RESTRICT xy, - int count, - SkPMColor* SK_RESTRICT colors) SK_ATTRIBUTE_OPTIMIZE_O1; - -void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s, - const uint32_t* SK_RESTRICT xy, - int count, SkPMColor* SK_RESTRICT colors) { - SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); - SkASSERT(s.fDoFilter == false); - - const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->lockColors(); - const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels(); - - // buffer is y32, x16, x16, x16, x16, x16 - // bump srcAddr to the proper row, since we're told Y never changes - SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height()); - srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes()); - - if (1 == s.fBitmap->width()) { - uint8_t src = srcAddr[0]; - SkPMColor dstValue = table[src]; - sk_memset32(colors, dstValue, count); - } else { - const uint16_t* xx = (const uint16_t*)(xy + 1); - - asm volatile ( - "subs %[count], %[count], #8 \n\t" // decrement count by 8, set flags - "blt 2f \n\t" // if count < 0, branch to singles - "1: \n\t" // eights loop - "ldmia %[xx]!, {r5, r7, r9, r11} \n\t" // load ptrs to pixels 0-7 - "uxth r4, r5 \n\t" // extract ptr 0 - "mov r5, r5, lsr #16 \n\t" // extract ptr 1 - "uxth r6, r7 \n\t" // extract ptr 2 - "mov r7, r7, lsr #16 \n\t" // extract ptr 3 - "ldrb r4, [%[srcAddr], r4] \n\t" // load pixel 0 from image - "uxth r8, r9 \n\t" // extract ptr 4 - "ldrb r5, [%[srcAddr], r5] \n\t" // load pixel 1 from image - "mov r9, r9, lsr #16 \n\t" // extract ptr 5 - "ldrb r6, [%[srcAddr], r6] \n\t" // load pixel 2 from image - "uxth r10, r11 \n\t" // extract ptr 6 - "ldrb r7, [%[srcAddr], r7] \n\t" // load pixel 3 from image - "mov r11, r11, lsr #16 \n\t" // extract ptr 7 - "ldrb r8, [%[srcAddr], r8] \n\t" // load pixel 4 from image - "ldrb r9, [%[srcAddr], r9] \n\t" // load pixel 5 from image - "ldrb r10, [%[srcAddr], r10] \n\t" // load pixel 6 from image - "ldrb r11, [%[srcAddr], r11] \n\t" // load pixel 7 from image - "ldr r4, [%[table], r4, lsl #2] \n\t" // load pixel 0 SkPMColor from colmap - "ldr r5, [%[table], r5, lsl #2] \n\t" // load pixel 1 SkPMColor from colmap - "ldr r6, [%[table], r6, lsl #2] \n\t" // load pixel 2 SkPMColor from colmap - "ldr r7, [%[table], r7, lsl #2] \n\t" // load pixel 3 SkPMColor from colmap - "ldr r8, [%[table], r8, lsl #2] \n\t" // load pixel 4 SkPMColor from colmap - "ldr r9, [%[table], r9, lsl #2] \n\t" // load pixel 5 SkPMColor from colmap - "ldr r10, [%[table], r10, lsl #2] \n\t" // load pixel 6 SkPMColor from colmap - "ldr r11, [%[table], r11, lsl #2] \n\t" // load pixel 7 SkPMColor from colmap - "subs %[count], %[count], #8 \n\t" // decrement loop counter - "stmia %[colors]!, {r4-r11} \n\t" // store 8 pixels - "bge 1b \n\t" // loop if counter >= 0 - "2: \n\t" - "adds %[count], %[count], #8 \n\t" // fix up counter, set flags - "beq 4f \n\t" // if count == 0, branch to exit - "3: \n\t" // singles loop - "ldrh r4, [%[xx]], #2 \n\t" // load pixel ptr - "subs %[count], %[count], #1 \n\t" // decrement loop counter - "ldrb r5, [%[srcAddr], r4] \n\t" // load pixel from image - "ldr r6, [%[table], r5, lsl #2] \n\t" // load SkPMColor from colmap - "str r6, [%[colors]], #4 \n\t" // store pixel, update ptr - "bne 3b \n\t" // loop if counter != 0 - "4: \n\t" // exit - : [xx] "+r" (xx), [count] "+r" (count), [colors] "+r" (colors) - : [table] "r" (table), [srcAddr] "r" (srcAddr) - : "memory", "cc", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" - ); - } - - s.fBitmap->getColorTable()->unlockColors(false); -} -#endif // SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN) - -/////////////////////////////////////////////////////////////////////////////// - -/* If we replace a sampleproc, then we null-out the associated shaderproc, - otherwise the shader won't even look at the matrix/sampler - */ -void SkBitmapProcState::platformProcs() { - bool doFilter = fDoFilter; - bool isOpaque = 256 == fAlphaScale; - bool justDx = false; - - if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { - justDx = true; - } - - switch (fBitmap->config()) { - case SkBitmap::kIndex8_Config: -#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN) - if (justDx && !doFilter) { -#if 0 /* crashing on android device */ - fSampleProc16 = SI8_D16_nofilter_DX_arm; - fShaderProc16 = NULL; -#endif - if (isOpaque) { - // this one is only very slighty faster than the C version - fSampleProc32 = SI8_opaque_D32_nofilter_DX_arm; - fShaderProc32 = NULL; - } - } -#endif - break; - default: - break; - } -} diff --git a/gfx/skia/src/opts/SkBlitRow_opts_arm.h b/gfx/skia/src/opts/SkBlitRow_opts_arm.h deleted file mode 100644 index d929814be3c9..000000000000 --- a/gfx/skia/src/opts/SkBlitRow_opts_arm.h +++ /dev/null @@ -1,41 +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 SkBlitRow_opts_arm_DEFINED -#define SkBlitRow_opts_arm_DEFINED - -#include "SkBlitRow.h" -#include "SkUtilsArm.h" - -// Define USE_NEON_CODE to indicate that we need to build NEON routines -#define USE_NEON_CODE (!SK_ARM_NEON_IS_NONE) - -// Define USE_ARM_CODE to indicate that we need to build ARM routines -#define USE_ARM_CODE (!SK_ARM_NEON_IS_ALWAYS) - -#if USE_NEON_CODE -// These are defined in SkBlitRow_opts_arm_neon.cpp -extern const SkBlitRow::Proc sk_blitrow_platform_565_procs_arm_neon[]; -extern const SkBlitRow::Proc sk_blitrow_platform_4444_procs_arm_neon[]; -extern const SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm_neon[]; - -extern void Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count, - SkPMColor color); -#endif - -#if USE_ARM_CODE -// These are defined in SkBlitRow_opts_arm.cpp -extern const SkBlitRow::Proc sk_blitrow_platform_565_procs_arm[]; -extern const SkBlitRow::Proc sk_blitrow_platform_4444_procs_arm[]; -extern const SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm[]; -#endif - -// Defined in SkBlitRow_opts_arm.cpp, used in all cases. -extern void S32A_Blend_BlitRow32_arm(SkPMColor* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, - int count, U8CPU alpha); - -#endif diff --git a/gfx/skia/src/opts/SkBlitRow_opts_none.cpp b/gfx/skia/src/opts/SkBlitRow_opts_none.cpp deleted file mode 100644 index 88e1af398cef..000000000000 --- a/gfx/skia/src/opts/SkBlitRow_opts_none.cpp +++ /dev/null @@ -1,45 +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 "SkBlitRow.h" -#include "SkBlitMask.h" - -// Platform impl of Platform_procs with no overrides - -SkBlitRow::Proc SkBlitRow::PlatformProcs4444(unsigned flags) { - return NULL; -} - -SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) { - return NULL; -} - -SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) { - return NULL; -} - -SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() { - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig, - SkMask::Format maskFormat, - SkColor color) { - return NULL; -} - -SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) { - return NULL; -} - -SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig, - SkMask::Format maskFormat, - RowFlags flags) { - return NULL; -} diff --git a/gfx/skia/src/pdf/SkPDFImage.cpp b/gfx/skia/src/pdf/SkPDFImage.cpp deleted file mode 100644 index f7889f16d7b4..000000000000 --- a/gfx/skia/src/pdf/SkPDFImage.cpp +++ /dev/null @@ -1,349 +0,0 @@ - -/* - * 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. - */ - - -#include "SkPDFImage.h" - -#include "SkBitmap.h" -#include "SkColor.h" -#include "SkColorPriv.h" -#include "SkPackBits.h" -#include "SkPDFCatalog.h" -#include "SkRect.h" -#include "SkStream.h" -#include "SkString.h" -#include "SkUnPreMultiply.h" - -namespace { - -void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect, - SkStream** imageData, SkStream** alphaData) { - SkMemoryStream* image = NULL; - SkMemoryStream* alpha = NULL; - bool hasAlpha = false; - bool isTransparent = false; - - bitmap.lockPixels(); - switch (bitmap.getConfig()) { - case SkBitmap::kIndex8_Config: { - const int rowBytes = srcRect.width(); - image = new SkMemoryStream(rowBytes * srcRect.height()); - uint8_t* dst = (uint8_t*)image->getMemoryBase(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes); - dst += rowBytes; - } - break; - } - case SkBitmap::kRLE_Index8_Config: { - const int rowBytes = srcRect.width(); - image = new SkMemoryStream(rowBytes * srcRect.height()); - uint8_t* dst = (uint8_t*)image->getMemoryBase(); - const SkBitmap::RLEPixels* rle = - (const SkBitmap::RLEPixels*)bitmap.getPixels(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - SkPackBits::Unpack8(dst, srcRect.fLeft, rowBytes, - rle->packedAtY(y)); - dst += rowBytes; - } - break; - } - case SkBitmap::kARGB_4444_Config: { - isTransparent = true; - const int rowBytes = (srcRect.width() * 3 + 1) / 2; - const int alphaRowBytes = (srcRect.width() + 1) / 2; - image = new SkMemoryStream(rowBytes * srcRect.height()); - alpha = new SkMemoryStream(alphaRowBytes * srcRect.height()); - uint8_t* dst = (uint8_t*)image->getMemoryBase(); - uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - uint16_t* src = bitmap.getAddr16(0, y); - int x; - for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) { - dst[0] = (SkGetPackedR4444(src[x]) << 4) | - SkGetPackedG4444(src[x]); - dst[1] = (SkGetPackedB4444(src[x]) << 4) | - SkGetPackedR4444(src[x + 1]); - dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) | - SkGetPackedB4444(src[x + 1]); - dst += 3; - alphaDst[0] = (SkGetPackedA4444(src[x]) << 4) | - SkGetPackedA4444(src[x + 1]); - if (alphaDst[0] != 0xFF) { - hasAlpha = true; - } - if (alphaDst[0]) { - isTransparent = false; - } - alphaDst++; - } - if (srcRect.width() & 1) { - dst[0] = (SkGetPackedR4444(src[x]) << 4) | - SkGetPackedG4444(src[x]); - dst[1] = (SkGetPackedB4444(src[x]) << 4); - dst += 2; - alphaDst[0] = (SkGetPackedA4444(src[x]) << 4); - if (alphaDst[0] != 0xF0) { - hasAlpha = true; - } - if (alphaDst[0] & 0xF0) { - isTransparent = false; - } - alphaDst++; - } - } - break; - } - case SkBitmap::kRGB_565_Config: { - const int rowBytes = srcRect.width() * 3; - image = new SkMemoryStream(rowBytes * srcRect.height()); - uint8_t* dst = (uint8_t*)image->getMemoryBase(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - uint16_t* src = bitmap.getAddr16(0, y); - for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { - dst[0] = SkGetPackedR16(src[x]); - dst[1] = SkGetPackedG16(src[x]); - dst[2] = SkGetPackedB16(src[x]); - dst += 3; - } - } - break; - } - case SkBitmap::kARGB_8888_Config: { - isTransparent = true; - const int rowBytes = srcRect.width() * 3; - image = new SkMemoryStream(rowBytes * srcRect.height()); - alpha = new SkMemoryStream(srcRect.width() * srcRect.height()); - uint8_t* dst = (uint8_t*)image->getMemoryBase(); - uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - uint32_t* src = bitmap.getAddr32(0, y); - for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { - dst[0] = SkGetPackedR32(src[x]); - dst[1] = SkGetPackedG32(src[x]); - dst[2] = SkGetPackedB32(src[x]); - dst += 3; - alphaDst[0] = SkGetPackedA32(src[x]); - if (alphaDst[0] != 0xFF) { - hasAlpha = true; - } - if (alphaDst[0]) { - isTransparent = false; - } - alphaDst++; - } - } - break; - } - case SkBitmap::kA1_Config: { - isTransparent = true; - image = new SkMemoryStream(1); - ((uint8_t*)image->getMemoryBase())[0] = 0; - - const int alphaRowBytes = (srcRect.width() + 7) / 8; - alpha = new SkMemoryStream(alphaRowBytes * srcRect.height()); - uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); - int offset1 = srcRect.fLeft % 8; - int offset2 = 8 - offset1; - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - uint8_t* src = bitmap.getAddr1(0, y); - // This may read up to one byte after src, but the potentially - // invalid bits are never used for computation. - for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) { - if (offset1) { - alphaDst[0] = src[x / 8] << offset1 | - src[x / 8 + 1] >> offset2; - } else { - alphaDst[0] = src[x / 8]; - } - if (x + 7 < srcRect.fRight && alphaDst[0] != 0xFF) { - hasAlpha = true; - } - if (x + 7 < srcRect.fRight && alphaDst[0]) { - isTransparent = false; - } - alphaDst++; - } - // Calculate the mask of bits we're interested in within the - // last byte of alphaDst. - // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE - uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1); - if (srcRect.width() % 8 && (alphaDst[-1] & mask) != mask) { - hasAlpha = true; - } - if (srcRect.width() % 8 && (alphaDst[-1] & mask)) { - isTransparent = false; - } - } - break; - } - case SkBitmap::kA8_Config: { - isTransparent = true; - image = new SkMemoryStream(1); - ((uint8_t*)image->getMemoryBase())[0] = 0; - - const int alphaRowBytes = srcRect.width(); - alpha = new SkMemoryStream(alphaRowBytes * srcRect.height()); - uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); - for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { - uint8_t* src = bitmap.getAddr8(0, y); - for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { - alphaDst[0] = src[x]; - if (alphaDst[0] != 0xFF) { - hasAlpha = true; - } - if (alphaDst[0]) { - isTransparent = false; - } - alphaDst++; - } - } - break; - } - default: - SkASSERT(false); - } - bitmap.unlockPixels(); - - if (isTransparent) { - SkSafeUnref(image); - } else { - *imageData = image; - } - - if (isTransparent || !hasAlpha) { - SkSafeUnref(alpha); - } else { - *alphaData = alpha; - } -} - -SkPDFArray* makeIndexedColorSpace(SkColorTable* table) { - SkPDFArray* result = new SkPDFArray(); - result->reserve(4); - result->appendName("Indexed"); - result->appendName("DeviceRGB"); - result->appendInt(table->count() - 1); - - // Potentially, this could be represented in fewer bytes with a stream. - // Max size as a string is 1.5k. - SkString index; - for (int i = 0; i < table->count(); i++) { - char buf[3]; - SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]); - buf[0] = SkGetPackedR32(color); - buf[1] = SkGetPackedG32(color); - buf[2] = SkGetPackedB32(color); - index.append(buf, 3); - } - result->append(new SkPDFString(index))->unref(); - return result; -} - -}; // namespace - -// static -SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, - const SkIRect& srcRect) { - if (bitmap.getConfig() == SkBitmap::kNo_Config) { - return NULL; - } - - SkStream* imageData = NULL; - SkStream* alphaData = NULL; - extractImageData(bitmap, srcRect, &imageData, &alphaData); - SkAutoUnref unrefImageData(imageData); - SkAutoUnref unrefAlphaData(alphaData); - if (!imageData) { - SkASSERT(!alphaData); - return NULL; - } - - SkPDFImage* image = - new SkPDFImage(imageData, bitmap, srcRect, false); - - if (alphaData != NULL) { - image->addSMask(new SkPDFImage(alphaData, bitmap, srcRect, true))->unref(); - } - return image; -} - -SkPDFImage::~SkPDFImage() { - fResources.unrefAll(); -} - -SkPDFImage* SkPDFImage::addSMask(SkPDFImage* mask) { - fResources.push(mask); - mask->ref(); - insert("SMask", new SkPDFObjRef(mask))->unref(); - return mask; -} - -void SkPDFImage::getResources(const SkTSet& knownResourceObjects, - SkTSet* newResourceObjects) { - GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects); -} - -SkPDFImage::SkPDFImage(SkStream* imageData, const SkBitmap& bitmap, - const SkIRect& srcRect, bool doingAlpha) { - this->setData(imageData); - SkBitmap::Config config = bitmap.getConfig(); - bool alphaOnly = (config == SkBitmap::kA1_Config || - config == SkBitmap::kA8_Config); - - insertName("Type", "XObject"); - insertName("Subtype", "Image"); - - if (!doingAlpha && alphaOnly) { - // For alpha only images, we stretch a single pixel of black for - // the color/shape part. - SkAutoTUnref one(new SkPDFInt(1)); - insert("Width", one.get()); - insert("Height", one.get()); - } else { - insertInt("Width", srcRect.width()); - insertInt("Height", srcRect.height()); - } - - // if (!image mask) { - if (doingAlpha || alphaOnly) { - insertName("ColorSpace", "DeviceGray"); - } else if (config == SkBitmap::kIndex8_Config || - config == SkBitmap::kRLE_Index8_Config) { - insert("ColorSpace", - makeIndexedColorSpace(bitmap.getColorTable()))->unref(); - } else { - insertName("ColorSpace", "DeviceRGB"); - } - // } - - int bitsPerComp = 8; - if (config == SkBitmap::kARGB_4444_Config) { - bitsPerComp = 4; - } else if (doingAlpha && config == SkBitmap::kA1_Config) { - bitsPerComp = 1; - } - insertInt("BitsPerComponent", bitsPerComp); - - if (config == SkBitmap::kRGB_565_Config) { - SkAutoTUnref zeroVal(new SkPDFInt(0)); - SkAutoTUnref scale5Val( - new SkPDFScalar(SkFloatToScalar(8.2258f))); // 255/2^5-1 - SkAutoTUnref scale6Val( - new SkPDFScalar(SkFloatToScalar(4.0476f))); // 255/2^6-1 - SkAutoTUnref decodeValue(new SkPDFArray()); - decodeValue->reserve(6); - decodeValue->append(zeroVal.get()); - decodeValue->append(scale5Val.get()); - decodeValue->append(zeroVal.get()); - decodeValue->append(scale6Val.get()); - decodeValue->append(zeroVal.get()); - decodeValue->append(scale5Val.get()); - insert("Decode", decodeValue.get()); - } -} diff --git a/gfx/skia/src/pdf/SkTSet.h b/gfx/skia/src/pdf/SkTSet.h deleted file mode 100644 index acf45a296baf..000000000000 --- a/gfx/skia/src/pdf/SkTSet.h +++ /dev/null @@ -1,280 +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 SkTSet_DEFINED -#define SkTSet_DEFINED - -#include "SkTDArray.h" -#include "SkTypes.h" - -/** \class SkTSet - - The SkTSet template class defines a set. - Main operations supported now are: add, merge, find and contains. - - TSet is mutable. -*/ - -// TODO: Add remove, intersect and difference operations. -// TODO: Add bench tests. -template class SK_API SkTSet { -public: - SkTSet() { - fArray = SkNEW(SkTDArray); - } - - ~SkTSet() { - SkASSERT(fArray); - SkDELETE(fArray); - } - - SkTSet(const SkTSet& src) { - this->fArray = SkNEW_ARGS(SkTDArray, (*src.fArray)); -#ifdef SK_DEBUG - validate(); -#endif - } - - SkTSet& operator=(const SkTSet& src) { - *this->fArray = *src.fArray; -#ifdef SK_DEBUG - validate(); -#endif - return *this; - } - - /** Merges src elements into this, and returns the number of duplicates - * found. - */ - int mergeInto(const SkTSet& src) { - SkASSERT(fArray); - int duplicates = 0; - - SkTDArray* fArrayNew = new SkTDArray(); - fArrayNew->setReserve(count() + src.count()); - int i = 0; - int j = 0; - - while (i < count() && j < src.count()) { - if ((*fArray)[i] < (*src.fArray)[j]) { - fArrayNew->push((*fArray)[i]); - i++; - } else if ((*fArray)[i] > (*src.fArray)[j]) { - fArrayNew->push((*src.fArray)[j]); - j++; - } else { - duplicates++; - j++; // Skip one of the duplicates. - } - } - - while (i < count()) { - fArrayNew->push((*fArray)[i]); - i++; - } - - while (j < src.count()) { - fArrayNew->push((*src.fArray)[j]); - j++; - } - SkDELETE(fArray); - fArray = fArrayNew; - fArrayNew = NULL; - -#ifdef SK_DEBUG - validate(); -#endif - return duplicates; - } - - /** Adds a new element into set and returns true if the element is already - * in this set. - */ - bool add(const T& elem) { - SkASSERT(fArray); - - int pos = 0; - int i = find(elem, &pos); - if (i >= 0) { - return false; - } - *fArray->insert(pos) = elem; -#ifdef SK_DEBUG - validate(); -#endif - return true; - } - - /** Returns true if this set is empty. - */ - bool isEmpty() const { - SkASSERT(fArray); - return fArray->isEmpty(); - } - - /** Return the number of elements in the set. - */ - int count() const { - SkASSERT(fArray); - return fArray->count(); - } - - /** Return the number of bytes in the set: count * sizeof(T). - */ - size_t bytes() const { - SkASSERT(fArray); - return fArray->bytes(); - } - - /** Return the beginning of a set iterator. - * Elements in the iterator will be sorted ascending. - */ - const T* begin() const { - SkASSERT(fArray); - return fArray->begin(); - } - - /** Return the end of a set iterator. - */ - const T* end() const { - SkASSERT(fArray); - return fArray->end(); - } - - const T& operator[](int index) const { - SkASSERT(fArray); - return (*fArray)[index]; - } - - /** Resets the set (deletes memory and initiates an empty set). - */ - void reset() { - SkASSERT(fArray); - fArray->reset(); - } - - /** Rewinds the set (preserves memory and initiates an empty set). - */ - void rewind() { - SkASSERT(fArray); - fArray->rewind(); - } - - /** Reserves memory for the set. - */ - void setReserve(size_t reserve) { - SkASSERT(fArray); - fArray->setReserve(reserve); - } - - /** Returns the index where an element was found. - * Returns -1 if the element was not found, and it fills *posToInsertSorted - * with the index of the place where elem should be inserted to preserve the - * internal array sorted. - * If element was found, *posToInsertSorted is undefined. - */ - int find(const T& elem, int* posToInsertSorted = NULL) const { - SkASSERT(fArray); - - if (fArray->count() == 0) { - if (posToInsertSorted) { - *posToInsertSorted = 0; - } - return -1; - } - int iMin = 0; - int iMax = fArray->count(); - - while (iMin < iMax - 1) { - int iMid = (iMin + iMax) / 2; - if (elem < (*fArray)[iMid]) { - iMax = iMid; - } else { - iMin = iMid; - } - } - if (elem == (*fArray)[iMin]) { - return iMin; - } - if (posToInsertSorted) { - if (elem < (*fArray)[iMin]) { - *posToInsertSorted = iMin; - } else { - *posToInsertSorted = iMin + 1; - } - } - - return -1; - } - - /** Returns true if the array contains this element. - */ - bool contains(const T& elem) const { - SkASSERT(fArray); - return (this->find(elem) >= 0); - } - - /** Copies internal array to destination. - */ - void copy(T* dst) const { - SkASSERT(fArray); - fArray->copyRange(0, fArray->count(), dst); - } - - /** Returns a const reference to the internal vector. - */ - const SkTDArray& toArray() { - SkASSERT(fArray); - return *fArray; - } - - /** Unref all elements in the set. - */ - void unrefAll() { - SkASSERT(fArray); - fArray->unrefAll(); - } - - /** safeUnref all elements in the set. - */ - void safeUnrefAll() { - SkASSERT(fArray); - fArray->safeUnrefAll(); - } - -#ifdef SK_DEBUG - void validate() const { - SkASSERT(fArray); - fArray->validate(); - SkASSERT(isSorted() && !hasDuplicates()); - } - - bool hasDuplicates() const { - for (int i = 0; i < fArray->count() - 1; ++i) { - if ((*fArray)[i] == (*fArray)[i + 1]) { - return true; - } - } - return false; - } - - bool isSorted() const { - for (int i = 0; i < fArray->count() - 1; ++i) { - // Use only < operator - if (!((*fArray)[i] < (*fArray)[i + 1])) { - return false; - } - } - return true; - } -#endif - -private: - SkTDArray* fArray; -}; - -#endif diff --git a/gfx/skia/src/ports/FontHostConfiguration_android.h b/gfx/skia/src/ports/FontHostConfiguration_android.h deleted file mode 100644 index 71eed579136e..000000000000 --- a/gfx/skia/src/ports/FontHostConfiguration_android.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2011 The Android Open Source Project - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef FONTHOSTCONFIGURATION_ANDROID_H_ -#define FONTHOSTCONFIGURATION_ANDROID_H_ - -#include "SkTDArray.h" - -/** - * The FontFamily data structure is created during parsing and handed back to - * Skia to fold into its representation of font families. fNames is the list of - * font names that alias to a font family. fFileNames is the list of font - * filenames for the family. Order is the priority order for the font. This is - * used internally to determine the order in which to place fallback fonts as - * they are read from the configuration files. - */ -struct FontFamily { - SkTDArray fNames; - SkTDArray fFileNames; - int order; -}; - -/** - * Parses all system font configuration files and returns the results in an - * array of FontFamily structures. - */ -void getFontFamilies(SkTDArray &fontFamilies); - -/** - * Parse the fallback and vendor system font configuration files and return the - * results in an array of FontFamily structures. - */ -void getFallbackFontFamilies(SkTDArray &fallbackFonts); - -/** - * Parses all test font configuration files and returns the results in an - * array of FontFamily structures. - */ -void getTestFontFamilies(SkTDArray &fontFamilies, - const char* testMainConfigFile, - const char* testFallbackConfigFile); - -struct AndroidLocale { - char language[3]; - char region[3]; -}; - -void getLocale(AndroidLocale &locale); - -#endif /* FONTHOSTCONFIGURATION_ANDROID_H_ */ diff --git a/gfx/skia/src/ports/SkDebug_brew.cpp b/gfx/skia/src/ports/SkDebug_brew.cpp deleted file mode 100644 index b7ad3ef27596..000000000000 --- a/gfx/skia/src/ports/SkDebug_brew.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* libs/corecg/SkDebug_brew.cpp - * - * Copyright 2009, The Android Open Source Project - * Copyright 2009, Company 100, Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkTypes.h" - -#ifdef SK_BUILD_FOR_BREW - -static const size_t kBufferSize = 256; - -#include -#include - -void SkDebugf(const char format[], ...) { - char buffer[kBufferSize + 1]; - va_list args; - va_start(args, format); - VSNPRINTF(buffer, kBufferSize, format, args); - va_end(args); - DBGPRINTF(buffer); -} - -#endif SK_BUILD_FOR_BREW diff --git a/gfx/skia/src/ports/SkFontHost_FreeType_common.cpp b/gfx/skia/src/ports/SkFontHost_FreeType_common.cpp deleted file mode 100644 index 2c486847b6d8..000000000000 --- a/gfx/skia/src/ports/SkFontHost_FreeType_common.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2006-2012 The Android Open Source Project - * Copyright 2012 Mozilla Foundation - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkColorPriv.h" -#include "SkFDot6.h" -#include "SkFontHost_FreeType_common.h" -#include "SkPath.h" - -#include -#include FT_OUTLINE_H -#include FT_BITMAP_H -// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. -#include FT_SYNTHESIS_H - -static FT_Pixel_Mode compute_pixel_mode(SkMask::Format format) { - switch (format) { - case SkMask::kBW_Format: - return FT_PIXEL_MODE_MONO; - case SkMask::kA8_Format: - default: - return FT_PIXEL_MODE_GRAY; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static uint16_t packTriple(unsigned r, unsigned g, unsigned b) { - return SkPackRGB16(r >> 3, g >> 2, b >> 3); -} - -static uint16_t grayToRGB16(U8CPU gray) { - SkASSERT(gray <= 255); - return SkPackRGB16(gray >> 3, gray >> 2, gray >> 3); -} - -static int bittst(const uint8_t data[], int bitOffset) { - SkASSERT(bitOffset >= 0); - int lowBit = data[bitOffset >> 3] >> (~bitOffset & 7); - return lowBit & 1; -} - -template -static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap, - int lcdIsBGR, bool lcdIsVert, const uint8_t* tableR, - const uint8_t* tableG, const uint8_t* tableB) { - if (lcdIsVert) { - SkASSERT(3 * glyph.fHeight == bitmap.rows); - } else { - SkASSERT(glyph.fHeight == bitmap.rows); - } - - uint16_t* dst = reinterpret_cast(glyph.fImage); - const size_t dstRB = glyph.rowBytes(); - const int width = glyph.fWidth; - const uint8_t* src = bitmap.buffer; - - switch (bitmap.pixel_mode) { - case FT_PIXEL_MODE_MONO: { - for (int y = 0; y < glyph.fHeight; ++y) { - for (int x = 0; x < width; ++x) { - dst[x] = -bittst(src, x); - } - dst = (uint16_t*)((char*)dst + dstRB); - src += bitmap.pitch; - } - } break; - case FT_PIXEL_MODE_GRAY: { - for (int y = 0; y < glyph.fHeight; ++y) { - for (int x = 0; x < width; ++x) { - dst[x] = grayToRGB16(src[x]); - } - dst = (uint16_t*)((char*)dst + dstRB); - src += bitmap.pitch; - } - } break; - default: { - SkASSERT(lcdIsVert || (glyph.fWidth * 3 == bitmap.width)); - for (int y = 0; y < glyph.fHeight; y++) { - if (lcdIsVert) { // vertical stripes - const uint8_t* srcR = src; - const uint8_t* srcG = srcR + bitmap.pitch; - const uint8_t* srcB = srcG + bitmap.pitch; - if (lcdIsBGR) { - SkTSwap(srcR, srcB); - } - for (int x = 0; x < width; x++) { - dst[x] = packTriple(sk_apply_lut_if(*srcR++, tableR), - sk_apply_lut_if(*srcG++, tableG), - sk_apply_lut_if(*srcB++, tableB)); - } - src += 3 * bitmap.pitch; - } else { // horizontal stripes - const uint8_t* triple = src; - if (lcdIsBGR) { - for (int x = 0; x < width; x++) { - dst[x] = packTriple(sk_apply_lut_if(triple[2], tableR), - sk_apply_lut_if(triple[1], tableG), - sk_apply_lut_if(triple[0], tableB)); - triple += 3; - } - } else { - for (int x = 0; x < width; x++) { - dst[x] = packTriple(sk_apply_lut_if(triple[0], tableR), - sk_apply_lut_if(triple[1], tableG), - sk_apply_lut_if(triple[2], tableB)); - triple += 3; - } - } - src += bitmap.pitch; - } - dst = (uint16_t*)((char*)dst + dstRB); - } - } break; - } -} - -void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGlyph& glyph) { - const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag); - const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); - - switch ( face->glyph->format ) { - case FT_GLYPH_FORMAT_OUTLINE: { - FT_Outline* outline = &face->glyph->outline; - FT_BBox bbox; - FT_Bitmap target; - - if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) { - emboldenOutline(face, outline); - } - - int dx = 0, dy = 0; - if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { - dx = SkFixedToFDot6(glyph.getSubXFixed()); - dy = SkFixedToFDot6(glyph.getSubYFixed()); - // negate dy since freetype-y-goes-up and skia-y-goes-down - dy = -dy; - } - FT_Outline_Get_CBox(outline, &bbox); - /* - what we really want to do for subpixel is - offset(dx, dy) - compute_bounds - offset(bbox & !63) - but that is two calls to offset, so we do the following, which - achieves the same thing with only one offset call. - */ - FT_Outline_Translate(outline, dx - ((bbox.xMin + dx) & ~63), - dy - ((bbox.yMin + dy) & ~63)); - - if (SkMask::kLCD16_Format == glyph.fMaskFormat) { - FT_Render_Glyph(face->glyph, doVert ? FT_RENDER_MODE_LCD_V : FT_RENDER_MODE_LCD); - if (fPreBlend.isApplicable()) { - copyFT2LCD16(glyph, face->glyph->bitmap, doBGR, doVert, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); - } else { - copyFT2LCD16(glyph, face->glyph->bitmap, doBGR, doVert, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); - } - } else { - target.width = glyph.fWidth; - target.rows = glyph.fHeight; - target.pitch = glyph.rowBytes(); - target.buffer = reinterpret_cast(glyph.fImage); - target.pixel_mode = compute_pixel_mode( - (SkMask::Format)fRec.fMaskFormat); - target.num_grays = 256; - - memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); - FT_Outline_Get_Bitmap(face->glyph->library, outline, &target); - } - } break; - - case FT_GLYPH_FORMAT_BITMAP: { - if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) { - FT_GlyphSlot_Own_Bitmap(face->glyph); - FT_Bitmap_Embolden(face->glyph->library, &face->glyph->bitmap, kBitmapEmboldenStrength, 0); - } - SkASSERT_CONTINUE(glyph.fWidth == face->glyph->bitmap.width); - SkASSERT_CONTINUE(glyph.fHeight == face->glyph->bitmap.rows); - SkASSERT_CONTINUE(glyph.fTop == -face->glyph->bitmap_top); - SkASSERT_CONTINUE(glyph.fLeft == face->glyph->bitmap_left); - - const uint8_t* src = (const uint8_t*)face->glyph->bitmap.buffer; - uint8_t* dst = (uint8_t*)glyph.fImage; - - if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY || - (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && - glyph.fMaskFormat == SkMask::kBW_Format)) { - unsigned srcRowBytes = face->glyph->bitmap.pitch; - unsigned dstRowBytes = glyph.rowBytes(); - unsigned minRowBytes = SkMin32(srcRowBytes, dstRowBytes); - unsigned extraRowBytes = dstRowBytes - minRowBytes; - - for (int y = face->glyph->bitmap.rows - 1; y >= 0; --y) { - memcpy(dst, src, minRowBytes); - memset(dst + minRowBytes, 0, extraRowBytes); - src += srcRowBytes; - dst += dstRowBytes; - } - } else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO && - glyph.fMaskFormat == SkMask::kA8_Format) { - for (int y = 0; y < face->glyph->bitmap.rows; ++y) { - uint8_t byte = 0; - int bits = 0; - const uint8_t* src_row = src; - uint8_t* dst_row = dst; - - for (int x = 0; x < face->glyph->bitmap.width; ++x) { - if (!bits) { - byte = *src_row++; - bits = 8; - } - - *dst_row++ = byte & 0x80 ? 0xff : 0; - bits--; - byte <<= 1; - } - - src += face->glyph->bitmap.pitch; - dst += glyph.rowBytes(); - } - } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { - if (fPreBlend.isApplicable()) { - copyFT2LCD16(glyph, face->glyph->bitmap, doBGR, doVert, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); - } else { - copyFT2LCD16(glyph, face->glyph->bitmap, doBGR, doVert, - fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); - } - } else { - SkDEBUGFAIL("unknown glyph bitmap transform needed"); - } - } break; - - default: - SkDEBUGFAIL("unknown glyph format"); - memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); - return; - } - -// We used to always do this pre-USE_COLOR_LUMINANCE, but with colorlum, -// it is optional -#if defined(SK_GAMMA_APPLY_TO_A8) - if (SkMask::kA8_Format == glyph.fMaskFormat && fPreBlend.isApplicable()) { - uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; - unsigned rowBytes = glyph.rowBytes(); - - for (int y = glyph.fHeight - 1; y >= 0; --y) { - for (int x = glyph.fWidth - 1; x >= 0; --x) { - dst[x] = fPreBlend.fG[dst[x]]; - } - dst += rowBytes; - } - } -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -static int move_proc(const FT_Vector* pt, void* ctx) { - SkPath* path = (SkPath*)ctx; - path->close(); // to close the previous contour (if any) - path->moveTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); - return 0; -} - -static int line_proc(const FT_Vector* pt, void* ctx) { - SkPath* path = (SkPath*)ctx; - path->lineTo(SkFDot6ToScalar(pt->x), -SkFDot6ToScalar(pt->y)); - return 0; -} - -static int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1, - void* ctx) { - SkPath* path = (SkPath*)ctx; - path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), - SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y)); - return 0; -} - -static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1, - const FT_Vector* pt2, void* ctx) { - SkPath* path = (SkPath*)ctx; - path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y), - SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y), - SkFDot6ToScalar(pt2->x), -SkFDot6ToScalar(pt2->y)); - return 0; -} - -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; - funcs.line_to = line_proc; - funcs.conic_to = quad_proc; - funcs.cubic_to = cubic_proc; - funcs.shift = 0; - funcs.delta = 0; - - FT_Error err = FT_Outline_Decompose(&face->glyph->outline, &funcs, path); - - if (err != 0) { - path->reset(); - return; - } - - 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/gfx/skia/src/ports/SkFontHost_android.cpp b/gfx/skia/src/ports/SkFontHost_android.cpp deleted file mode 100644 index 37495e7a10e2..000000000000 --- a/gfx/skia/src/ports/SkFontHost_android.cpp +++ /dev/null @@ -1,1075 +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 "SkFontHost.h" -#include "SkFontHost_FreeType_common.h" -#include "SkFontDescriptor.h" -#include "SkGraphics.h" -#include "SkDescriptor.h" -#include "SkPaint.h" -#include "SkString.h" -#include "SkStream.h" -#include "SkThread.h" -#include "SkTSearch.h" -#include "SkTypeface_android.h" -#include "FontHostConfiguration_android.h" - -#ifndef SK_FONT_FILE_PREFIX - #define SK_FONT_FILE_PREFIX "/fonts/" -#endif - -#ifndef SK_DEBUG_FONTS - #define SK_DEBUG_FONTS 0 -#endif - -// For test only. -static const char* gTestMainConfigFile = NULL; -static const char* gTestFallbackConfigFile = NULL; -static const char* gTestFontFilePrefix = NULL; - -bool find_name_and_attributes(SkStream* stream, SkString* name, - SkTypeface::Style* style, bool* isFixedPitch); - -static void GetFullPathForSysFonts(SkString* full, const char name[]) { - if (gTestFontFilePrefix) { - full->set(gTestFontFilePrefix); - } else { - full->set(getenv("ANDROID_ROOT")); - full->append(SK_FONT_FILE_PREFIX); - } - full->append(name); -} - -/////////////////////////////////////////////////////////////////////////////// - -struct FamilyRec; - -/* This guy holds a mapping of a name -> family, used for looking up fonts. - Since it is stored in a stretchy array that doesn't preserve object - semantics, we don't use constructor/destructors, but just have explicit - helpers to manage our internal bookkeeping. -*/ -struct NameFamilyPair { - const char* fName; // we own this - FamilyRec* fFamily; // we don't own this, we just reference it - - void construct(const char name[], FamilyRec* family) { - fName = strdup(name); - fFamily = family; // we don't own this, so just record the referene - } - - void destruct() { - free((char*)fName); - // we don't own family, so just ignore our reference - } -}; -typedef SkTDArray NameFamilyPairList; - -// we use atomic_inc to grow this for each typeface we create -static int32_t gUniqueFontID; - -// this is the mutex that protects gFamilyHead and GetNameList() -SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex); -static FamilyRec* gFamilyHead; - -static NameFamilyPairList& GetNameList() { - /* - * It is assumed that the caller has already acquired a lock on - * gFamilyHeadAndNameListMutex before calling this. - */ - static NameFamilyPairList* gNameList; - if (NULL == gNameList) { - gNameList = SkNEW(NameFamilyPairList); - // register a delete proc with sk_atexit(..) when available - } - return *gNameList; -} - -struct FamilyRec { - FamilyRec* fNext; - SkTypeface* fFaces[4]; - - FamilyRec() - { - fNext = gFamilyHead; - memset(fFaces, 0, sizeof(fFaces)); - gFamilyHead = this; - } -}; - -static SkTypeface* find_best_face(const FamilyRec* family, - SkTypeface::Style style) { - SkTypeface* const* faces = family->fFaces; - - if (faces[style] != NULL) { // exact match - return faces[style]; - } - // look for a matching bold - style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); - if (faces[style] != NULL) { - return faces[style]; - } - // look for the plain - if (faces[SkTypeface::kNormal] != NULL) { - return faces[SkTypeface::kNormal]; - } - // look for anything - for (int i = 0; i < 4; i++) { - if (faces[i] != NULL) { - return faces[i]; - } - } - // should never get here, since the faces list should not be empty - SkDEBUGFAIL("faces list is empty"); - return NULL; -} - -static FamilyRec* find_family(const SkTypeface* member) { - FamilyRec* curr = gFamilyHead; - while (curr != NULL) { - for (int i = 0; i < 4; i++) { - if (curr->fFaces[i] == member) { - return curr; - } - } - curr = curr->fNext; - } - return NULL; -} - -// gFamilyHeadAndNameListMutex must already be acquired -static const char* find_family_name(const SkTypeface* member) { - FamilyRec* family = find_family(member); - if (NULL == family) { - return NULL; - } - - NameFamilyPairList& namelist = GetNameList(); - NameFamilyPair* list = namelist.begin(); - int count = namelist.count(); - - for (int i = 0; i < count; i++) { - NameFamilyPair* pair = &list[i]; - if (pair->fFamily == family) { - return pair->fName; - } - } - - return NULL; -} - -/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt - is not modified. - */ -static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { - FamilyRec* curr = gFamilyHead; - while (curr != NULL) { - for (int i = 0; i < 4; i++) { - SkTypeface* face = curr->fFaces[i]; - if (face != NULL && face->uniqueID() == uniqueID) { - return face; - } - } - curr = curr->fNext; - } - return NULL; -} - -/* Remove reference to this face from its family. If the resulting family - is empty (has no faces), return that family, otherwise return NULL -*/ -static FamilyRec* remove_from_family(const SkTypeface* face) { - FamilyRec* family = find_family(face); - if (family) { - SkASSERT(family->fFaces[face->style()] == face); - family->fFaces[face->style()] = NULL; - - for (int i = 0; i < 4; i++) { - if (family->fFaces[i] != NULL) { // family is non-empty - return NULL; - } - } - } else { -// SkDebugf("remove_from_family(%p) face not found", face); - } - return family; // return the empty family -} - -// maybe we should make FamilyRec be doubly-linked -static void detach_and_delete_family(FamilyRec* family) { - FamilyRec* curr = gFamilyHead; - FamilyRec* prev = NULL; - - while (curr != NULL) { - FamilyRec* next = curr->fNext; - if (curr == family) { - if (prev == NULL) { - gFamilyHead = next; - } else { - prev->fNext = next; - } - SkDELETE(family); - return; - } - prev = curr; - curr = next; - } - SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); -} - -// gFamilyHeadAndNameListMutex must already be acquired -static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { - NameFamilyPairList& namelist = GetNameList(); - NameFamilyPair* list = namelist.begin(); - int count = namelist.count(); - - int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); - - if (index >= 0) { - return find_best_face(list[index].fFamily, style); - } - return NULL; -} - -// gFamilyHeadAndNameListMutex must already be acquired -static SkTypeface* find_typeface(const SkTypeface* familyMember, - SkTypeface::Style style) { - const FamilyRec* family = find_family(familyMember); - return family ? find_best_face(family, style) : NULL; -} - -// gFamilyHeadAndNameListMutex must already be acquired -static void add_name(const char name[], FamilyRec* family) { - SkAutoAsciiToLC tolc(name); - name = tolc.lc(); - - NameFamilyPairList& namelist = GetNameList(); - NameFamilyPair* list = namelist.begin(); - int count = namelist.count(); - - int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); - - if (index < 0) { - list = namelist.insert(~index); - list->construct(name, family); - } -} - -// gFamilyHeadAndNameListMutex must already be acquired -static void remove_from_names(FamilyRec* emptyFamily) { -#ifdef SK_DEBUG - for (int i = 0; i < 4; i++) { - SkASSERT(emptyFamily->fFaces[i] == NULL); - } -#endif - - SkTDArray& list = GetNameList(); - - // must go backwards when removing - for (int i = list.count() - 1; i >= 0; --i) { - NameFamilyPair* pair = &list[i]; - if (pair->fFamily == emptyFamily) { - pair->destruct(); - list.remove(i); - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -class FamilyTypeface : public SkTypeface_FreeType { -public: - FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember, - bool isFixedPitch) - : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { - fIsSysFont = sysFont; - - // our caller has acquired the gFamilyHeadAndNameListMutex so this is safe - FamilyRec* rec = NULL; - if (familyMember) { - rec = find_family(familyMember); - SkASSERT(rec); - } else { - rec = SkNEW(FamilyRec); - } - rec->fFaces[style] = this; - } - - virtual ~FamilyTypeface() { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - - // remove us from our family. If the family is now empty, we return - // that and then remove that family from the name list - FamilyRec* family = remove_from_family(this); - if (NULL != family) { - remove_from_names(family); - detach_and_delete_family(family); - } - } - - bool isSysFont() const { return fIsSysFont; } - - virtual const char* getUniqueString() const = 0; - virtual const char* getFilePath() const = 0; - -protected: - virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; - -private: - bool fIsSysFont; - - typedef SkTypeface_FreeType INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -class StreamTypeface : public FamilyTypeface { -public: - StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember, - SkStream* stream, bool isFixedPitch) - : INHERITED(style, sysFont, familyMember, isFixedPitch) { - SkASSERT(stream); - stream->ref(); - fStream = stream; - } - virtual ~StreamTypeface() { - fStream->unref(); - } - - virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } - virtual const char* getFilePath() const SK_OVERRIDE { return NULL; } - -protected: - virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { - *ttcIndex = 0; - // we just ref our existing stream, since the caller will call unref() - // when they are through - fStream->ref(); - // must rewind each time, since the caller assumes a "new" stream - fStream->rewind(); - return fStream; - } - -private: - SkStream* fStream; - - typedef FamilyTypeface INHERITED; -}; - -class FileTypeface : public FamilyTypeface { -public: - FileTypeface(Style style, bool sysFont, SkTypeface* familyMember, - const char path[], bool isFixedPitch) - : INHERITED(style, sysFont, familyMember, isFixedPitch) { - SkString fullpath; - - if (sysFont) { - GetFullPathForSysFonts(&fullpath, path); - path = fullpath.c_str(); - } - fPath.set(path); - } - - virtual const char* getUniqueString() const SK_OVERRIDE { - const char* str = strrchr(fPath.c_str(), '/'); - if (str) { - str += 1; // skip the '/' - } - return str; - } - - virtual const char* getFilePath() const SK_OVERRIDE { - return fPath.c_str(); - } - -protected: - virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { - *ttcIndex = 0; - return SkStream::NewFromFile(fPath.c_str()); - } - -private: - SkString fPath; - - typedef FamilyTypeface INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -static bool get_name_and_style(const char path[], SkString* name, - SkTypeface::Style* style, - bool* isFixedPitch, bool isExpected) { - SkString fullpath; - GetFullPathForSysFonts(&fullpath, path); - - SkAutoTUnref stream(SkStream::NewFromFile(fullpath.c_str())); - if (stream.get()) { - return find_name_and_attributes(stream, name, style, isFixedPitch); - } else { - if (isExpected) { - SkDebugf("---- failed to open <%s> as a font", fullpath.c_str()); - } - return false; - } -} - -// used to record our notion of the pre-existing fonts -struct FontInitRec { - const char* fFileName; - const char* const* fNames; // null-terminated list -}; - -// deliberately empty, but we use the address to identify fallback fonts -static const char* gFBNames[] = { NULL }; - -/* Fonts are grouped by family, with the first font in a family having the - list of names (even if that list is empty), and the following members having - null for the list. The names list must be NULL-terminated. -*/ -static FontInitRec *gSystemFonts; -static size_t gNumSystemFonts = 0; - -// these globals are assigned (once) by load_system_fonts() -static FamilyRec* gDefaultFamily; -static SkTypeface* gDefaultNormal; -static char** gDefaultNames = NULL; -static uint32_t *gFallbackFonts; - -#if SK_DEBUG_FONTS -static void dump_globals() { - SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal, - gDefaultNormal ? gDefaultNormal->uniqueID() : 0, - gDefaultNormal ? gDefaultNormal->getRefCnt() : 0); - - if (gDefaultFamily) { - SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", - gDefaultFamily, - gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0, - gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0, - gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0, - gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0, - gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0, - gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0, - gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0, - gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0); - } else { - SkDebugf("gDefaultFamily=%p", gDefaultFamily); - } - - SkDebugf("gNumSystemFonts=%d gSystemFonts=%p gFallbackFonts=%p", - gNumSystemFonts, gSystemFonts, gFallbackFonts); - - for (size_t i = 0; i < gNumSystemFonts; ++i) { - SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName); - size_t namesIndex = 0; - if (gSystemFonts[i].fNames) - for (const char* fontName = gSystemFonts[i].fNames[namesIndex]; - fontName != 0; - fontName = gSystemFonts[i].fNames[++namesIndex]) { - SkDebugf(" name[%u]=%s", namesIndex, fontName); - } - } - - if (gFamilyHead) { - FamilyRec* rec = gFamilyHead; - int i=0; - while (rec) { - SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", - i++, rec, - rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0, - rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0, - rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0, - rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0, - rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0, - rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0, - rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0, - rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0); - rec = rec->fNext; - } - } else { - SkDebugf("gFamilyHead=%p", gFamilyHead); - } - -} -#endif - - -/* Load info from a configuration file that populates the system/fallback font structures -*/ -static void load_font_info() { - SkTDArray fontFamilies; - if (gTestMainConfigFile) { - getTestFontFamilies(fontFamilies, gTestMainConfigFile, gTestFallbackConfigFile); - } else { - getFontFamilies(fontFamilies); - } - - SkTDArray fontInfo; - for (int i = 0; i < fontFamilies.count(); ++i) { - FontFamily *family = fontFamilies[i]; - for (int j = 0; j < family->fFileNames.count(); ++j) { - FontInitRec fontInfoRecord; - fontInfoRecord.fFileName = family->fFileNames[j]; - if (j == 0) { - if (family->fNames.count() == 0) { - // Fallback font - fontInfoRecord.fNames = (char **)gFBNames; - } else { - SkTDArray names = family->fNames; - const char **nameList = (const char**) - malloc((names.count() + 1) * sizeof(char*)); - if (nameList == NULL) { - // shouldn't get here - SkDEBUGFAIL("Failed to allocate nameList"); - break; - } - if (gDefaultNames == NULL) { - gDefaultNames = (char**) nameList; - } - for (int i = 0; i < names.count(); ++i) { - nameList[i] = names[i]; - } - nameList[names.count()] = NULL; - fontInfoRecord.fNames = nameList; - } - } else { - fontInfoRecord.fNames = NULL; - } - *fontInfo.append() = fontInfoRecord; - } - } - gNumSystemFonts = fontInfo.count(); - gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec)); - gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t)); - if (gSystemFonts == NULL) { - // shouldn't get here - SkDEBUGFAIL("No system fonts were found"); - gNumSystemFonts = 0; - } - -#if SK_DEBUG_FONTS - SkDebugf("---- We have %d system fonts", gNumSystemFonts); -#endif - for (size_t i = 0; i < gNumSystemFonts; ++i) { - gSystemFonts[i].fFileName = fontInfo[i].fFileName; - gSystemFonts[i].fNames = fontInfo[i].fNames; -#if SK_DEBUG_FONTS - SkDebugf("---- gSystemFonts[%d] fileName=%s", i, fontInfo[i].fFileName); -#endif - } - fontFamilies.deleteAll(); -} - -/* - * Called once (ensured by the sentinel check at the beginning of our body). - * Initializes all the globals, and register the system fonts. - * - * gFamilyHeadAndNameListMutex must already be acquired. - */ -static void init_system_fonts() { - // check if we've already been called - if (gDefaultNormal) { - return; - } - - SkASSERT(gUniqueFontID == 0); - - load_font_info(); - - FontInitRec* rec = gSystemFonts; - SkTypeface* firstInFamily = NULL; - int fallbackCount = 0; - - for (size_t i = 0; i < gNumSystemFonts; i++) { - // if we're the first in a new family, clear firstInFamily - if (rec[i].fNames != NULL) { - firstInFamily = NULL; - } - - bool isFixedPitch; - SkString name; - SkTypeface::Style style; - - // we expect all the fonts, except the "fallback" fonts - bool isExpected = (rec[i].fNames != gFBNames); - if (!get_name_and_style(rec[i].fFileName, &name, &style, - &isFixedPitch, isExpected)) { - // We need to increase gUniqueFontID here so that the unique id of - // each font matches its index in gSystemFonts array, as expected - // by find_uniqueID. - sk_atomic_inc(&gUniqueFontID); - continue; - } - - SkTypeface* tf = SkNEW_ARGS(FileTypeface, - (style, - true, // system-font (cannot delete) - firstInFamily, // what family to join - rec[i].fFileName, - isFixedPitch) // filename - ); -#if SK_DEBUG_FONTS - SkDebugf("---- SkTypeface[%d] %s fontID %d", - i, rec[i].fFileName, tf->uniqueID()); -#endif - - if (rec[i].fNames != NULL) { - // see if this is one of our fallback fonts - if (rec[i].fNames == gFBNames) { -#if SK_DEBUG_FONTS - SkDebugf("---- adding %s as fallback[%d] fontID %d", - rec[i].fFileName, fallbackCount, tf->uniqueID()); -#endif - gFallbackFonts[fallbackCount++] = tf->uniqueID(); - - // Use the font file name as the name of the typeface. - const char **nameList = (const char**)malloc(2 * sizeof(char*)); - if (nameList == NULL) { - // shouldn't get here - SkDEBUGFAIL("Failed to allocate nameList"); - break; - } - nameList[0] = rec[i].fFileName; - nameList[1] = NULL; - rec[i].fNames = nameList; - } - - firstInFamily = tf; - FamilyRec* family = find_family(tf); - const char* const* names = rec[i].fNames; - - // record the default family if this is it - if (names == gDefaultNames) { - gDefaultFamily = family; - } - // add the names to map to this family - while (*names) { - add_name(*names, family); - names += 1; - } - } - } - - // do this after all fonts are loaded. This is our default font, and it - // acts as a sentinel so we only execute load_system_fonts() once - gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); - // now terminate our fallback list with the sentinel value - gFallbackFonts[fallbackCount] = 0; - -#if SK_DEBUG_FONTS - SkDEBUGCODE(dump_globals()); -#endif -} - -static size_t find_uniqueID(const char* filename) { - // uniqueID is the index, offset by one, of the associated element in - // gSystemFonts[] (assumes system fonts are loaded before external fonts) - // return 0 if not found - const FontInitRec* rec = gSystemFonts; - for (size_t i = 0; i < gNumSystemFonts; i++) { - if (strcmp(rec[i].fFileName, filename) == 0) { - return i+1; - } - } - return 0; -} - -static void reload_fallback_fonts() { - if (gTestFallbackConfigFile) { - // No need to reload fallback fonts in test environment. - return; - } - - SkGraphics::PurgeFontCache(); - - SkTDArray fallbackFamilies; - getFallbackFontFamilies(fallbackFamilies); - - int fallbackCount = 0; - for (int i = 0; i < fallbackFamilies.count(); ++i) { - FontFamily *family = fallbackFamilies[i]; - - for (int j = 0; j < family->fFileNames.count(); ++j) { - if (family->fFileNames[j]) { - - // ensure the fallback font exists before adding it to the list - bool isFixedPitch; - SkString name; - SkTypeface::Style style; - if (!get_name_and_style(family->fFileNames[j], &name, &style, - &isFixedPitch, false)) { - continue; - } - - size_t uniqueID = find_uniqueID(family->fFileNames[j]); - SkASSERT(uniqueID != 0); -#if SK_DEBUG_FONTS - SkDebugf("---- reload %s as fallback[%d] fontID %d oldFontID %d", - family->fFileNames[j], fallbackCount, uniqueID, - gFallbackFonts[fallbackCount]); -#endif - gFallbackFonts[fallbackCount++] = uniqueID; - break; // The fallback set contains only the first font of each family - } - } - } - // reset the sentinel the end of the newly ordered array - gFallbackFonts[fallbackCount] = 0; -} - -static void load_system_fonts() { - static AndroidLocale prevLocale; - AndroidLocale locale; - - getLocale(locale); - - if (!gDefaultNormal) { - prevLocale = locale; - init_system_fonts(); - } else if (strncmp(locale.language, prevLocale.language, 2) || - strncmp(locale.region, prevLocale.region, 2)) { - prevLocale = locale; - reload_fallback_fonts(); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, - bool* isLocalStream) const { - { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - desc->setFamilyName(find_family_name(this)); - desc->setFontFileName(this->getUniqueString()); - } - *isLocalStream = !this->isSysFont(); -} - -#if 0 // do we need this different name lookup for Deserialize? -SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - ... - if (NULL != fontFileName && 0 != *fontFileName) { - const FontInitRec* rec = gSystemFonts; - for (size_t i = 0; i < gNumSystemFonts; i++) { - if (strcmp(rec[i].fFileName, fontFileName) == 0) { - // backup until we hit the fNames - for (int j = i; j >= 0; --j) { - if (rec[j].fNames != NULL) { - return SkFontHost::CreateTypeface(NULL, - rec[j].fNames[0], style); - } - } - } - } - } - ... -} -#endif - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - SkTypeface::Style style) { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - - load_system_fonts(); - - // clip to legal style bits - style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - - SkTypeface* tf = NULL; - - if (NULL != familyFace) { - tf = find_typeface(familyFace, style); - } else if (NULL != familyName) { -// SkDebugf("======= familyName <%s>\n", familyName); - tf = find_typeface(familyName, style); - } - - if (NULL == tf) { - tf = find_best_face(gDefaultFamily, style); - } - - // we ref(), since the semantic is to return a new instance - tf->ref(); - return tf; -} - -SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, - SkFontID origFontID) { -#if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) - // Skia does not support font fallback for ndk applications in order to - // enable clients such as WebKit to customize their font selection. - // Clients can use GetFallbackFamilyNameForChar() to get the fallback - // font for individual characters. - return NULL; -#else - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - - load_system_fonts(); - - const SkTypeface* origTypeface = find_from_uniqueID(origFontID); - const SkTypeface* currTypeface = find_from_uniqueID(currFontID); - - SkASSERT(origTypeface != 0); - SkASSERT(currTypeface != 0); - SkASSERT(gFallbackFonts); - - // Our fallback list always stores the id of the plain in each fallback - // family, so we transform currFontID to its plain equivalent. - currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID(); - - /* First see if fontID is already one of our fallbacks. If so, return - its successor. If fontID is not in our list, then return the first one - in our list. Note: list is zero-terminated, and returning zero means - we have no more fonts to use for fallbacks. - */ - const uint32_t* list = gFallbackFonts; - for (int i = 0; list[i] != 0; i++) { - if (list[i] == currFontID) { - if (list[i+1] == 0) - return NULL; - const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]); - return SkRef(find_typeface(nextTypeface, origTypeface->style())); - } - } - - // If we get here, currFontID was not a fallback, so we start at the - // beginning of our list. Assuming there is at least one fallback font, - // i.e. gFallbackFonts[0] != 0. - const SkTypeface* firstTypeface = find_from_uniqueID(list[0]); - return SkRef(find_typeface(firstTypeface, origTypeface->style())); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { - if (NULL == stream || stream->getLength() <= 0) { - return NULL; - } - - bool isFixedPitch; - SkTypeface::Style style; - - if (find_name_and_attributes(stream, NULL, &style, &isFixedPitch)) { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - // Make sure system fonts are loaded to comply with the assumption of - // unique id offset by one in find_uniqueID. - load_system_fonts(); - return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedPitch)); - } else { - return NULL; - } -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { - SkAutoTUnref stream(SkStream::NewFromFile(path)); - return stream.get() ? SkFontHost::CreateTypefaceFromStream(stream) : NULL; -} - -/////////////////////////////////////////////////////////////////////////////// -// Function from SkTypeface_android.h -/////////////////////////////////////////////////////////////////////////////// - -struct FBScriptInfo { - const FallbackScripts fScript; - const char* fScriptID; - const SkTypeface::Style fStyle; - const SkUnichar fChar; // representative character for that script type - SkFontID fFontID; -}; - -#define SK_DEFINE_SCRIPT_ENTRY(script, style, unichar) \ - { script, #script, style, unichar, 0 } - -static FBScriptInfo gFBScriptInfo[] = { - SK_DEFINE_SCRIPT_ENTRY(kArabic_FallbackScript, SkTypeface::kNormal, 0x0627), - SK_DEFINE_SCRIPT_ENTRY(kArmenian_FallbackScript, SkTypeface::kNormal, 0x0531), - SK_DEFINE_SCRIPT_ENTRY(kBengali_FallbackScript, SkTypeface::kNormal, 0x0981), - SK_DEFINE_SCRIPT_ENTRY(kDevanagari_FallbackScript, SkTypeface::kNormal, 0x0901), - SK_DEFINE_SCRIPT_ENTRY(kEthiopic_FallbackScript, SkTypeface::kNormal, 0x1200), - SK_DEFINE_SCRIPT_ENTRY(kGeorgian_FallbackScript, SkTypeface::kNormal, 0x10A0), - SK_DEFINE_SCRIPT_ENTRY(kHebrewRegular_FallbackScript, SkTypeface::kNormal, 0x0591), - SK_DEFINE_SCRIPT_ENTRY(kHebrewBold_FallbackScript, SkTypeface::kBold, 0x0591), - SK_DEFINE_SCRIPT_ENTRY(kKannada_FallbackScript, SkTypeface::kNormal, 0x0C90), - SK_DEFINE_SCRIPT_ENTRY(kMalayalam_FallbackScript, SkTypeface::kNormal, 0x0D10), - SK_DEFINE_SCRIPT_ENTRY(kTamilRegular_FallbackScript, SkTypeface::kNormal, 0x0B82), - SK_DEFINE_SCRIPT_ENTRY(kTamilBold_FallbackScript, SkTypeface::kBold, 0x0B82), - SK_DEFINE_SCRIPT_ENTRY(kThai_FallbackScript, SkTypeface::kNormal, 0x0E01), - SK_DEFINE_SCRIPT_ENTRY(kTelugu_FallbackScript, SkTypeface::kNormal, 0x0C10), -}; - -static bool gFBScriptInitialized = false; -static const int gFBScriptInfoCount = sizeof(gFBScriptInfo) / sizeof(FBScriptInfo); - -// ensure that if any value is added to the public enum it is also added here -SK_COMPILE_ASSERT(gFBScriptInfoCount == kFallbackScriptNumber, FBScript_count_mismatch); - -// this function can't be called if the gFamilyHeadAndNameListMutex is already locked -static bool typefaceContainsChar(SkTypeface* face, SkUnichar uni) { - SkPaint paint; - paint.setTypeface(face); - paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); - - uint16_t glyphID; - paint.textToGlyphs(&uni, sizeof(uni), &glyphID); - return glyphID != 0; -} - -// this function can't be called if the gFamilyHeadAndNameListMutex is already locked -static SkTypeface* findFallbackTypefaceForChar(SkUnichar uni) { - SkASSERT(gFallbackFonts); - const uint32_t* list = gFallbackFonts; - for (int i = 0; list[i] != 0; i++) { - SkTypeface* face; - { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - face = find_from_uniqueID(list[i]); - } - if (typefaceContainsChar(face, uni)) { - return face; - } - } - return 0; -} - -// this function can't be called if the gFamilyHeadAndNameListMutex is already locked -static SkFontID findFallbackFontIDForChar(SkUnichar uni, SkTypeface::Style style) { - const SkTypeface* tf = findFallbackTypefaceForChar(uni); - if (!tf) { - return 0; - } - return find_typeface(tf, style)->uniqueID(); -} - -// this function can't be called if the gFamilyHeadAndNameListMutex is already locked -static void initFBScriptInfo() { - if (gFBScriptInitialized) { - return; - } - - // ensure the system fonts are loaded - gFamilyHeadAndNameListMutex.acquire(); - load_system_fonts(); - gFamilyHeadAndNameListMutex.release(); - - for (int i = 0; i < gFBScriptInfoCount; i++) { - FBScriptInfo& scriptInfo = gFBScriptInfo[i]; - // selects the best available style for the desired font. However, if - // bold is requested and no bold font exists for the typeface containing - // the character the next best style is chosen (e.g. normal). - scriptInfo.fFontID = findFallbackFontIDForChar(scriptInfo.fChar, scriptInfo.fStyle); -#if SK_DEBUG_FONTS - SkDebugf("gFBScriptInfo[%s] --> %d", scriptInfo.fScriptID, scriptInfo.fFontID); -#endif - } - // mark the value as initialized so we don't repeat our work unnecessarily - gFBScriptInitialized = true; -} - -SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) { - if (!SkTypeface_ValidScript(script)) { - return NULL; - } - - // ensure that our table is populated - initFBScriptInfo(); - - FBScriptInfo& scriptInfo = gFBScriptInfo[script]; - - // ensure the element with that index actually maps to the correct script - SkASSERT(scriptInfo.fScript == script); - - // if a suitable script could not be found then return NULL - if (scriptInfo.fFontID == 0) { - return NULL; - } - - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - - // retrieve the typeface the corresponds to this fontID - SkTypeface* tf = find_from_uniqueID(scriptInfo.fFontID); - // we ref(), since the semantic is to return a new instance - tf->ref(); - return tf; -} - -const char* SkGetFallbackScriptID(FallbackScripts script) { - for (int i = 0; i < gFBScriptInfoCount; i++) { - if (gFBScriptInfo[i].fScript == script) { - return gFBScriptInfo[i].fScriptID; - } - } - return NULL; -} - -FallbackScripts SkGetFallbackScriptFromID(const char* id) { - for (int i = 0; i < gFBScriptInfoCount; i++) { - if (strcmp(gFBScriptInfo[i].fScriptID, id) == 0) { - return gFBScriptInfo[i].fScript; - } - } - return kFallbackScriptNumber; // Use kFallbackScriptNumber as an invalid value. -} - -SkTypeface* SkCreateFallbackTypefaceForChar(SkUnichar uni, - SkTypeface::Style style) { - { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - load_system_fonts(); - } - - SkTypeface* tf = findFallbackTypefaceForChar(uni); - if (!tf) { - return NULL; - } - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - tf = find_typeface(tf, style); - // we ref(), since the semantic is to return a new instance - tf->ref(); - return tf; -} - -bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { - SkASSERT(name); - { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - load_system_fonts(); - } - - const SkTypeface* tf = findFallbackTypefaceForChar(uni); - if (!tf) { - return false; - } - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - name->set(find_family_name(tf)); - return true; -} - -void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, - const char* fontsdir) { - gTestMainConfigFile = mainconf; - gTestFallbackConfigFile = fallbackconf; - gTestFontFilePrefix = fontsdir; - SkASSERT(gTestMainConfigFile); - SkASSERT(gTestFallbackConfigFile); - SkASSERT(gTestFontFilePrefix); - SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s", - gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix)); -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkFontMgr.h" - -SkFontMgr* SkFontMgr::Factory() { - // todo - return NULL; -} diff --git a/gfx/skia/src/ports/SkFontHost_linux.cpp b/gfx/skia/src/ports/SkFontHost_linux.cpp deleted file mode 100644 index 05b73dcf23f8..000000000000 --- a/gfx/skia/src/ports/SkFontHost_linux.cpp +++ /dev/null @@ -1,524 +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 "SkFontHost.h" -#include "SkFontHost_FreeType_common.h" -#include "SkFontDescriptor.h" -#include "SkDescriptor.h" -#include "SkOSFile.h" -#include "SkPaint.h" -#include "SkString.h" -#include "SkStream.h" -#include "SkThread.h" -#include "SkTSearch.h" - -#ifndef SK_FONT_FILE_PREFIX -#ifdef SK_BUILD_FOR_ANDROID - #define SK_FONT_FILE_PREFIX "/fonts/" -#else - #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" -#endif -#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); - -/////////////////////////////////////////////////////////////////////////////// - -struct FamilyRec; - -/* This guy holds a mapping of a name -> family, used for looking up fonts. - Since it is stored in a stretchy array that doesn't preserve object - semantics, we don't use constructor/destructors, but just have explicit - helpers to manage our internal bookkeeping. - */ -struct NameFamilyPair { - const char* fName; // we own this - FamilyRec* fFamily; // we don't own this, we just reference it - - void construct(const char name[], FamilyRec* family) - { - fName = strdup(name); - fFamily = family; // we don't own this, so just record the referene - } - void destruct() - { - free((char*)fName); - // we don't own family, so just ignore our reference - } -}; - -// we use atomic_inc to grow this for each typeface we create -static int32_t gUniqueFontID; - -// this is the mutex that protects these globals -SK_DECLARE_STATIC_MUTEX(gFamilyMutex); -static FamilyRec* gFamilyHead; -static SkTDArray gNameList; - -struct FamilyRec { - FamilyRec* fNext; - SkTypeface* fFaces[4]; - - FamilyRec() - { - fNext = gFamilyHead; - memset(fFaces, 0, sizeof(fFaces)); - gFamilyHead = this; - } -}; - -static SkTypeface* find_best_face(const FamilyRec* family, - SkTypeface::Style style) { - SkTypeface* const* faces = family->fFaces; - - if (faces[style] != NULL) { // exact match - return faces[style]; - } - // look for a matching bold - style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); - if (faces[style] != NULL) { - return faces[style]; - } - // look for the plain - if (faces[SkTypeface::kNormal] != NULL) { - return faces[SkTypeface::kNormal]; - } - // look for anything - for (int i = 0; i < 4; i++) { - if (faces[i] != NULL) { - return faces[i]; - } - } - // should never get here, since the faces list should not be empty - SkDEBUGFAIL("faces list is empty"); - return NULL; -} - -static FamilyRec* find_family(const SkTypeface* member) { - FamilyRec* curr = gFamilyHead; - while (curr != NULL) { - for (int i = 0; i < 4; i++) { - if (curr->fFaces[i] == member) { - return curr; - } - } - curr = curr->fNext; - } - return NULL; -} - -/* Remove reference to this face from its family. If the resulting family - is empty (has no faces), return that family, otherwise return NULL - */ -static FamilyRec* remove_from_family(const SkTypeface* face) { - FamilyRec* family = find_family(face); - SkASSERT(family->fFaces[face->style()] == face); - family->fFaces[face->style()] = NULL; - - for (int i = 0; i < 4; i++) { - if (family->fFaces[i] != NULL) { // family is non-empty - return NULL; - } - } - return family; // return the empty family -} - -// maybe we should make FamilyRec be doubly-linked -static void detach_and_delete_family(FamilyRec* family) { - FamilyRec* curr = gFamilyHead; - FamilyRec* prev = NULL; - - while (curr != NULL) { - FamilyRec* next = curr->fNext; - if (curr == family) { - if (prev == NULL) { - gFamilyHead = next; - } else { - prev->fNext = next; - } - SkDELETE(family); - return; - } - prev = curr; - curr = next; - } - SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); -} - -static const char* find_family_name(const SkTypeface* familyMember) { - const FamilyRec* familyRec = find_family(familyMember); - for (int i = 0; i < gNameList.count(); i++) { - if (gNameList[i].fFamily == familyRec) { - return gNameList[i].fName; - } - } - return NULL; -} - -static FamilyRec* find_familyrec(const char name[]) { - const NameFamilyPair* list = gNameList.begin(); - int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, - sizeof(list[0])); - return index >= 0 ? list[index].fFamily : NULL; -} - -static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { - FamilyRec* rec = find_familyrec(name); - return rec ? find_best_face(rec, style) : NULL; -} - -static SkTypeface* find_typeface(const SkTypeface* familyMember, - SkTypeface::Style style) { - const FamilyRec* family = find_family(familyMember); - return family ? find_best_face(family, style) : NULL; -} - -static void add_name(const char name[], FamilyRec* family) { - SkAutoAsciiToLC tolc(name); - name = tolc.lc(); - - NameFamilyPair* list = gNameList.begin(); - int count = gNameList.count(); - - int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); - - if (index < 0) { - list = gNameList.insert(~index); - list->construct(name, family); - } -} - -static void remove_from_names(FamilyRec* emptyFamily) { -#ifdef SK_DEBUG - for (int i = 0; i < 4; i++) { - SkASSERT(emptyFamily->fFaces[i] == NULL); - } -#endif - - SkTDArray& list = gNameList; - - // must go backwards when removing - for (int i = list.count() - 1; i >= 0; --i) { - NameFamilyPair* pair = &list[i]; - if (pair->fFamily == emptyFamily) { - pair->destruct(); - list.remove(i); - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -class FamilyTypeface : public SkTypeface_FreeType { -public: - FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedPitch) - : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { - fIsSysFont = sysFont; - - SkAutoMutexAcquire ac(gFamilyMutex); - - if (NULL == family) { - family = SkNEW(FamilyRec); - } - family->fFaces[style] = this; - fFamilyRec = family; // just record it so we can return it if asked - } - - virtual ~FamilyTypeface() { - SkAutoMutexAcquire ac(gFamilyMutex); - - // remove us from our family. If the family is now empty, we return - // that and then remove that family from the name list - FamilyRec* family = remove_from_family(this); - if (NULL != family) { - remove_from_names(family); - detach_and_delete_family(family); - } - } - - bool isSysFont() const { return fIsSysFont; } - FamilyRec* getFamily() const { return fFamilyRec; } - - virtual const char* getUniqueString() const = 0; - -protected: - virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; - -private: - FamilyRec* fFamilyRec; // we don't own this, just point to it - bool fIsSysFont; - - typedef SkTypeface_FreeType INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -/* This subclass is just a place holder for when we have no fonts available. - It exists so that our globals (e.g. gFamilyHead) that expect *something* - will not be null. - */ -class EmptyTypeface : public FamilyTypeface { -public: - EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} - - virtual const char* getUniqueString() SK_OVERRIDE const { return NULL; } - -protected: - virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } - -private: - typedef FamilyTypeface INHERITED; -}; - -class StreamTypeface : public FamilyTypeface { -public: - StreamTypeface(Style style, bool sysFont, FamilyRec* family, - SkStream* stream, bool isFixedPitch) - : INHERITED(style, sysFont, family, isFixedPitch) { - stream->ref(); - fStream = stream; - } - virtual ~StreamTypeface() { - fStream->unref(); - } - - virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } - -protected: - virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { - *ttcIndex = 0; - fStream->ref(); - return fStream; - } - -private: - SkStream* fStream; - - typedef FamilyTypeface INHERITED; -}; - -class FileTypeface : public FamilyTypeface { -public: - FileTypeface(Style style, bool sysFont, FamilyRec* family, - const char path[], bool isFixedPitch) - : INHERITED(style, sysFont, family, isFixedPitch) { - fPath.set(path); - } - - virtual const char* getUniqueString() const SK_OVERRIDE { - const char* str = strrchr(fPath.c_str(), '/'); - if (str) { - str += 1; // skip the '/' - } - return str; - } - -protected: - virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { - *ttcIndex = 0; - return SkStream::NewFromFile(fPath.c_str()); - } - -private: - SkString fPath; - - typedef FamilyTypeface INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -static bool get_name_and_style(const char path[], SkString* name, - SkTypeface::Style* style, bool* isFixedPitch) { - SkAutoTUnref stream(SkStream::NewFromFile(path)); - if (stream.get()) { - return find_name_and_attributes(stream, name, style, isFixedPitch); - } else { - SkDebugf("---- failed to open <%s> as a font\n", path); - return false; - } -} - -// these globals are assigned (once) by load_system_fonts() -static SkTypeface* gFallBackTypeface; -static FamilyRec* gDefaultFamily; -static SkTypeface* gDefaultNormal; - -static void load_directory_fonts(const SkString& directory, unsigned int* count) { - SkOSFile::Iter iter(directory.c_str(), ".ttf"); - SkString name; - - while (iter.next(&name, false)) { - SkString filename(directory); - filename.append(name); - - bool isFixedPitch; - SkString realname; - SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning - - if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) { - SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); - continue; - } - - FamilyRec* family = find_familyrec(realname.c_str()); - if (family && family->fFaces[style]) { - continue; - } - - // this constructor puts us into the global gFamilyHead llist - FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, - (style, - true, // system-font (cannot delete) - family, // what family to join - filename.c_str(), - isFixedPitch) // filename - ); - - if (NULL == family) { - add_name(realname.c_str(), tf->getFamily()); - } - *count += 1; - } - - SkOSFile::Iter dirIter(directory.c_str()); - while (dirIter.next(&name, true)) { - if (name.startsWith(".")) { - continue; - } - SkString dirname(directory); - dirname.append(name); - dirname.append(SK_FONT_FILE_DIR_SEPERATOR); - load_directory_fonts(dirname, count); - } -} - -static void load_system_fonts() { - // check if we've already be called - if (NULL != gDefaultNormal) { - return; - } - - SkString baseDirectory; -#ifdef SK_BUILD_FOR_ANDROID - baseDirectory.set(getenv("ANDROID_ROOT")); -#endif - - baseDirectory.append(SK_FONT_FILE_PREFIX); - - unsigned int count = 0; - load_directory_fonts(baseDirectory, &count); - - if (0 == count) { - SkNEW(EmptyTypeface); - } - - // do this after all fonts are loaded. This is our default font, and it - // acts as a sentinel so we only execute load_system_fonts() once - static const char* gDefaultNames[] = { - "Arial", "Verdana", "Times New Roman", NULL - }; - const char** names = gDefaultNames; - while (*names) { - SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); - if (tf) { - gDefaultNormal = tf; - break; - } - } - // check if we found *something* - if (NULL == gDefaultNormal) { - if (NULL == gFamilyHead) { - sk_throw(); - } - for (int i = 0; i < 4; i++) { - if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { - break; - } - } - } - if (NULL == gDefaultNormal) { - sk_throw(); - } - gFallBackTypeface = gDefaultNormal; - gDefaultFamily = find_family(gDefaultNormal); -} - -/////////////////////////////////////////////////////////////////////////////// - -void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, - bool* isLocalStream) const { - desc->setFamilyName(find_family_name(this)); - desc->setFontFileName(this->getUniqueString()); - *isLocalStream = !this->isSysFont(); -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - SkTypeface::Style style) { - load_system_fonts(); - - SkAutoMutexAcquire ac(gFamilyMutex); - - // clip to legal style bits - style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - - SkTypeface* tf = NULL; - - if (NULL != familyFace) { - tf = find_typeface(familyFace, style); - } else if (NULL != familyName) { - // SkDebugf("======= familyName <%s>\n", familyName); - tf = find_typeface(familyName, style); - } - - if (NULL == tf) { - tf = find_best_face(gDefaultFamily, style); - } - - SkSafeRef(tf); - return tf; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { - if (NULL == stream || stream->getLength() <= 0) { - SkDELETE(stream); - return NULL; - } - - bool isFixedPitch; - SkTypeface::Style style; - if (find_name_and_attributes(stream, NULL, &style, &isFixedPitch)) { - return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedPitch)); - } else { - return NULL; - } -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { - SkAutoTUnref stream(SkStream::NewFromFile(path)); - return stream.get() ? CreateTypefaceFromStream(stream) : NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkFontMgr.h" - -SkFontMgr* SkFontMgr::Factory() { - // todo - return NULL; -} diff --git a/gfx/skia/src/ports/SkFontHost_none.cpp b/gfx/skia/src/ports/SkFontHost_none.cpp deleted file mode 100644 index c5267096b496..000000000000 --- a/gfx/skia/src/ports/SkFontHost_none.cpp +++ /dev/null @@ -1,37 +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 "SkFontHost.h" -#include "SkScalerContext.h" - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char famillyName[], - SkTypeface::Style style) { - SkDEBUGFAIL("SkFontHost::FindTypeface unimplemented"); - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*) { - SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented"); - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { - SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented"); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkFontMgr.h" - -SkFontMgr* SkFontMgr::Factory() { - // todo - return NULL; -} diff --git a/gfx/skia/src/ports/SkGlobalInitialization_chromium.cpp b/gfx/skia/src/ports/SkGlobalInitialization_chromium.cpp deleted file mode 100644 index d05af709954b..000000000000 --- a/gfx/skia/src/ports/SkGlobalInitialization_chromium.cpp +++ /dev/null @@ -1,34 +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 "SkBitmapProcShader.h" -#include "SkBlurImageFilter.h" -#include "SkBlurMaskFilter.h" -#include "SkColorFilter.h" -#include "SkCornerPathEffect.h" -#include "SkDashPathEffect.h" -#include "SkGradientShader.h" -#include "SkLayerDrawLooper.h" -#include "SkMallocPixelRef.h" -#include "SkXfermode.h" -#include "SkMagnifierImageFilter.h" - -void SkFlattenable::InitializeFlattenables() { - - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurImageFilter) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCornerPathEffect) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDashPathEffect) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter) - - SkBlurMaskFilter::InitializeFlattenables(); - SkColorFilter::InitializeFlattenables(); - SkGradientShader::InitializeFlattenables(); - SkXfermode::InitializeFlattenables(); -} diff --git a/gfx/skia/src/ports/SkImageDecoder_empty.cpp b/gfx/skia/src/ports/SkImageDecoder_empty.cpp deleted file mode 100644 index 410eef11b892..000000000000 --- a/gfx/skia/src/ports/SkImageDecoder_empty.cpp +++ /dev/null @@ -1,71 +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 "SkImageDecoder.h" -#include "SkImageEncoder.h" -#include "SkMovie.h" - -class SkBitmap; -class SkStream; - -SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) { - return NULL; -} - -bool SkImageDecoder::DecodeFile(const char file[], SkBitmap*, SkBitmap::Config, - SkImageDecoder::Mode, SkImageDecoder::Format*) { - return false; -} - -bool SkImageDecoder::decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode) { - return false; -} - -bool SkImageDecoder::DecodeStream(SkStream*, SkBitmap*, SkBitmap::Config, SkImageDecoder::Mode, - SkImageDecoder::Format*) { - return false; -} - -bool SkImageDecoder::DecodeMemory(const void*, size_t, SkBitmap*, SkBitmap::Config, - SkImageDecoder::Mode, SkImageDecoder::Format*) { - return false; -} - -SkImageDecoder* CreateJPEGImageDecoder() { - return NULL; -} -///////////////////////////////////////////////////////////////////////// - -SkMovie* SkMovie::DecodeStream(SkStream* stream) { - return NULL; -} - -///////////////////////////////////////////////////////////////////////// - -SkImageEncoder* SkImageEncoder::Create(Type t) { - return NULL; -} - -bool SkImageEncoder::EncodeFile(const char file[], const SkBitmap&, Type, int quality) { - return false; -} - -bool SkImageEncoder::EncodeStream(SkWStream*, const SkBitmap&, SkImageEncoder::Type, int) { - return false; -} - -bool SkImageEncoder::encodeStream(SkWStream*, const SkBitmap&, int) { - return false; -} - -///////////////////////////////////////////////////////////////////////// - -#include "SkImages.h" - -void SkImages::InitializeFlattenables() {} diff --git a/gfx/skia/src/ports/SkMemory_brew.cpp b/gfx/skia/src/ports/SkMemory_brew.cpp deleted file mode 100644 index 96af7021e61a..000000000000 --- a/gfx/skia/src/ports/SkMemory_brew.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* libs/graphics/ports/SkMemory_brew.cpp - * - * Copyright 2009, The Android Open Source Project - * Copyright 2009, Company 100, Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkTypes.h" - -#ifdef SK_BUILD_FOR_BREW - -#include - -void sk_throw() { - SkDEBUGFAIL("sk_throw"); - abort(); -} - -void sk_out_of_memory(void) { - SkDEBUGFAIL("sk_out_of_memory"); - abort(); -} - -void* sk_malloc_throw(size_t size) { - return sk_malloc_flags(size, SK_MALLOC_THROW); -} - -void* sk_realloc_throw(void* addr, size_t size) { - void* p = REALLOC(addr, size | ALLOC_NO_ZMEM); - if (size == 0) { - return p; - } - if (p == NULL) { - sk_throw(); - } - return p; -} - -void sk_free(void* p) { - FREEIF(p); -} - -void* sk_malloc_flags(size_t size, unsigned flags) { - void* p = MALLOC(size | ALLOC_NO_ZMEM); - if (p == NULL) { - if (flags & SK_MALLOC_THROW) { - sk_throw(); - } - } - return p; -} - -#endif diff --git a/gfx/skia/src/ports/SkOSFile_brew.cpp b/gfx/skia/src/ports/SkOSFile_brew.cpp deleted file mode 100644 index 50e133ff2f9e..000000000000 --- a/gfx/skia/src/ports/SkOSFile_brew.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* libs/graphics/ports/SkOSFile_brew.cpp - * - * Copyright 2006, The Android Open Source Project - * Copyright 2009, Company 100, Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - - -#include "SkOSFile.h" - -#ifdef SK_BUILD_FOR_BREW - -#include -#include -#include - -SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) -{ - int err; - OpenFileMode mode; - IFileMgr* fileMgr; - IFile* file; - IShell* shell; - - shell = reinterpret_cast(GETAPPINSTANCE())->m_pIShell; - err = ISHELL_CreateInstance(shell, AEECLSID_FILEMGR, (void**)&fileMgr); - if (err!= SUCCESS) - return NULL; - - if (flags & kWrite_SkFILE_Flag) - mode = _OFM_READWRITE; - else /* kRead_SkFILE_Flag */ - mode = _OFM_READ; - - file = IFILEMGR_OpenFile(fileMgr, path, mode); - IFILEMGR_Release(fileMgr); - - return (SkFILE*)file; -} - -size_t sk_fgetsize(SkFILE* f) -{ - FileInfo fileInfo; - - IFILE_GetInfo((IFile*)f, &fileInfo); - return fileInfo.dwSize; -} - -bool sk_frewind(SkFILE* f) -{ - SkASSERT(f); - return IFILE_Seek((IFile*)f, _SEEK_START, 0) == SUCCESS; -} - -size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f) -{ - SkASSERT(f); - if (buffer == NULL) - { - int err = IFILE_Seek((IFile*)f, _SEEK_CURRENT, (int)byteCount); - if (err == EFAILED) { - SkDEBUGF(("sk_fread: IFILE_Seek(%d) failed returned:%d\n", byteCount, err)); - return 0; - } - return byteCount; - } - else - return IFILE_Read((IFile*)f, buffer, byteCount); -} - -size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f) -{ - SkASSERT(f); - return IFILE_Write((IFile*)f, buffer, byteCount); -} - -void sk_fflush(SkFILE* f) -{ - SkASSERT(f); -} - -void sk_fclose(SkFILE* f) -{ - SkASSERT(f); - IFILE_Release((IFile*)f); -} - -#endif diff --git a/gfx/skia/src/sfnt/SkOTUtils.h b/gfx/skia/src/sfnt/SkOTUtils.h deleted file mode 100644 index 3c5ada25ebd0..000000000000 --- a/gfx/skia/src/sfnt/SkOTUtils.h +++ /dev/null @@ -1,37 +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 SkOTUtils_DEFINED -#define SkOTUtils_DEFINED - -#include "SkOTTableTypes.h" -class SkData; -class SkStream; - -struct SkOTUtils { - /** - * Calculates the OpenType checksum for data. - */ - static uint32_t CalcTableChecksum(SK_OT_ULONG *data, size_t length); - - /** - * Renames an sfnt font. On failure (invalid data or not an sfnt font) - * returns NULL. - * - * Essentially, this removes any existing 'name' table and replaces it - * with a new one in which FontFamilyName, FontSubfamilyName, - * UniqueFontIdentifier, FullFontName, and PostscriptName are fontName. - * - * The new 'name' table records will be written with the Windows, - * UnicodeBMPUCS2, and English_UnitedStates settings. - * - * fontName and fontNameLen must be specified in terms of ASCII chars. - */ - static SkData* RenameFont(SkStream* fontData, const char* fontName, int fontNameLen); -}; - -#endif diff --git a/gfx/skia/src/utils/SkBitmapChecksummer.cpp b/gfx/skia/src/utils/SkBitmapChecksummer.cpp deleted file mode 100644 index 883210c36005..000000000000 --- a/gfx/skia/src/utils/SkBitmapChecksummer.cpp +++ /dev/null @@ -1,69 +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 "SkBitmap.h" -#include "SkBitmapChecksummer.h" -#include "SkBitmapTransformer.h" -#include "SkCityHash.h" -#include "SkEndian.h" - -/** - * Write an integer value into a bytebuffer in little-endian order. - */ -static void write_int_to_buffer(int val, char* buf) { - val = SkEndian_SwapLE32(val); - for (int byte=0; byte<4; byte++) { - *buf++ = (char)(val & 0xff); - val = val >> 8; - } -} - -/*static*/ uint64_t SkBitmapChecksummer::Compute64Internal( - const SkBitmap& bitmap, const SkBitmapTransformer& transformer) { - size_t pixelBufferSize = transformer.bytesNeededTotal(); - size_t totalBufferSize = pixelBufferSize + 8; // leave room for x/y dimensions - - SkAutoMalloc bufferManager(totalBufferSize); - char *bufferStart = static_cast(bufferManager.get()); - char *bufPtr = bufferStart; - // start with the x/y dimensions - write_int_to_buffer(bitmap.width(), bufPtr); - bufPtr += 4; - write_int_to_buffer(bitmap.height(), bufPtr); - bufPtr += 4; - - // add all the pixel data - if (!transformer.copyBitmapToPixelBuffer(bufPtr, pixelBufferSize)) { - return 0; - } - return SkCityHash::Compute64(bufferStart, totalBufferSize); -} - -/*static*/ uint64_t SkBitmapChecksummer::Compute64(const SkBitmap& bitmap) { - const SkBitmapTransformer::PixelFormat kPixelFormat = - SkBitmapTransformer::kARGB_8888_Premul_PixelFormat; - - // First, try to transform the existing bitmap. - const SkBitmapTransformer transformer = - SkBitmapTransformer(bitmap, kPixelFormat); - if (transformer.isValid(false)) { - return Compute64Internal(bitmap, transformer); - } - - // Hmm, that didn't work. Maybe if we create a new - // kARGB_8888_Config version of the bitmap it will work better? - SkBitmap copyBitmap; - bitmap.copyTo(©Bitmap, SkBitmap::kARGB_8888_Config); - const SkBitmapTransformer copyTransformer = - SkBitmapTransformer(copyBitmap, kPixelFormat); - if (copyTransformer.isValid(true)) { - return Compute64Internal(copyBitmap, copyTransformer); - } else { - return 0; - } -} diff --git a/gfx/skia/src/utils/SkBitmapChecksummer.h b/gfx/skia/src/utils/SkBitmapChecksummer.h deleted file mode 100644 index 63ac726c2eba..000000000000 --- a/gfx/skia/src/utils/SkBitmapChecksummer.h +++ /dev/null @@ -1,37 +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 SkBitmapChecksummer_DEFINED -#define SkBitmapChecksummer_DEFINED - -#include "SkBitmap.h" -#include "SkBitmapTransformer.h" - -/** - * Static class that can generate checksums from SkBitmaps. - */ -class SkBitmapChecksummer { -public: - /** - * Returns a 64-bit checksum of the pixels in this bitmap. - * - * If this is unable to compute the checksum for some reason, - * it returns 0. - * - * Note: depending on the bitmap config, 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. - */ - static uint64_t Compute64(const SkBitmap& bitmap); - -private: - static uint64_t Compute64Internal(const SkBitmap& bitmap, - const SkBitmapTransformer& transformer); -}; - -#endif diff --git a/gfx/skia/src/utils/SkBitmapTransformer.cpp b/gfx/skia/src/utils/SkBitmapTransformer.cpp deleted file mode 100644 index c8356d423844..000000000000 --- a/gfx/skia/src/utils/SkBitmapTransformer.cpp +++ /dev/null @@ -1,87 +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 "SkBitmap.h" -#include "SkBitmapTransformer.h" -#include "SkColorPriv.h" -#include "SkTypes.h" - -bool SkBitmapTransformer::isValid(bool logReason) const { - bool retval = true; - - switch(fPixelFormat) { - case kARGB_8888_Premul_PixelFormat: - break; - default: - if (logReason) { - SkDEBUGF(("PixelFormat %d not supported\n", fPixelFormat)); - } - retval = false; - } - - SkBitmap::Config bitmapConfig = fBitmap.config(); - switch(bitmapConfig) { - case SkBitmap::kARGB_8888_Config: - break; - default: - if (logReason) { - SkDEBUGF(("SkBitmap::Config %d not supported\n", bitmapConfig)); - } - retval = false; - } - - return retval; -} - -/** - * Transform from kARGB_8888_Config to kARGB_8888_Premul_PixelFormat. - * - * Similar to the various scanline transformers in - * src/images/transform_scanline.h . - */ -static void transform_scanline(const char* SK_RESTRICT src, int width, - char* SK_RESTRICT dst) { - const SkPMColor* SK_RESTRICT srcP = reinterpret_cast(src); - for (int i = 0; i < width; i++) { - SkPMColor c = *srcP++; - unsigned a = SkGetPackedA32(c); - unsigned r = SkGetPackedR32(c); - unsigned g = SkGetPackedG32(c); - unsigned b = SkGetPackedB32(c); - *dst++ = a; - *dst++ = r; - *dst++ = g; - *dst++ = b; - } -} - -bool SkBitmapTransformer::copyBitmapToPixelBuffer(void *dstBuffer, - size_t dstBufferSize) const { - if (!this->isValid(true)) { - return false; - } - size_t bytesNeeded = this->bytesNeededTotal(); - if (dstBufferSize < bytesNeeded) { - SkDEBUGF(("dstBufferSize %d must be >= %d\n", dstBufferSize, bytesNeeded)); - return false; - } - - fBitmap.lockPixels(); - int width = fBitmap.width(); - size_t srcRowBytes = fBitmap.rowBytes(); - size_t dstRowBytes = this->bytesNeededPerRow(); - const char *srcBytes = const_cast(static_cast(fBitmap.getPixels())); - char *dstBytes = static_cast(dstBuffer); - for (int y = 0; y < fBitmap.height(); y++) { - transform_scanline(srcBytes, width, dstBytes); - srcBytes += srcRowBytes; - dstBytes += dstRowBytes; - } - fBitmap.unlockPixels(); - return true; -} diff --git a/gfx/skia/src/utils/SkBitmapTransformer.h b/gfx/skia/src/utils/SkBitmapTransformer.h deleted file mode 100644 index 70971ac62541..000000000000 --- a/gfx/skia/src/utils/SkBitmapTransformer.h +++ /dev/null @@ -1,104 +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 SkBitmapTransformer_DEFINED -#define SkBitmapTransformer_DEFINED - -#include "SkBitmap.h" - -/** - * Class that can copy pixel data out of an SkBitmap, transforming it - * into the appropriate PixelFormat. - * - * As noted in https://codereview.appspot.com/6849119/#msg6 and - * https://codereview.appspot.com/6900047 , at some point we might want - * to make this more general purpose: - * - support more PixelFormats - * - use existing SkCanvas::Config8888 enum instead of new PixelFormat enum - * - add method to copy pixel data for a single row, instead of the whole bitmap - * - add methods to copy pixel data INTO an SkBitmap - * - * That would allow us to replace SkCopyConfig8888ToBitmap() in - * src/core/SkConfig8888.h , as well as the transformations used by - * src/images/SkImageDecoder_libpng.cpp , with this common code. - * - * But for now, we want something more narrowly targeted, just - * supplying what is needed by SkBitmapChecksummer. - */ -class SkBitmapTransformer { -public: - enum PixelFormat { - // 32 bits per pixel, ARGB byte order, with the alpha-channel - // value premultiplied into the R/G/B channel values. - kARGB_8888_Premul_PixelFormat, - - // marks the end of the list - kLast_PixelFormat = kARGB_8888_Premul_PixelFormat, - }; - - /** - * Creates an SkBitmapTransformer instance that can transform between - * the given bitmap and a pixel buffer with given pixelFormat. - * - * Call IsValid() before using, to confirm that this particular - * bitmap/pixelFormat combination is supported! - */ - SkBitmapTransformer(const SkBitmap& bitmap, PixelFormat pixelFormat) : - fBitmap(bitmap), fPixelFormat(pixelFormat) {} - - /** - * Returns true iff we can convert between fBitmap and fPixelFormat. - * If this returns false, the return values of any other methods will - * be meaningless! - * - * @param logReason whether to log the reason why this combination - * is unsupported (only applies in debug mode) - */ - bool isValid(bool logReason=false) const; - - /** - * Returns the number of bytes needed to store a single row of the - * bitmap's pixels if converted to pixelFormat. - */ - size_t bytesNeededPerRow() const { - // This is hard-coded for the single supported PixelFormat. - return fBitmap.width() * 4; - } - - /** - * Returns the number of bytes needed to store the entire bitmap - * if converted to pixelFormat, ASSUMING that it is written - * out as a single contiguous blob of pixels (no leftover bytes - * at the end of each row). - */ - size_t bytesNeededTotal() const { - return this->bytesNeededPerRow() * fBitmap.height(); - } - - /** - * Writes the entire bitmap into dstBuffer, using the already-specified - * pixelFormat. Returns true if successful. - * - * dstBufferSize is the maximum allowable bytes to write into dstBuffer; - * if that is not large enough to hold the entire bitmap, then this - * will fail immediately and return false. - * We force the caller to pass this in to avoid buffer overruns in - * unanticipated cases. - * - * All pixels for all rows will be written into dstBuffer as a - * single contiguous blob (no skipped pixels at the end of each - * row). - */ - bool copyBitmapToPixelBuffer (void *dstBuffer, size_t dstBufferSize) const; - -private: - const SkBitmap& fBitmap; - const PixelFormat fPixelFormat; -}; - -#endif diff --git a/gfx/skia/src/utils/SkCityHash.cpp b/gfx/skia/src/utils/SkCityHash.cpp deleted file mode 100644 index a21aa89634ce..000000000000 --- a/gfx/skia/src/utils/SkCityHash.cpp +++ /dev/null @@ -1,23 +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. - */ - -/** - * Pass any calls through to the CityHash library. - * This is the only source file that accesses the CityHash code directly. - */ - -#include "SkCityHash.h" -#include "SkTypes.h" -#include "city.h" - -uint32_t SkCityHash::Compute32(const char *data, size_t size) { - return CityHash32(data, size); -} - -uint64_t SkCityHash::Compute64(const char *data, size_t size) { - return CityHash64(data, size); -} diff --git a/gfx/skia/src/utils/SkCityHash.h b/gfx/skia/src/utils/SkCityHash.h deleted file mode 100644 index c69e0fb37b3c..000000000000 --- a/gfx/skia/src/utils/SkCityHash.h +++ /dev/null @@ -1,47 +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. - */ - -/** - * Hash functions, using the CityHash algorithm. - * - * Results are guaranteed to be: - * 1. consistent across revisions of the library (for a given set - * of bytes, the checksum generated at one revision of the Skia - * library will match the one generated on any other revision of - * the Skia library) - * 2. consistent across platforms (for a given - * set of bytes, the checksum generated on one platform will - * match the one generated on any other platform) - */ - -#ifndef SkCityHash_DEFINED -#define SkCityHash_DEFINED - -#include "SkTypes.h" - -class SkCityHash : SkNoncopyable { -public: - /** - * Compute a 32-bit checksum for a given data block. - * - * @param data Memory address of the data block to be processed. - * @param size Size of the data block in bytes. - * @return checksum result - */ - static uint32_t Compute32(const char *data, size_t size); - - /** - * Compute a 64-bit checksum for a given data block. - * - * @param data Memory address of the data block to be processed. - * @param size Size of the data block in bytes. - * @return checksum result - */ - static uint64_t Compute64(const char *data, size_t size); -}; - -#endif diff --git a/gfx/skia/src/utils/cityhash/README b/gfx/skia/src/utils/cityhash/README deleted file mode 100644 index d93928857f5e..000000000000 --- a/gfx/skia/src/utils/cityhash/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains files needed to build third_party/externals/cityhash -(such as the config.h file that would normally be created by autoconf) diff --git a/gfx/skia/src/utils/cityhash/config.h b/gfx/skia/src/utils/cityhash/config.h deleted file mode 100644 index bd3641658e40..000000000000 --- a/gfx/skia/src/utils/cityhash/config.h +++ /dev/null @@ -1,17 +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. - */ - -/** - * Converts from Skia build flags to the macro definitions cityhash normally - * gets from autoconf. - */ - -#include "SkTypes.h" - -#ifdef SK_CPU_BENDIAN - #define WORDS_BIGENDIAN 1 -#endif diff --git a/gfx/skia/src/utils/mac/SkBitmap_Mac.cpp b/gfx/skia/src/utils/mac/SkBitmap_Mac.cpp deleted file mode 100644 index 151dc9b8f9ba..000000000000 --- a/gfx/skia/src/utils/mac/SkBitmap_Mac.cpp +++ /dev/null @@ -1,149 +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 "SkBitmap.h" -#include "SkColorPriv.h" -#include "SkMath.h" - -#if defined(SK_BUILD_FOR_MAC) - -#include - -#ifndef __ppc__ - #define SWAP_16BIT -#endif - -static void convertGL32_to_Mac32(uint32_t dst[], const SkBitmap& bm) { - memcpy(dst, bm.getPixels(), bm.getSize()); - return; - - uint32_t* stop = dst + (bm.getSize() >> 2); - const uint8_t* src = (const uint8_t*)bm.getPixels(); - while (dst < stop) { - *dst++ = src[2] << 24 | src[1] << 16 | src[0] << 8 | src[3] << 0; - src += sizeof(uint32_t); - } -} - -static void convert565_to_32(uint32_t dst[], const SkBitmap& bm) { - for (int y = 0; y < bm.height(); y++) { - const uint16_t* src = bm.getAddr16(0, y); - const uint16_t* stop = src + bm.width(); - while (src < stop) { - unsigned c = *src++; - unsigned r = SkPacked16ToR32(c); - unsigned g = SkPacked16ToG32(c); - unsigned b = SkPacked16ToB32(c); - - *dst++ = (b << 24) | (g << 16) | (r << 8) | 0xFF; - } - } -} - -static void convert4444_to_555(uint16_t dst[], const uint16_t src[], int count) -{ - const uint16_t* stop = src + count; - - while (src < stop) - { - unsigned c = *src++; - - unsigned r = SkGetPackedR4444(c); - unsigned g = SkGetPackedG4444(c); - unsigned b = SkGetPackedB4444(c); - // convert to 5 bits - r = (r << 1) | (r >> 3); - g = (g << 1) | (g >> 3); - b = (b << 1) | (b >> 3); - // build the 555 - c = (r << 10) | (g << 5) | b; - -#ifdef SWAP_16BIT - c = (c >> 8) | (c << 8); -#endif - *dst++ = c; - } -} - -#include "SkTemplates.h" - -static CGImageRef bitmap2imageref(const SkBitmap& bm) { - size_t bitsPerComp; - size_t bitsPerPixel; - CGBitmapInfo info; - CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - CGDataProviderRef data = CGDataProviderCreateWithData(NULL, - bm.getPixels(), - bm.getSize(), - NULL); - SkAutoTCallVProc acp(data); - SkAutoTCallVProc acp2(cs); - - switch (bm.config()) { - case SkBitmap::kARGB_8888_Config: - bitsPerComp = 8; - bitsPerPixel = 32; - info = kCGImageAlphaPremultipliedLast; - break; - case SkBitmap::kARGB_4444_Config: - bitsPerComp = 4; - bitsPerPixel = 16; - info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Little; - break; -#if 0 // not supported by quartz !!! - case SkBitmap::kRGB_565_Config: - bitsPerComp = 5; - bitsPerPixel = 16; - info = kCGImageAlphaNone | kCGBitmapByteOrder16Little; - break; -#endif - default: - return NULL; - } - - return CGImageCreate(bm.width(), bm.height(), bitsPerComp, bitsPerPixel, - bm.rowBytes(), cs, info, data, - NULL, false, kCGRenderingIntentDefault); -} - -void SkBitmap::drawToPort(WindowRef wind, CGContextRef cg) const { - if (fPixels == NULL || fWidth == 0 || fHeight == 0) { - return; - } - - bool useQD = false; - if (NULL == cg) { - SetPortWindowPort(wind); - QDBeginCGContext(GetWindowPort(wind), &cg); - useQD = true; - } - - SkBitmap bm; - if (this->config() == kRGB_565_Config) { - this->copyTo(&bm, kARGB_8888_Config); - } else { - bm = *this; - } - bm.lockPixels(); - - CGImageRef image = bitmap2imageref(bm); - if (image) { - CGRect rect; - rect.origin.x = rect.origin.y = 0; - rect.size.width = bm.width(); - rect.size.height = bm.height(); - - CGContextDrawImage(cg, rect, image); - CGImageRelease(image); - } - - if (useQD) { - QDEndCGContext(GetWindowPort(wind), &cg); - } -} - -#endif diff --git a/gfx/skia/src/views/unix/skia_unix.cpp b/gfx/skia/src/views/unix/skia_unix.cpp deleted file mode 100644 index 108e9ac20688..000000000000 --- a/gfx/skia/src/views/unix/skia_unix.cpp +++ /dev/null @@ -1,62 +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 "X11/Xlib.h" -#include "X11/keysym.h" - -#include "SkApplication.h" -#include "SkEvent.h" -#include "SkWindow.h" -#include "SkTypes.h" - -#include -#include - -SkOSWindow* gWindow; - -static void catch_alarm(int sig) -{ - SkEvent::ServiceQueueTimer(); -} - -int main(int argc, char** argv){ - signal(SIGALRM, catch_alarm); - - gWindow = create_sk_window(NULL, argc, argv); - - // drain any events that occurred before gWindow was assigned. - while (SkEvent::ProcessEvent()); - - // Start normal Skia sequence - application_init(); - - gWindow->loop(); - - delete gWindow; - application_term(); - return 0; -} - -// SkEvent handlers - -void SkEvent::SignalNonEmptyQueue() -{ - if (gWindow) { - gWindow->post_linuxevent(); - } -} - -void SkEvent::SignalQueueTimer(SkMSec delay) -{ - itimerval newTimer; - newTimer.it_interval.tv_sec = 0; - newTimer.it_interval.tv_usec = 0; - newTimer.it_value.tv_sec = 0; - newTimer.it_value.tv_usec = delay * 1000; - - setitimer(ITIMER_REAL, &newTimer, NULL); -} diff --git a/gfx/skia/src/views/views_files.mk b/gfx/skia/src/views/views_files.mk deleted file mode 100644 index 9c5e9e0fc640..000000000000 --- a/gfx/skia/src/views/views_files.mk +++ /dev/null @@ -1,26 +0,0 @@ -SOURCE := \ - SkEvent.cpp \ - SkEventSink.cpp \ - SkOSMenu.cpp \ - SkTagList.cpp \ - SkView.cpp \ - SkViewPriv.cpp \ - SkWindow.cpp \ - SkTouchGesture.cpp -# SkBGViewArtist.cpp \ - SkMetaData.cpp \ - SkListView.cpp \ - SkListWidget.cpp \ - SkParsePaint.cpp \ - SkProgressBarView.cpp \ - SkProgressView.cpp \ - SkScrollBarView.cpp \ - SkStackViewLayout.cpp \ - SkStaticTextView.cpp \ - SkTextBox.cpp \ - SkViewInflate.cpp \ - SkWidget.cpp \ - SkWidgetViews.cpp \ - SkWidgets.cpp \ -# SkBorderView.cpp \ -# SkImageView.cpp \ diff --git a/gfx/skia/src/xml/xml_files.mk b/gfx/skia/src/xml/xml_files.mk deleted file mode 100644 index d4342dd2ef1b..000000000000 --- a/gfx/skia/src/xml/xml_files.mk +++ /dev/null @@ -1,3 +0,0 @@ -SOURCE := \ - SkDOM.cpp \ - SkXMLParser.cpp diff --git a/gfx/skia/include/animator/SkAnimator.h b/gfx/skia/trunk/include/animator/SkAnimator.h similarity index 100% rename from gfx/skia/include/animator/SkAnimator.h rename to gfx/skia/trunk/include/animator/SkAnimator.h diff --git a/gfx/skia/include/animator/SkAnimatorView.h b/gfx/skia/trunk/include/animator/SkAnimatorView.h similarity index 100% rename from gfx/skia/include/animator/SkAnimatorView.h rename to gfx/skia/trunk/include/animator/SkAnimatorView.h diff --git a/gfx/skia/include/config/SkUserConfig.h b/gfx/skia/trunk/include/config/SkUserConfig.h similarity index 79% rename from gfx/skia/include/config/SkUserConfig.h rename to gfx/skia/trunk/include/config/SkUserConfig.h index c965e919b3f3..66efdd325f75 100644 --- a/gfx/skia/include/config/SkUserConfig.h +++ b/gfx/skia/trunk/include/config/SkUserConfig.h @@ -37,22 +37,6 @@ /////////////////////////////////////////////////////////////////////////////// -/* Scalars (the fractional value type in skia) can be implemented either as - floats or 16.16 integers (fixed). Exactly one of these two symbols must be - defined. -*/ -//#define SK_SCALAR_IS_FLOAT -//#define SK_SCALAR_IS_FIXED - - -/* For some performance-critical scalar operations, skia will optionally work - around the standard float operators if it knows that the CPU does not have - native support for floats. If your environment uses software floating point, - define this flag. - */ -//#define SK_SOFTWARE_FLOAT - - /* Skia has lots of debug-only code. Often this is just null checks or other parameter checking, but sometimes it can be quite intrusive (e.g. check that each 32bit pixel is in premultiplied form). This code can be very useful @@ -79,7 +63,7 @@ allow instance count tracking in either debug or release builds. By default it is enabled in debug but disabled in release. */ -//#define SK_ENABLE_INST_COUNT 1 +#define SK_ENABLE_INST_COUNT 0 /* If, in debugging mode, Skia needs to stop (presumably to invoke a debugger) it will call SK_CRASH(). If this is not defined it, it is defined in @@ -104,12 +88,6 @@ //#define SK_UINT8_BITFIELD_LENDIAN -/* Some compilers don't support long long for 64bit integers. If yours does - not, define this to the appropriate type. - */ -//#define SkLONGLONG int64_t - - /* To write debug messages to a console, skia will call SkDebugf(...) following printf conventions (e.g. const char* format, ...). If you want to redirect this to something other than printf, define yours here @@ -122,10 +100,12 @@ */ //#define SK_DEFAULT_FONT_CACHE_LIMIT (1024 * 1024) -/* If defined, use CoreText instead of ATSUI on OS X. -*/ -//#define SK_USE_MAC_CORE_TEXT - +/* + * To specify the default size of the image cache, undefine this and set it to + * the desired value (in bytes). SkGraphics.h as a runtime API to set this + * value as well. If this is undefined, a built-in value will be used. + */ +//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024) /* If zlib is available and you want to support the flate compression algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the @@ -144,17 +124,6 @@ */ //#define SK_SFNTLY_SUBSETTER "sfntly/subsetter/font_subsetter.h" -/* Define this to remove dimension checks on bitmaps. Not all blits will be - correct yet, so this is mostly for debugging the implementation. - */ -#define SK_ALLOW_OVER_32K_BITMAPS - -/** - * To revert to int-only srcrect behavior in drawBitmapRect(ToRect), - * define this symbol. - */ -//#define SK_SUPPORT_INT_SRCRECT_DRAWBITMAPRECT - /* Define this to set the upper limit for text to support LCD. Values that are very large increase the cost in the font cache and draw slower, without improving readability. If this is undefined, Skia will use its default @@ -201,14 +170,35 @@ */ //#define SK_SUPPORT_GPU 1 -/* Don't dither 32bit gradients, to match what the canvas test suite expects. - */ -#define SK_DISABLE_DITHER_32BIT_GRADIENT -/* Don't include stdint.h on windows as it conflicts with our build system. +/* The PDF generation code uses Path Ops to generate inverse fills and complex + * clipping paths, but at this time, Path Ops is not release ready yet. So, + * the code is hidden behind this #define guard. If you are feeling adventurous + * and want the latest and greatest PDF generation code, uncomment the #define. + * When Path Ops is release ready, the define guards and this user config + * define should be removed entirely. */ -#ifdef SK_BUILD_FOR_WIN32 - #define SK_IGNORE_STDINT_DOT_H -#endif +//#define SK_PDF_USE_PATHOPS +/* Skia uses these defines as the target of include preprocessor directives. + * The header files pointed to by these defines provide declarations and + * possibly inline implementations of threading primitives. + * + * See SkThread.h for documentation on what these includes must contain. + */ +//#define SK_ATOMICS_PLATFORM_H "SkAtomics_xxx.h" +//#define SK_MUTEX_PLATFORM_H "SkMutex_xxx.h" +# if defined(SK_BUILD_FOR_WIN32) +# define SK_ATOMICS_PLATFORM_H "skia/SkAtomics_win.h" +# elif defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) +# define SK_ATOMICS_PLATFORM_H "skia/SkAtomics_android.h" +# else +# define SK_ATOMICS_PLATFORM_H "skia/SkAtomics_sync.h" +# endif + +# if defined(SK_BUILD_FOR_WIN32) +# define SK_MUTEX_PLATFORM_H "skia/SkMutex_win.h" +# else +# define SK_MUTEX_PLATFORM_H "skia/SkMutex_pthread.h" +# endif #endif diff --git a/gfx/skia/include/core/Sk64.h b/gfx/skia/trunk/include/core/Sk64.h similarity index 100% rename from gfx/skia/include/core/Sk64.h rename to gfx/skia/trunk/include/core/Sk64.h diff --git a/gfx/skia/include/core/SkAdvancedTypefaceMetrics.h b/gfx/skia/trunk/include/core/SkAdvancedTypefaceMetrics.h similarity index 94% rename from gfx/skia/include/core/SkAdvancedTypefaceMetrics.h rename to gfx/skia/trunk/include/core/SkAdvancedTypefaceMetrics.h index acfd86e218da..e75365ba31ca 100755 --- a/gfx/skia/include/core/SkAdvancedTypefaceMetrics.h +++ b/gfx/skia/trunk/include/core/SkAdvancedTypefaceMetrics.h @@ -15,7 +15,6 @@ #include "SkString.h" #include "SkTDArray.h" #include "SkTemplates.h" -#include "SkTScopedPtr.h" /** \class SkAdvancedTypefaceMetrics @@ -90,7 +89,7 @@ public: uint16_t fStartId; uint16_t fEndId; SkTDArray fAdvance; - SkTScopedPtr > fNext; + SkAutoTDelete > fNext; }; struct VerticalMetric { @@ -102,12 +101,12 @@ public: typedef AdvanceMetric VerticalAdvanceRange; // This is indexed by glyph id. - SkTScopedPtr fGlyphWidths; + SkAutoTDelete fGlyphWidths; // Only used for Vertical CID fonts. - SkTScopedPtr fVerticalMetrics; + SkAutoTDelete fVerticalMetrics; // The names of each glyph, only populated for postscript fonts. - SkTScopedPtr > fGlyphNames; + SkAutoTDelete > fGlyphNames; // The mapping from glyph to Unicode, only populated if // kToUnicode_PerGlyphInfo is passed to GetAdvancedTypefaceMetrics. @@ -125,7 +124,7 @@ void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric* range, template SkAdvancedTypefaceMetrics::AdvanceMetric* appendRange( - SkTScopedPtr >* nextSlot, + SkAutoTDelete >* nextSlot, int startId); template diff --git a/gfx/skia/include/core/SkAnnotation.h b/gfx/skia/trunk/include/core/SkAnnotation.h similarity index 72% rename from gfx/skia/include/core/SkAnnotation.h rename to gfx/skia/trunk/include/core/SkAnnotation.h index 18ee1cd1a659..872bb941a5dc 100644 --- a/gfx/skia/include/core/SkAnnotation.h +++ b/gfx/skia/trunk/include/core/SkAnnotation.h @@ -8,10 +8,12 @@ #ifndef SkAnnotation_DEFINED #define SkAnnotation_DEFINED -#include "SkFlattenable.h" +#include "SkRefCnt.h" +#include "SkString.h" class SkData; -class SkDataSet; +class SkReadBuffer; +class SkWriteBuffer; class SkStream; class SkWStream; struct SkPoint; @@ -20,40 +22,24 @@ struct SkPoint; * Experimental class for annotating draws. Do not use directly yet. * Use helper functions at the bottom of this file for now. */ -class SkAnnotation : public SkFlattenable { +class SkAnnotation : public SkRefCnt { public: - enum Flags { - // If set, the associated drawing primitive should not be drawn - kNoDraw_Flag = 1 << 0, - }; - - SkAnnotation(SkDataSet*, uint32_t flags); + SkAnnotation(const char key[], SkData* value); virtual ~SkAnnotation(); - uint32_t getFlags() const { return fFlags; } - SkDataSet* getDataSet() const { return fDataSet; } - - bool isNoDraw() const { return SkToBool(fFlags & kNoDraw_Flag); } - /** - * Helper for search the annotation's dataset. + * Return the data for the specified key, or NULL. */ - SkData* find(const char name[]) const; + SkData* find(const char key[]) const; - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAnnotation) - -protected: - SkAnnotation(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkAnnotation(SkReadBuffer&); + void writeToBuffer(SkWriteBuffer&) const; private: - SkDataSet* fDataSet; - uint32_t fFlags; + SkString fKey; + SkData* fData; - void writeToStream(SkWStream*) const; - void readFromStream(SkStream*); - - typedef SkFlattenable INHERITED; + typedef SkRefCnt INHERITED; }; /** diff --git a/gfx/skia/include/core/SkBitmap.h b/gfx/skia/trunk/include/core/SkBitmap.h similarity index 71% rename from gfx/skia/include/core/SkBitmap.h rename to gfx/skia/trunk/include/core/SkBitmap.h index 124525e249ea..42ef8778bfcf 100644 --- a/gfx/skia/include/core/SkBitmap.h +++ b/gfx/skia/trunk/include/core/SkBitmap.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,13 +5,12 @@ * found in the LICENSE file. */ - #ifndef SkBitmap_DEFINED #define SkBitmap_DEFINED -#include "Sk64.h" #include "SkColor.h" #include "SkColorTable.h" +#include "SkImageInfo.h" #include "SkPoint.h" #include "SkRefCnt.h" @@ -20,11 +18,11 @@ struct SkIRect; struct SkRect; class SkPaint; class SkPixelRef; +class SkPixelRefFactory; class SkRegion; class SkString; -// This is an opaque class, not interpreted by skia -class SkGpuTexture; +class GrTexture; /** \class SkBitmap @@ -38,29 +36,21 @@ class SkGpuTexture; */ class SK_API SkBitmap { public: - class Allocator; + class SK_API Allocator; enum Config { kNo_Config, //!< bitmap has not been configured - /** - * 1-bit per pixel, (0 is transparent, 1 is opaque) - * Valid as a destination (target of a canvas), but not valid as a src. - * i.e. you can draw into a 1-bit bitmap, but you cannot draw from one. - */ - kA1_Config, kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque) kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing) kARGB_4444_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing) kARGB_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing) - /** - * Custom compressed format, not supported on all platforms. - * Cannot be used as a destination (target of a canvas). - * i.e. you may be able to draw from one, but you cannot draw into one. - */ - kRLE_Index8_Config, + }; - kConfigCount + // do not add this to the Config enum, otherwise the compiler will let us + // pass this as a valid parameter for Config. + enum { + kConfigCount = kARGB_8888_Config + 1 }; /** @@ -89,49 +79,72 @@ public: // This method is not exported to java. void swap(SkBitmap& other); - /** Return true iff the bitmap has empty dimensions. - */ - bool empty() const { return 0 == fWidth || 0 == fHeight; } + /////////////////////////////////////////////////////////////////////////// - /** Return true iff the bitmap has no pixelref. Note: this can return true even if the - dimensions of the bitmap are > 0 (see empty()). - */ - bool isNull() const { return NULL == fPixelRef; } + const SkImageInfo& info() const { return fInfo; } - /** Return the config for the bitmap. - */ - Config config() const { return (Config)fConfig; } - /** DEPRECATED, use config() - */ - Config getConfig() const { return this->config(); } - /** Return the bitmap's width, in pixels. - */ - int width() const { return fWidth; } - /** Return the bitmap's height, in pixels. - */ - int height() const { return fHeight; } - /** Return the number of bytes between subsequent rows of the bitmap. - */ - size_t rowBytes() const { return fRowBytes; } - - /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for - 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0 - for configs that are not at least 1-byte per pixel (e.g. kA1_Config - or kNo_Config) - */ - int shiftPerPixel() const { return fBytesPerPixel >> 1; } + int width() const { return fInfo.fWidth; } + int height() const { return fInfo.fHeight; } + SkColorType colorType() const { return fInfo.fColorType; } + SkAlphaType alphaType() const { return fInfo.fAlphaType; } /** Return the number of bytes per pixel based on the config. If the config - does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned. - */ - int bytesPerPixel() const { return fBytesPerPixel; } + does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned. + */ + int bytesPerPixel() const { return fInfo.bytesPerPixel(); } /** Return the rowbytes expressed as a number of pixels (like width and - height). Note, for 1-byte per pixel configs like kA8_Config, this will - return the same as rowBytes(). Is undefined for configs that are less - than 1-byte per pixel (e.g. kA1_Config) - */ - int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); } + height). Note, for 1-byte per pixel configs like kA8_Config, this will + return the same as rowBytes(). Is undefined for configs that are less + than 1-byte per pixel (e.g. kA1_Config) + */ + int rowBytesAsPixels() const { + return fRowBytes >> this->shiftPerPixel(); + } + + /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for + 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0 + for configs that are not at least 1-byte per pixel (e.g. kA1_Config + or kNo_Config) + */ + int shiftPerPixel() const { return this->bytesPerPixel() >> 1; } + + /////////////////////////////////////////////////////////////////////////// + + /** Return true iff the bitmap has empty dimensions. + * Hey! Before you use this, see if you really want to know drawsNothing() instead. + */ + bool empty() const { return fInfo.isEmpty(); } + + /** Return true iff the bitmap has no pixelref. Note: this can return true even if the + * dimensions of the bitmap are > 0 (see empty()). + * Hey! Before you use this, see if you really want to know drawsNothing() instead. + */ + bool isNull() const { return NULL == fPixelRef; } + + /** Return true iff drawing this bitmap has no effect. + */ + bool drawsNothing() const { return this->empty() || this->isNull(); } + + /** Return the config for the bitmap. */ + Config config() const; + + SK_ATTR_DEPRECATED("use config()") + Config getConfig() const { return this->config(); } + + /** Return the number of bytes between subsequent rows of the bitmap. */ + size_t rowBytes() const { return fRowBytes; } + + /** + * Set the bitmap's alphaType, returning true on success. If false is + * returned, then the specified new alphaType is incompatible with the + * Config, and the current alphaType is unchanged. + * + * Note: this changes the alphatype for the underlying pixels, which means + * that all bitmaps that might be sharing (subsets of) the pixels will + * be affected. + */ + bool setAlphaType(SkAlphaType); /** Return the address of the pixels for this SkBitmap. */ @@ -141,27 +154,29 @@ public: Note this truncates the result to 32bits. Call getSize64() to detect if the real size exceeds 32bits. */ - size_t getSize() const { return fHeight * fRowBytes; } + size_t getSize() const { return fInfo.fHeight * fRowBytes; } /** Return the number of bytes from the pointer returned by getPixels() to the end of the allocated space in the buffer. Required in cases where extractSubset has been called. */ - size_t getSafeSize() const ; + size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } - /** Return the byte size of the pixels, based on the height and rowBytes. - This routine is slightly slower than getSize(), but does not truncate - the answer to 32bits. - */ - Sk64 getSize64() const { - Sk64 size; - size.setMul(fHeight, fRowBytes); - return size; + /** + * Return the full size of the bitmap, in bytes. + */ + int64_t computeSize64() const { + return sk_64_mul(fInfo.fHeight, fRowBytes); } - /** Same as getSafeSize(), but does not truncate the answer to 32bits. - */ - Sk64 getSafeSize64() const ; + /** + * Return the number of bytes from the pointer returned by getPixels() + * to the end of the allocated space in the buffer. This may be smaller + * than computeSize64() if there is any rowbytes padding beyond the width. + */ + int64_t computeSafeSize64() const { + return fInfo.getSafeSize64(fRowBytes); + } /** Returns true if this bitmap is marked as immutable, meaning that the contents of its pixels will not change for the lifetime of the bitmap. @@ -178,12 +193,9 @@ public: /** Returns true if the bitmap is opaque (has no translucent/transparent pixels). */ - bool isOpaque() const; - - /** Specify if this bitmap's pixels are all opaque or not. Is only meaningful for configs - that support per-pixel alpha (RGB32, A1, A8). - */ - void setIsOpaque(bool); + bool isOpaque() const { + return SkAlphaTypeIsOpaque(this->alphaType()); + } /** Returns true if the bitmap is volatile (i.e. should not be cached by devices.) */ @@ -220,7 +232,7 @@ public: return ComputeBytesPerPixel(c) >> 1; } - static Sk64 ComputeSize64(Config, int width, int height); + static int64_t ComputeSize64(Config, int width, int height); static size_t ComputeSize(Config, int width, int height); /** @@ -229,18 +241,11 @@ public: * it will return false. * * Since this can be an expensive operation, the bitmap stores a flag for - * this (isOpaque, setIsOpaque). Only call this if you need to compute this - * value from "unknown" pixels. + * this (isOpaque). Only call this if you need to compute this value from + * "unknown" pixels. */ static bool ComputeIsOpaque(const SkBitmap&); - /** - * Calls ComputeIsOpaque, and passes its result to setIsOpaque(). - */ - void computeAndSetOpaquePredicate() { - this->setIsOpaque(ComputeIsOpaque(*this)); - } - /** * Return the bitmap's bounds [0, 0, width, height] as an SkRect */ @@ -251,7 +256,72 @@ public: ComputeRowBytes() is called to compute the optimal value. This resets any pixel/colortable ownership, just like reset(). */ - void setConfig(Config, int width, int height, size_t rowBytes = 0); + bool setConfig(Config, int width, int height, size_t rowBytes, SkAlphaType); + + bool setConfig(Config config, int width, int height, size_t rowBytes = 0) { + return this->setConfig(config, width, height, rowBytes, + kPremul_SkAlphaType); + } + + bool setConfig(const SkImageInfo& info, size_t rowBytes = 0); + + /** + * Allocate a pixelref to match the specified image info. If the Factory + * is non-null, call it to allcoate the pixelref. If the ImageInfo requires + * a colortable, then ColorTable must be non-null, and will be ref'd. + * On failure, the bitmap will be set to empty and return false. + */ + bool allocPixels(const SkImageInfo&, SkPixelRefFactory*, SkColorTable*); + + /** + * Allocate a pixelref to match the specified image info, using the default + * allocator. + * On success, the bitmap's pixels will be "locked", and return true. + * On failure, the bitmap will be set to empty and return false. + */ + bool allocPixels(const SkImageInfo& info) { + return this->allocPixels(info, NULL, NULL); + } + + /** + * Legacy helper function, which creates an SkImageInfo from the specified + * config and then calls allocPixels(info). + */ + bool allocConfigPixels(Config, int width, int height, bool isOpaque = false); + + bool allocN32Pixels(int width, int height, bool isOpaque = false) { + SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); + if (isOpaque) { + info.fAlphaType = kOpaque_SkAlphaType; + } + return this->allocPixels(info); + } + + /** + * Install a pixelref that wraps the specified pixels and rowBytes, and + * optional ReleaseProc and context. When the pixels are no longer + * referenced, if ReleaseProc is not null, it will be called with the + * pixels and context as parameters. + * On failure, the bitmap will be set to empty and return false. + */ + bool installPixels(const SkImageInfo&, void* pixels, size_t rowBytes, + void (*ReleaseProc)(void* addr, void* context), + void* context); + + /** + * DEPRECATED: call info(). + */ + bool asImageInfo(SkImageInfo* info) const { + // compatibility: return false for kUnknown + if (kUnknown_SkColorType == this->colorType()) { + return false; + } + if (info) { + *info = this->info(); + } + return true; + } + /** Use this to assign a new pixel address for an existing bitmap. This will automatically release any pixelref previously installed. Only call this if you are handling ownership/lifetime of the pixel memory. @@ -323,18 +393,41 @@ public: */ bool allocPixels(Allocator* allocator, SkColorTable* ctable); - /** Return the current pixelref object, if any - */ + /** + * Return the current pixelref object or NULL if there is none. This does + * not affect the refcount of the pixelref. + */ SkPixelRef* pixelRef() const { return fPixelRef; } - /** Return the offset into the pixelref, if any. Will return 0 if there is - no pixelref installed. - */ - size_t pixelRefOffset() const { return fPixelRefOffset; } - /** Assign a pixelref and optional offset. Pixelrefs are reference counted, - so the existing one (if any) will be unref'd and the new one will be - ref'd. - */ - SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset = 0); + + /** + * A bitmap can reference a subset of a pixelref's pixels. That means the + * bitmap's width/height can be <= the dimensions of the pixelref. The + * pixelref origin is the x,y location within the pixelref's pixels for + * the bitmap's top/left corner. To be valid the following must be true: + * + * origin_x + bitmap_width <= pixelref_width + * origin_y + bitmap_height <= pixelref_height + * + * pixelRefOrigin() returns this origin, or (0,0) if there is no pixelRef. + */ + SkIPoint pixelRefOrigin() const { return fPixelRefOrigin; } + + /** + * Assign a pixelref and origin to the bitmap. Pixelrefs are reference, + * so the existing one (if any) will be unref'd and the new one will be + * ref'd. (x,y) specify the offset within the pixelref's pixels for the + * top/left corner of the bitmap. For a bitmap that encompases the entire + * pixels of the pixelref, these will be (0,0). + */ + SkPixelRef* setPixelRef(SkPixelRef* pr, int dx, int dy); + + SkPixelRef* setPixelRef(SkPixelRef* pr, const SkIPoint& origin) { + return this->setPixelRef(pr, origin.fX, origin.fY); + } + + SkPixelRef* setPixelRef(SkPixelRef* pr) { + return this->setPixelRef(pr, 0, 0); + } /** Call this to ensure that the bitmap points to the current pixel address in the pixelref. Balance it with a call to unlockPixels(). These calls @@ -362,16 +455,16 @@ public: */ bool readyToDraw() const { return this->getPixels() != NULL && - ((this->config() != kIndex8_Config && - this->config() != kRLE_Index8_Config) || - fColorTable != NULL); + (this->config() != kIndex8_Config || NULL != fColorTable); } /** Returns the pixelRef's texture, or NULL */ - SkGpuTexture* getTexture() const; + GrTexture* getTexture() const; - /** Return the bitmap's colortable (if any). Does not affect the colortable's + /** Return the bitmap's colortable, if it uses one (i.e. colorType is + Index_8) and the pixels are locked. + Otherwise returns NULL. Does not affect the colortable's reference count. */ SkColorTable* getColorTable() const { return fColorTable; } @@ -389,28 +482,38 @@ public: */ void notifyPixelsChanged() const; - /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format - for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is ignored. - If the config is kA8_Config, then the r,g,b parameters are ignored. - */ - void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const; - /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format - for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is presumed - to be 0xFF. If the config is kA8_Config, then the r,g,b parameters are ignored and the - pixels are all set to 0xFF. - */ - void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const { - this->eraseARGB(0xFF, r, g, b); - } - /** Initialize the bitmap's pixels with the specified color, automatically converting into the correct format - for the bitmap's config. If the config is kRGB_565_Config, then the color's alpha value is presumed - to be 0xFF. If the config is kA8_Config, then only the color's alpha value is used. - */ + /** + * Fill the entire bitmap with the specified color. + * If the bitmap's config does not support alpha (e.g. 565) then the alpha + * of the color is ignored (treated as opaque). If the config only supports + * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored. + */ void eraseColor(SkColor c) const { this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); } + /** + * Fill the entire bitmap with the specified color. + * If the bitmap's config does not support alpha (e.g. 565) then the alpha + * of the color is ignored (treated as opaque). If the config only supports + * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored. + */ + void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const; + + SK_ATTR_DEPRECATED("use eraseARGB or eraseColor") + void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const { + this->eraseARGB(0xFF, r, g, b); + } + + /** + * Fill the specified area of this bitmap with the specified color. + * If the bitmap's config does not support alpha (e.g. 565) then the alpha + * of the color is ignored (treated as opaque). If the config only supports + * alpha (e.g. A1 or A8) then the color's r,g,b components are ignored. + */ + void eraseArea(const SkIRect& area, SkColor c) const; + /** Scroll (a subset of) the contents of this bitmap by dx/dy. If there are no pixels allocated (i.e. getPixels() returns null) the method will still update the inval region (if present). If the bitmap is immutable, @@ -475,14 +578,6 @@ public: */ inline uint8_t* getAddr8(int x, int y) const; - /** Returns the address of the byte containing the pixel specified by x,y - * for 1bit pixels. - * In debug build, this asserts that the pixels are allocated and locked, - * and that the config is 1-bit, however none of these checks are performed - * in the release build. - */ - inline uint8_t* getAddr1(int x, int y) const; - /** Returns the color corresponding to the pixel specified by x,y for * colortable based bitmaps. * In debug build, this asserts that the pixels are allocated and locked, @@ -532,15 +627,8 @@ public: */ bool canCopyTo(Config newConfig) const; - bool hasMipMap() const; + SK_ATTR_DEPRECATED("use setFilterLevel on SkPaint") void buildMipMap(bool forceRebuild = false); - void freeMipMap(); - - /** Given scale factors sx, sy, determine the miplevel available in the - bitmap, and return it (this is the amount to shift matrix iterators - by). If dst is not null, it is set to the correct level. - */ - int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy); #ifdef SK_BUILD_FOR_ANDROID bool hasHardwareMipMap() const { @@ -588,8 +676,8 @@ public: buffers as they can optimize the recording process and avoid recording duplicate bitmaps and pixelRefs. */ - void flatten(SkFlattenableWriteBuffer&) const; - void unflatten(SkFlattenableReadBuffer&); + void flatten(SkWriteBuffer&) const; + void unflatten(SkReadBuffer&); SkDEBUGCODE(void validate() const;) @@ -615,7 +703,7 @@ public: */ class HeapAllocator : public Allocator { public: - virtual bool allocPixelRef(SkBitmap*, SkColorTable*); + virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE; }; class RLEPixels { @@ -646,13 +734,13 @@ private: mutable MipMap* fMipMap; mutable SkPixelRef* fPixelRef; - mutable size_t fPixelRefOffset; mutable int fPixelLockCount; - // either user-specified (in which case it is not treated as mutable) - // or a cache of the returned value from fPixelRef->lockPixels() + // These are just caches from the locked pixelref mutable void* fPixels; mutable SkColorTable* fColorTable; // only meaningful for kIndex8 + SkIPoint fPixelRefOrigin; + enum Flags { kImageIsOpaque_Flag = 0x01, kImageIsVolatile_Flag = 0x02, @@ -666,19 +754,20 @@ private: #endif }; + SkImageInfo fInfo; + uint32_t fRowBytes; - uint32_t fWidth; - uint32_t fHeight; - uint8_t fConfig; + uint8_t fFlags; - uint8_t fBytesPerPixel; // based on config + + void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const; /* Internal computations for safe size. */ - static Sk64 ComputeSafeSize64(Config config, - uint32_t width, - uint32_t height, - size_t rowBytes); + static int64_t ComputeSafeSize64(Config config, + uint32_t width, + uint32_t height, + size_t rowBytes); static size_t ComputeSafeSize(Config config, uint32_t width, uint32_t height, @@ -690,6 +779,16 @@ private: void updatePixelsFromRef() const; static SkFixed ComputeMipLevel(SkFixed sx, SkFixed dy); + + /** Given scale factors sx, sy, determine the miplevel available in the + bitmap, and return it (this is the amount to shift matrix iterators + by). If dst is not null, it is set to the correct level. + */ + int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy); + bool hasMipMap() const; + void freeMipMap(); + + friend struct SkBitmapProcState; }; class SkAutoLockPixels : public SkNoncopyable { @@ -710,6 +809,8 @@ private: const SkBitmap& fBitmap; bool fDidLock; }; +//TODO(mtklein): uncomment when 71713004 lands and Chromium's fixed. +//#define SkAutoLockPixels(...) SK_REQUIRE_LOCAL_VAR(SkAutoLockPixels) /** Helper class that performs the lock/unlockColors calls on a colortable. The destructor will call unlockColors(false) if it has a bitmap's colortable @@ -734,7 +835,7 @@ public: } ~SkAutoLockColors() { if (fCTable) { - fCTable->unlockColors(false); + fCTable->unlockColors(); } } @@ -748,7 +849,7 @@ public: */ const SkPMColor* lockColors(SkColorTable* ctable) { if (fCTable) { - fCTable->unlockColors(false); + fCTable->unlockColors(); } fCTable = ctable; fColors = ctable ? ctable->lockColors() : NULL; @@ -763,44 +864,37 @@ private: SkColorTable* fCTable; const SkPMColor* fColors; }; +#define SkAutoLockColors(...) SK_REQUIRE_LOCAL_VAR(SkAutoLockColors) /////////////////////////////////////////////////////////////////////////////// inline uint32_t* SkBitmap::getAddr32(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kARGB_8888_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kARGB_8888_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2)); } inline uint16_t* SkBitmap::getAddr16(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kRGB_565_Config || this->config() == kARGB_4444_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1)); } inline uint8_t* SkBitmap::getAddr8(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kA8_Config || this->config() == kIndex8_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint8_t*)fPixels + y * fRowBytes + x; } inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kIndex8_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kIndex8_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); SkASSERT(fColorTable); return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)]; } -// returns the address of the byte that contains the x coordinate -inline uint8_t* SkBitmap::getAddr1(int x, int y) const { - SkASSERT(fPixels); - SkASSERT(fConfig == kA1_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); - return (uint8_t*)fPixels + y * fRowBytes + (x >> 3); -} - #endif diff --git a/gfx/skia/trunk/include/core/SkBitmapDevice.h b/gfx/skia/trunk/include/core/SkBitmapDevice.h new file mode 100644 index 000000000000..e4f9b88a5e68 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkBitmapDevice.h @@ -0,0 +1,287 @@ + +/* + * 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 SkBitmapDevice_DEFINED +#define SkBitmapDevice_DEFINED + +#include "SkDevice.h" + +/////////////////////////////////////////////////////////////////////////////// +class SK_API SkBitmapDevice : public SkBaseDevice { +public: + SK_DECLARE_INST_COUNT(SkBitmapDevice) + + /** + * Construct a new device with the specified bitmap as its backend. It is + * valid for the bitmap to have no pixels associated with it. In that case, + * any drawing to this device will have no effect. + */ + SkBitmapDevice(const SkBitmap& bitmap); + + /** + * Construct a new device with the specified bitmap as its backend. It is + * valid for the bitmap to have no pixels associated with it. In that case, + * any drawing to this device will have no effect. + */ + SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties); + + /** + * Create a new raster device and have the pixels be automatically + * allocated. The rowBytes of the device will be computed automatically + * based on the config and the width. + * + * @param config The desired config for the pixels. If the request cannot + * be met, the closest matching support config will be used. + * @param width width (in pixels) of the device + * @param height height (in pixels) of the device + * @param isOpaque Set to true if it is known that all of the pixels will + * be drawn to opaquely. Used as an accelerator when drawing + * these pixels to another device. + */ + SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false); + + /** + * Create a new raster device and have the pixels be automatically + * allocated. The rowBytes of the device will be computed automatically + * based on the config and the width. + * + * @param config The desired config for the pixels. If the request cannot + * be met, the closest matching support config will be used. + * @param width width (in pixels) of the device + * @param height height (in pixels) of the device + * @param isOpaque Set to true if it is known that all of the pixels will + * be drawn to opaquely. Used as an accelerator when drawing + * these pixels to another device. + * @param deviceProperties Properties which affect compositing. + */ + SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque, + const SkDeviceProperties& deviceProperties); + + virtual ~SkBitmapDevice(); + + virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; } + + /** Return the width of the device (in pixels). + */ + virtual int width() const SK_OVERRIDE { return fBitmap.width(); } + /** Return the height of the device (in pixels). + */ + virtual int height() const SK_OVERRIDE { return fBitmap.height(); } + + /** Returns true if the device's bitmap's config treats every pixels as + implicitly opaque. + */ + virtual bool isOpaque() const SK_OVERRIDE { return fBitmap.isOpaque(); } + + /** Return the bitmap config of the device's pixels + */ + virtual SkBitmap::Config config() const SK_OVERRIDE { return fBitmap.config(); } + + /** + * DEPRECATED: This will be made protected once WebKit stops using it. + * Instead use Canvas' writePixels method. + * + * Similar to draw sprite, this method will copy the pixels in bitmap onto + * the device, with the top/left corner specified by (x, y). The pixel + * values in the device are completely replaced: there is no blending. + * + * Currently if bitmap is backed by a texture this is a no-op. This may be + * relaxed in the future. + * + * If the bitmap has config kARGB_8888_Config then the config8888 param + * will determines how the pixel valuess are intepreted. If the bitmap is + * not kARGB_8888_Config then this parameter is ignored. + */ + virtual void writePixels(const SkBitmap& bitmap, int x, int y, + SkCanvas::Config8888 config8888) SK_OVERRIDE; + + /** + * Return the device's associated gpu render target, or NULL. + */ + virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } + +protected: + /** + * Device may filter the text flags for drawing text here. If it wants to + * make a change to the specified values, it should write them into the + * textflags parameter (output) and return true. If the paint is fine as + * is, then ignore the textflags parameter and return false. + * + * The baseclass SkDevice filters based on its depth and blitters. + */ + virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE; + + /** Clears the entire device to the specified color (including alpha). + * Ignores the clip. + */ + virtual void clear(SkColor color) SK_OVERRIDE; + + /** These are called inside the per-device-layer loop for each draw call. + When these are called, we have already applied any saveLayer operations, + and are handling any looping from the paint, and any effects from the + DrawFilter. + */ + virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE; + virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, + const SkPoint[], const SkPaint& paint) SK_OVERRIDE; + virtual void drawRect(const SkDraw&, const SkRect& r, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawOval(const SkDraw&, const SkRect& oval, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawRRect(const SkDraw&, const SkRRect& rr, + const SkPaint& paint) SK_OVERRIDE; + + /** + * If pathIsMutable, then the implementation is allowed to cast path to a + * non-const pointer and modify it in place (as an optimization). Canvas + * may do this to implement helpers such as drawOval, by placing a temp + * path on the stack to hold the representation of the oval. + * + * If prePathMatrix is not null, it should logically be applied before any + * stroking or other effects. If there are no effects on the paint that + * affect the geometry/rasterization, then the pre matrix can just be + * pre-concated with the current matrix. + */ + virtual void drawPath(const SkDraw&, const SkPath& path, + const SkPaint& paint, + const SkMatrix* prePathMatrix = NULL, + bool pathIsMutable = false) SK_OVERRIDE; + virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, + const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE; + virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, + int x, int y, const SkPaint& paint) SK_OVERRIDE; + + /** + * The default impl. will create a bitmap-shader from the bitmap, + * and call drawRect with it. + */ + virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, + const SkRect* srcOrNull, const SkRect& dst, + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; + + /** + * Does not handle text decoration. + * Decorations (underline and stike-thru) will be handled by SkCanvas. + */ + virtual void drawText(const SkDraw&, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE; + virtual void drawPosText(const SkDraw&, const void* text, size_t len, + const SkScalar pos[], SkScalar constY, + int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE; + virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, + const SkPoint verts[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint) SK_OVERRIDE; + /** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to + onCreateCompatibleDevice on this device with kSaveLayer_Usage. + */ + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, + const SkPaint&) SK_OVERRIDE; + + /////////////////////////////////////////////////////////////////////////// + + /** Update as needed the pixel value in the bitmap, so that the caller can + access the pixels directly. Note: only the pixels field should be + altered. The config/width/height/rowbytes must remain unchanged. + @return the device contents as a bitmap + */ + virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE; + + SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } + // just for subclasses, to assign a custom pixelref + SkPixelRef* setPixelRef(SkPixelRef* pr) { + fBitmap.setPixelRef(pr); + return pr; + } + + /** + * Implements readPixels API. The caller will ensure that: + * 1. bitmap has pixel config kARGB_8888_Config. + * 2. bitmap has pixels. + * 3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is + * contained in the device bounds. + */ + virtual bool onReadPixels(const SkBitmap& bitmap, + int x, int y, + SkCanvas::Config8888 config8888) SK_OVERRIDE; + + /** Called when this device is installed into a Canvas. Balanced by a call + to unlockPixels() when the device is removed from a Canvas. + */ + virtual void lockPixels() SK_OVERRIDE; + virtual void unlockPixels() SK_OVERRIDE; + + /** + * Returns true if the device allows processing of this imagefilter. If + * false is returned, then the filter is ignored. This may happen for + * some subclasses that do not support pixel manipulations after drawing + * has occurred (e.g. printing). The default implementation returns true. + */ + virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE; + + /** + * Override and return true for filters that the device can handle + * intrinsically. Doing so means that SkCanvas will pass-through this + * filter to drawSprite and drawDevice (and potentially filterImage). + * Returning false means the SkCanvas will have apply the filter itself, + * and just pass the resulting image to the device. + */ + virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE; + + /** + * Related (but not required) to canHandleImageFilter, this method returns + * true if the device could apply the filter to the src bitmap and return + * the result (and updates offset as needed). + * If the device does not recognize or support this filter, + * it just returns false and leaves result and offset unchanged. + */ + virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; + +private: + friend class SkCanvas; + friend struct DeviceCM; //for setMatrixClip + friend class SkDraw; + friend class SkDrawIter; + friend class SkDeviceFilteredPaint; + friend class SkDeviceImageFilterProxy; + + friend class SkSurface_Raster; + + void init(SkBitmap::Config config, int width, int height, bool isOpaque); + + // used to change the backend's pixels (and possibly config/rowbytes) + // but cannot change the width/height, so there should be no change to + // any clip information. + virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE; + + /** + * Subclasses should override this to implement createCompatibleDevice. + */ + virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) SK_OVERRIDE; + + /** Causes any deferred drawing to the device to be completed. + */ + virtual void flush() SK_OVERRIDE {} + + virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE; + + SkBitmap fBitmap; + + typedef SkBaseDevice INHERITED; +}; + +#endif // SkBitmapDevice_DEFINED diff --git a/gfx/skia/include/core/SkBlitRow.h b/gfx/skia/trunk/include/core/SkBlitRow.h similarity index 98% rename from gfx/skia/include/core/SkBlitRow.h rename to gfx/skia/trunk/include/core/SkBlitRow.h index febc405f2910..501134238f6d 100644 --- a/gfx/skia/include/core/SkBlitRow.h +++ b/gfx/skia/trunk/include/core/SkBlitRow.h @@ -92,7 +92,6 @@ public: static Proc32 PlatformProcs32(unsigned flags); static Proc PlatformProcs565(unsigned flags); - static Proc PlatformProcs4444(unsigned flags); static ColorProc PlatformColorProc(); private: diff --git a/gfx/skia/include/core/SkBounder.h b/gfx/skia/trunk/include/core/SkBounder.h similarity index 100% rename from gfx/skia/include/core/SkBounder.h rename to gfx/skia/trunk/include/core/SkBounder.h diff --git a/gfx/skia/include/core/SkCanvas.h b/gfx/skia/trunk/include/core/SkCanvas.h similarity index 88% rename from gfx/skia/include/core/SkCanvas.h rename to gfx/skia/trunk/include/core/SkCanvas.h index 1e7e8280b211..7235efb2f0a9 100644 --- a/gfx/skia/include/core/SkCanvas.h +++ b/gfx/skia/trunk/include/core/SkCanvas.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkCanvas_DEFINED #define SkCanvas_DEFINED @@ -18,17 +16,18 @@ #include "SkRefCnt.h" #include "SkPath.h" #include "SkRegion.h" -#include "SkScalarCompare.h" #include "SkXfermode.h" class SkBounder; -class SkDevice; +class SkBaseDevice; class SkDraw; class SkDrawFilter; class SkMetaData; class SkPicture; class SkRRect; +class SkSurface; class SkSurface_Base; +class GrContext; /** \class SkCanvas @@ -49,15 +48,26 @@ class SK_API SkCanvas : public SkRefCnt { public: SK_DECLARE_INST_COUNT(SkCanvas) + /** + * Creates an empty canvas with no backing device/pixels, and zero + * dimensions. + */ SkCanvas(); + /** + * Creates a canvas of the specified dimensions, but explicitly not backed + * by any device/pixels. Typically this use used by subclasses who handle + * the draw calls in some other way. + */ + SkCanvas(int width, int height); + /** Construct a canvas with the specified device to draw into. @param device Specifies a device for the canvas to draw into. */ - explicit SkCanvas(SkDevice* device); + explicit SkCanvas(SkBaseDevice* device); - /** Deprecated - Construct a canvas with the specified bitmap to draw into. + /** Construct a canvas with the specified bitmap to draw into. @param bitmap Specifies a bitmap for the canvas to draw into. Its structure are copied to the canvas. */ @@ -84,7 +94,7 @@ public: the bitmap of the pixels that the canvas draws into. The reference count of the returned device is not changed by this call. */ - SkDevice* getDevice() const; + SkBaseDevice* getDevice() const; /** * saveLayer() can create another device (which is later drawn onto @@ -99,15 +109,19 @@ public: * is drawn to, but is optional here, as there is a small perf hit * sometimes. */ - SkDevice* getTopDevice(bool updateMatrixClip = false) const; + SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const; /** - * Shortcut for getDevice()->createCompatibleDevice(...). - * If getDevice() == NULL, this method does nothing, and returns NULL. + * Create a new surface matching the specified info, one that attempts to + * be maximally compatible when used with this canvas. */ - SkDevice* createCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque); + SkSurface* newSurface(const SkImageInfo&); + + /** + * Return the GPU context of the device that is associated with the canvas. + * For a canvas with non-GPU device, NULL is returned. + */ + GrContext* getGrContext(); /////////////////////////////////////////////////////////////////////////// @@ -239,6 +253,12 @@ public: operate on this copy. When the balancing call to restore() is made, the previous matrix, clip, and drawFilter are restored. + @param flags The flags govern what portion of the Matrix/Clip/drawFilter + state the save (and matching restore) effect. For example, + if only kMatrix is specified, then only the matrix state + will be pushed and popped. Likewise for the clip if kClip + is specified. However, the drawFilter is always affected + by calls to save/restore. @return The value to pass to restoreToCount() to balance this save() */ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag); @@ -381,6 +401,13 @@ public: fAllowSoftClip = allow; } + /** EXPERIMENTAL -- only used for testing + Set to simplify clip stack using path ops. + */ + void setAllowSimplifyClip(bool allow) { + fAllowSimplifyClip = allow; + } + /** Modify the current clip with the specified region. Note that unlike clipRect() and clipPath() which transform their arguments by the current matrix, clipRegion() assumes its argument is already in device @@ -435,14 +462,13 @@ public: not intersect the current clip) */ bool quickRejectY(SkScalar top, SkScalar bottom) const { - SkASSERT(SkScalarToCompareType(top) <= SkScalarToCompareType(bottom)); - const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); + SkASSERT(top <= bottom); + const SkRect& clipR = this->getLocalClipBounds(); // In the case where the clip is empty and we are provided with a // negative top and positive bottom parameter then this test will return // false even though it will be clipped. We have chosen to exclude that // check as it is rare and would result double the comparisons. - return SkScalarToCompareType(top) >= clipR.fBottom - || SkScalarToCompareType(bottom) <= clipR.fTop; + return top >= clipR.fBottom || bottom <= clipR.fTop; } /** Return the bounds of the current clip (in local coordinates) in the @@ -652,6 +678,11 @@ public: bitmap's original width/height, then the bitmap will be drawn as if it were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be the edge color replicated. + + If a shader is present on the paint it will be ignored, except in the + case where the bitmap is kA8_Config. In that case, the color is + generated by the shader. + @param bitmap The bitmap to be drawn @param left The position of the left side of the bitmap being drawn @param top The position of the top side of the bitmap being drawn @@ -660,6 +691,16 @@ public: virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint = NULL); + enum DrawBitmapRectFlags { + kNone_DrawBitmapRectFlag = 0x0, + /** + * When filtering is enabled, allow the color samples outside of + * the src rect (but still in the src bitmap) to bleed into the + * drawn portion + */ + kBleed_DrawBitmapRectFlag = 0x1, + }; + /** Draw the specified bitmap, with the specified matrix applied (before the canvas' matrix is applied). @param bitmap The bitmap to be drawn @@ -670,22 +711,24 @@ public: */ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, - const SkPaint* paint); + const SkPaint* paint = NULL, + DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag); void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, - const SkPaint* paint) { - this->drawBitmapRectToRect(bitmap, NULL, dst, paint); + const SkPaint* paint = NULL) { + this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag); } void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc, - const SkRect& dst, const SkPaint* paint = NULL) { + const SkRect& dst, const SkPaint* paint = NULL, + DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) { SkRect realSrcStorage; SkRect* realSrcPtr = NULL; if (isrc) { realSrcStorage.set(*isrc); realSrcPtr = &realSrcStorage; } - this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint); + this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags); } virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, @@ -698,9 +741,9 @@ public: * bitmap is the "center", then the center-rect should be [2, 2, 3, 3]. * * If the dst is >= the bitmap size, then... - * - The 4 corners are not stretch at all. - * - The sides are stretch in only one axis. - * - The center is stretch in both axes. + * - The 4 corners are not stretched at all. + * - The sides are stretched in only one axis. + * - The center is stretched in both axes. * Else, for each axis where dst < bitmap, * - The corners shrink proportionally * - The sides (along the shrink axis) and center are not drawn @@ -786,21 +829,6 @@ public: const SkPath& path, const SkMatrix* matrix, const SkPaint& paint); -#ifdef SK_BUILD_FOR_ANDROID - /** Draw the text on path, with each character/glyph origin specified by the pos[] - array. The origin is interpreted by the Align setting in the paint. - @param text The text to be drawn - @param byteLength The number of bytes to read from the text parameter - @param pos Array of positions, used to position each character - @param paint The paint used for the text (e.g. color, size, style) - @param path The path to draw on - @param matrix The canvas matrix - */ - void drawPosTextOnPath(const void* text, size_t byteLength, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix); -#endif - /** Draw the picture into this canvas. This method effective brackets the playback of the picture's draw calls with save/restore, so the state of this canvas will be unchanged after this call. @@ -821,7 +849,7 @@ public: corresponding texs and colors arrays if non-null) @param vertices Array of vertices for the mesh @param texs May be null. If not null, specifies the coordinate - in texture space for each vertex. + in _texture_ space (not uv space) for each vertex. @param colors May be null. If not null, specifies a color for each vertex, to be interpolated across the triangle. @param xmode Used if both texs and colors are present. In this @@ -845,7 +873,24 @@ public: subclasses like SkPicture's recording canvas, that can store the data and then play it back later (via another call to drawData). */ - virtual void drawData(const void* data, size_t length); + virtual void drawData(const void* data, size_t length) { + // do nothing. Subclasses may do something with the data + } + + /** Add comments. beginCommentGroup/endCommentGroup open/close a new group. + Each comment added via addComment is notionally attached to its + enclosing group. Top-level comments simply belong to no group. + */ + virtual void beginCommentGroup(const char* description) { + // do nothing. Subclasses may do something + } + virtual void addComment(const char* kywd, const char* value) { + // do nothing. Subclasses may do something + } + virtual void endCommentGroup() { + // do nothing. Subclasses may do something + } + ////////////////////////////////////////////////////////////////////////// @@ -900,11 +945,10 @@ public: */ ClipType getClipType() const; - /** Return the current device clip (concatenation of all clip calls). + /** DEPRECATED -- need to move this guy to private/friend + * Return the current device clip (concatenation of all clip calls). * This does not account for the translate in any of the devices. * @return the current device clip (concatenation of all clip calls). - * - * DEPRECATED -- call getClipDeviceBounds() instead. */ const SkRegion& getTotalClip() const; @@ -952,7 +996,7 @@ public: // These reflect the current device in the iterator - SkDevice* device() const; + SkBaseDevice* device() const; const SkMatrix& matrix() const; const SkRegion& clip() const; const SkPaint& paint() const; @@ -972,27 +1016,34 @@ public: }; protected: + // default impl defers to getDevice()->newSurface(info) + virtual SkSurface* onNewSurface(const SkImageInfo&); + // Returns the canvas to be used by DrawIter. Default implementation // returns this. Subclasses that encapsulate an indirect canvas may // need to overload this method. The impl must keep track of this, as it // is not released or deleted by the caller. virtual SkCanvas* canvasForDrawIter(); - // all of the drawBitmap variants call this guy - void commonDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix&, - const SkPaint& paint); - // Clip rectangle bounds. Called internally by saveLayer. // returns false if the entire rectangle is entirely clipped out + // If non-NULL, The imageFilter parameter will be used to expand the clip + // and offscreen bounds for any margin required by the filter DAG. bool clipRectBounds(const SkRect* bounds, SaveFlags flags, - SkIRect* intersection); + SkIRect* intersection, + const SkImageFilter* imageFilter = NULL); + + // Called by child classes that override clipPath and clipRRect to only + // track fast conservative clip bounds, rather than exact clips. + bool updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op, + bool inverseFilled); // notify our surface (if we have one) that we are about to draw, so it // can perform copy-on-write or invalidate any cached images void predrawNotify(); - /** DEPRECATED -- use constructor(device) - + /** + DEPRECATED -- need to remove when subclass stop relying on it. Marked as 'protected' to avoid new clients using this before we can completely remove it. @@ -1000,7 +1051,7 @@ protected: reference count is incremented. If the canvas was already holding a device, its reference count is decremented. The new device is returned. */ - virtual SkDevice* setDevice(SkDevice* device); + virtual SkBaseDevice* setDevice(SkBaseDevice* device); private: class MCRec; @@ -1023,6 +1074,7 @@ private: fSurfaceBase = sb; } friend class SkSurface_Base; + friend class SkSurface_Gpu; bool fDeviceCMDirty; // cleared by updateDeviceCMCache() void updateDeviceCMCache(); @@ -1030,23 +1082,23 @@ private: friend class SkDrawIter; // needs setupDrawForLayerDevice() friend class AutoDrawLooper; - SkDevice* createLayerDevice(SkBitmap::Config, int width, int height, - bool isOpaque); + SkBaseDevice* createLayerDevice(SkBitmap::Config, int width, int height, + bool isOpaque); - SkDevice* init(SkDevice*); + SkBaseDevice* init(SkBaseDevice*); // internal methods are not virtual, so they can safely be called by other // canvas apis, without confusing subclasses (like SkPictureRecording) - void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m, - const SkPaint* paint); + void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint); void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint); + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags); void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint); void internalDrawPaint(const SkPaint& paint); int internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags, bool justForImageFilter); - void internalDrawDevice(SkDevice*, int x, int y, const SkPaint*); + void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*); // shared by save() and saveLayer() int internalSave(SaveFlags flags); @@ -1060,18 +1112,20 @@ private: /* These maintain a cache of the clip bounds in local coordinates, (converted to 2s-compliment if floats are slow). */ - mutable SkRectCompareType fLocalBoundsCompareType; - mutable bool fLocalBoundsCompareTypeDirty; + mutable SkRect fCachedLocalClipBounds; + mutable bool fCachedLocalClipBoundsDirty; bool fAllowSoftClip; + bool fAllowSimplifyClip; - const SkRectCompareType& getLocalClipBoundsCompareType() const { - if (fLocalBoundsCompareTypeDirty) { - this->computeLocalClipBoundsCompareType(); - fLocalBoundsCompareTypeDirty = false; + const SkRect& getLocalClipBounds() const { + if (fCachedLocalClipBoundsDirty) { + if (!this->getClipBounds(&fCachedLocalClipBounds)) { + fCachedLocalClipBounds.setEmpty(); + } + fCachedLocalClipBoundsDirty = false; } - return fLocalBoundsCompareType; + return fCachedLocalClipBounds; } - void computeLocalClipBoundsCompareType() const; class AutoValidateClip : ::SkNoncopyable { public: @@ -1099,11 +1153,12 @@ private: */ class SkAutoCanvasRestore : SkNoncopyable { public: - SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) { - SkASSERT(canvas); - fSaveCount = canvas->getSaveCount(); - if (doSave) { - canvas->save(); + SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) { + if (fCanvas) { + fSaveCount = canvas->getSaveCount(); + if (doSave) { + canvas->save(); + } } } ~SkAutoCanvasRestore() { @@ -1127,5 +1182,28 @@ private: SkCanvas* fCanvas; int fSaveCount; }; +#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore) + +/** Stack helper class to automatically open and close a comment block + */ +class SkAutoCommentBlock : SkNoncopyable { +public: + SkAutoCommentBlock(SkCanvas* canvas, const char* description) { + fCanvas = canvas; + if (NULL != fCanvas) { + fCanvas->beginCommentGroup(description); + } + } + + ~SkAutoCommentBlock() { + if (NULL != fCanvas) { + fCanvas->endCommentGroup(); + } + } + +private: + SkCanvas* fCanvas; +}; +#define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock) #endif diff --git a/gfx/skia/include/core/SkChecksum.h b/gfx/skia/trunk/include/core/SkChecksum.h similarity index 64% rename from gfx/skia/include/core/SkChecksum.h rename to gfx/skia/trunk/include/core/SkChecksum.h index 9cb45c33071b..bf3228f91db8 100644 --- a/gfx/skia/include/core/SkChecksum.h +++ b/gfx/skia/trunk/include/core/SkChecksum.h @@ -10,6 +10,15 @@ #include "SkTypes.h" +/** + * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant + * to be very very fast, as it is used internally by the font cache, in + * conjuction with the entire raw key. This algorithm does not generate + * unique values as well as others (e.g. MD5) but it performs much faster. + * Skia's use cases can survive non-unique values (since the entire key is + * always available). Clients should only be used in circumstances where speed + * over uniqueness is at a premium. + */ class SkChecksum : SkNoncopyable { private: /* @@ -27,6 +36,42 @@ private: } public: + + /** + * Calculate 32-bit Murmur hash (murmur3). + * This should take 2-3x longer than SkChecksum::Compute, but is a considerably better hash. + * See en.wikipedia.org/wiki/MurmurHash. + * + * @param data Memory address of the data block to be processed. Must be 32-bit aligned. + * @param size Size of the data block in bytes. Must be a multiple of 4. + * @param seed Initial hash seed. (optional) + * @return hash result + */ + static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) { + SkASSERT(SkIsAlign4(bytes)); + const size_t words = bytes/4; + + uint32_t hash = seed; + for (size_t i = 0; i < words; i++) { + uint32_t k = data[i]; + k *= 0xcc9e2d51; + k = (k << 15) | (k >> 17); + k *= 0x1b873593; + + hash ^= k; + hash = (hash << 13) | (hash >> 19); + hash *= 5; + hash += 0xe6546b64; + } + hash ^= bytes; + hash ^= hash >> 16; + hash *= 0x85ebca6b; + hash ^= hash >> 13; + hash *= 0xc2b2ae35; + hash ^= hash >> 16; + return hash; + } + /** * Compute a 32-bit checksum for a given data block * diff --git a/gfx/skia/include/core/SkChunkAlloc.h b/gfx/skia/trunk/include/core/SkChunkAlloc.h similarity index 94% rename from gfx/skia/include/core/SkChunkAlloc.h rename to gfx/skia/trunk/include/core/SkChunkAlloc.h index 1b52a35c16c0..e13e2b99c640 100644 --- a/gfx/skia/include/core/SkChunkAlloc.h +++ b/gfx/skia/trunk/include/core/SkChunkAlloc.h @@ -42,6 +42,7 @@ public: size_t unalloc(void* ptr); size_t totalCapacity() const { return fTotalCapacity; } + size_t totalUsed() const { return fTotalUsed; } int blockCount() const { return fBlockCount; } /** @@ -58,6 +59,7 @@ private: size_t fMinSize; size_t fChunkSize; size_t fTotalCapacity; + size_t fTotalUsed; // will be <= fTotalCapacity int fBlockCount; Block* newBlock(size_t bytes, AllocFailType ftype); diff --git a/gfx/skia/include/core/SkClipStack.h b/gfx/skia/trunk/include/core/SkClipStack.h similarity index 93% rename from gfx/skia/include/core/SkClipStack.h rename to gfx/skia/trunk/include/core/SkClipStack.h index 256f603962d5..0d6cfb296fc5 100644 --- a/gfx/skia/include/core/SkClipStack.h +++ b/gfx/skia/trunk/include/core/SkClipStack.h @@ -109,7 +109,7 @@ public: stack not to the element itself. That is the same clip path in different stacks will have a different ID since the elements produce different clip result in the context of their stacks. */ - int32_t getGenID() const { return fGenID; } + int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGenID; } /** * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape @@ -315,26 +315,13 @@ public: */ bool isWideOpen() const; - /** - * Add a callback function that will be called whenever a clip state - * is no longer viable. This will occur whenever restore - * is called or when a clipDevRect or clipDevPath call updates the - * clip within an existing save/restore state. Each clip state is - * represented by a unique generation ID. - */ - typedef void (*PFPurgeClipCB)(int genID, void* data); - void addPurgeClipCallback(PFPurgeClipCB callback, void* data) const; - - /** - * Remove a callback added earlier via addPurgeClipCallback - */ - void removePurgeClipCallback(PFPurgeClipCB callback, void* data) const; - /** * The generation ID has three reserved values to indicate special * (potentially ignorable) cases */ - static const int32_t kInvalidGenID = 0; + static const int32_t kInvalidGenID = 0; //!< Invalid id that is never returned by + //!< SkClipStack. Useful when caching clips + //!< based on GenID. static const int32_t kEmptyGenID = 1; // no pixels writeable static const int32_t kWideOpenGenID = 2; // all pixels writeable @@ -440,22 +427,10 @@ private: // invalid ID. static int32_t gGenID; - struct ClipCallbackData { - PFPurgeClipCB fCallback; - void* fData; - - friend bool operator==(const ClipCallbackData& a, - const ClipCallbackData& b) { - return a.fCallback == b.fCallback && a.fData == b.fData; - } - }; - - mutable SkTDArray fCallbackData; - /** - * Invoke all the purge callbacks passing in element's generation ID. + * Restore the stack back to the specified save count. */ - void purgeClip(Element* element); + void restoreTo(int saveCount); /** * Return the next unique generation ID. diff --git a/gfx/skia/include/core/SkColor.h b/gfx/skia/trunk/include/core/SkColor.h similarity index 97% rename from gfx/skia/include/core/SkColor.h rename to gfx/skia/trunk/include/core/SkColor.h index dafc59676d2f..7faeca7f84b3 100644 --- a/gfx/skia/include/core/SkColor.h +++ b/gfx/skia/trunk/include/core/SkColor.h @@ -73,6 +73,9 @@ static inline SkColor SkColorSetA(SkColor c, U8CPU a) { // common colors +#define SK_AlphaTRANSPARENT 0x00 //!< transparent SkAlpha value +#define SK_AlphaOPAQUE 0xFF //!< opaque SkAlpha value + #define SK_ColorTRANSPARENT 0x00000000 //!< transparent SkColor value #define SK_ColorBLACK 0xFF000000 //!< black SkColor value diff --git a/gfx/skia/include/core/SkColorFilter.h b/gfx/skia/trunk/include/core/SkColorFilter.h similarity index 90% rename from gfx/skia/include/core/SkColorFilter.h rename to gfx/skia/trunk/include/core/SkColorFilter.h index 65a8cf33c293..a5ffca818dee 100644 --- a/gfx/skia/include/core/SkColorFilter.h +++ b/gfx/skia/trunk/include/core/SkColorFilter.h @@ -18,6 +18,14 @@ class SkBitmap; class GrEffectRef; class GrContext; +/** + * ColorFilters are optional objects in the drawing pipeline. When present in + * a paint, they are called with the "src" colors, and return new colors, which + * are then passed onto the next stage (either ImageFilter or Xfermode). + * + * All subclasses are required to be reentrant-safe : it must be legal to share + * the same instance between several threads. + */ class SK_API SkColorFilter : public SkFlattenable { public: SK_DECLARE_INST_COUNT(SkColorFilter) @@ -120,10 +128,14 @@ public: */ virtual GrEffectRef* asNewEffect(GrContext*) const; + SkDEVCODE(virtual void toString(SkString* str) const = 0;) + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkColorFilter) + protected: SkColorFilter() {} - SkColorFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {} + SkColorFilter(SkReadBuffer& rb) : INHERITED(rb) {} private: typedef SkFlattenable INHERITED; diff --git a/gfx/skia/include/core/SkColorPriv.h b/gfx/skia/trunk/include/core/SkColorPriv.h similarity index 90% rename from gfx/skia/include/core/SkColorPriv.h rename to gfx/skia/trunk/include/core/SkColorPriv.h index 46f7d2718440..7a74c4a034b2 100644 --- a/gfx/skia/include/core/SkColorPriv.h +++ b/gfx/skia/trunk/include/core/SkColorPriv.h @@ -269,36 +269,90 @@ static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, } /** - * 32b optimized version; currently appears to be 10% faster even on 64b - * architectures than an equivalent 64b version and 30% faster than - * SkFourByteInterp(). Third parameter controls blending of the first two: - * (src, dst, 0) returns dst - * (src, dst, 0xFF) returns src - * ** Does not match the results of SkFourByteInterp() because we use - * a more accurate scale computation! - * TODO: migrate Skia function to using an accurate 255->266 alpha - * conversion. + * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB + */ +static inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) { + const uint32_t mask = 0x00FF00FF; + *ag = (color >> 8) & mask; + *rb = color & mask; +} + +/** + * 0xAARRGGBB -> 0x00AA00GG00RR00BB + * (note, ARGB -> AGRB) + */ +static inline uint64_t SkSplay(uint32_t color) { + const uint32_t mask = 0x00FF00FF; + uint64_t agrb = (color >> 8) & mask; // 0x0000000000AA00GG + agrb <<= 32; // 0x00AA00GG00000000 + agrb |= color & mask; // 0x00AA00GG00RR00BB + return agrb; +} + +/** + * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB + */ +static inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) { + const uint32_t mask = 0xFF00FF00; + return (ag & mask) | ((rb & mask) >> 8); +} + +/** + * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB + * (note, AGRB -> ARGB) + */ +static inline uint32_t SkUnsplay(uint64_t agrb) { + const uint32_t mask = 0xFF00FF00; + return SkPMColor( + ((agrb & mask) >> 8) | // 0x00RR00BB + ((agrb >> 32) & mask)); // 0xAARRGGBB +} + +static inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) { + SkASSERT(scale <= 256); + + // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide. + uint32_t src_ag, src_rb, dst_ag, dst_rb; + SkSplay(src, &src_ag, &src_rb); + SkSplay(dst, &dst_ag, &dst_rb); + + const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag; + const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb; + + return SkUnsplay(ret_ag, ret_rb); +} + +static inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) { + SkASSERT(scale <= 256); + // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide. + return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst)); +} + +// TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere. + +/** + * Same as SkFourByteInterp256, but faster. + */ +static inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) { + // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine. + if (sizeof(void*) == 4) { + return SkFastFourByteInterp256_32(src, dst, scale); + } else { + return SkFastFourByteInterp256_64(src, dst, scale); + } +} + +/** + * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better + * srcWeight scaling to [0, 256]. */ static inline SkPMColor SkFastFourByteInterp(SkPMColor src, SkPMColor dst, U8CPU srcWeight) { - SkASSERT(srcWeight < 256); - - // Reorders ARGB to AG-RB in order to reduce the number of operations. - const uint32_t mask = 0xFF00FF; - uint32_t src_rb = src & mask; - uint32_t src_ag = (src >> 8) & mask; - uint32_t dst_rb = dst & mask; - uint32_t dst_ag = (dst >> 8) & mask; - + SkASSERT(srcWeight <= 255); // scale = srcWeight + (srcWeight >> 7) is more accurate than // scale = srcWeight + 1, but 7% slower - int scale = srcWeight + (srcWeight >> 7); - - uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb; - uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag; - - return (ret_ag & ~mask) | ((ret_rb & ~mask) >> 8); + return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7)); } /** @@ -313,9 +367,9 @@ static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) static inline SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { SkA32Assert(a); - SkA32Assert(r); - SkA32Assert(g); - SkA32Assert(b); + SkR32Assert(r); + SkG32Assert(g); + SkB32Assert(b); if (a != 255) { r = SkMulDiv255Round(r, a); @@ -329,7 +383,6 @@ SK_API extern const uint32_t gMask_00FF00FF; static inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) { uint32_t mask = gMask_00FF00FF; -// uint32_t mask = 0xFF00FF; uint32_t rb = ((c & mask) * scale) >> 8; uint32_t ag = ((c >> 8) & mask) * scale; @@ -833,29 +886,29 @@ static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB, SkBlend32(srcB, dstB, maskB)); } -static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t src[], - SkColor color, int width, SkPMColor) { - int srcA = SkColorGetA(color); - int srcR = SkColorGetR(color); - int srcG = SkColorGetG(color); - int srcB = SkColorGetB(color); +static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[], + SkColor src, int width, SkPMColor) { + int srcA = SkColorGetA(src); + int srcR = SkColorGetR(src); + int srcG = SkColorGetG(src); + int srcB = SkColorGetB(src); srcA = SkAlpha255To256(srcA); for (int i = 0; i < width; i++) { - dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], src[i]); + dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]); } } -static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t src[], - SkColor color, int width, +static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[], + SkColor src, int width, SkPMColor opaqueDst) { - int srcR = SkColorGetR(color); - int srcG = SkColorGetG(color); - int srcB = SkColorGetB(color); + int srcR = SkColorGetR(src); + int srcG = SkColorGetG(src); + int srcB = SkColorGetB(src); for (int i = 0; i < width; i++) { - dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], src[i], + dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i], opaqueDst); } } diff --git a/gfx/skia/include/core/SkColorShader.h b/gfx/skia/trunk/include/core/SkColorShader.h similarity index 95% rename from gfx/skia/include/core/SkColorShader.h rename to gfx/skia/trunk/include/core/SkColorShader.h index c3790682e4b0..5b8a86dfc1b0 100644 --- a/gfx/skia/include/core/SkColorShader.h +++ b/gfx/skia/trunk/include/core/SkColorShader.h @@ -52,8 +52,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorShader) protected: - SkColorShader(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkColorShader(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: diff --git a/gfx/skia/trunk/include/core/SkColorTable.h b/gfx/skia/trunk/include/core/SkColorTable.h new file mode 100644 index 000000000000..e4c8c86c13dd --- /dev/null +++ b/gfx/skia/trunk/include/core/SkColorTable.h @@ -0,0 +1,94 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkColorTable_DEFINED +#define SkColorTable_DEFINED + +#include "SkColor.h" +#include "SkFlattenable.h" +#include "SkImageInfo.h" + +/** \class SkColorTable + + SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by + 8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable. +*/ +class SkColorTable : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkColorTable) + + /** Makes a deep copy of colors. + */ + SkColorTable(const SkColorTable& src); + SkColorTable(const SkPMColor colors[], int count, + SkAlphaType alphaType = kPremul_SkAlphaType); + virtual ~SkColorTable(); + + SkAlphaType alphaType() const { return (SkAlphaType)fAlphaType; } + + bool isOpaque() const { + return SkAlphaTypeIsOpaque(this->alphaType()); + } + + /** Returns the number of colors in the table. + */ + int count() const { return fCount; } + + /** Returns the specified color from the table. In the debug build, this asserts that + the index is in range (0 <= index < count). + */ + SkPMColor operator[](int index) const { + SkASSERT(fColors != NULL && (unsigned)index < fCount); + return fColors[index]; + } + + /** + * Return the array of colors for reading. This must be balanced by a call + * to unlockColors(). + */ + const SkPMColor* lockColors() { + SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);) + return fColors; + } + + /** + * Balancing call to lockColors(). + */ + void unlockColors(); + + /** Similar to lockColors(), lock16BitCache() returns the array of + RGB16 colors that mirror the 32bit colors. However, this function + will return null if kColorsAreOpaque_Flag is not set. + Also, unlike lockColors(), the returned array here cannot be modified. + */ + const uint16_t* lock16BitCache(); + /** Balancing call to lock16BitCache(). + */ + void unlock16BitCache() { + SkASSERT(f16BitCacheLockCount > 0); + SkDEBUGCODE(f16BitCacheLockCount -= 1); + } + + explicit SkColorTable(SkReadBuffer&); + void writeToBuffer(SkWriteBuffer&) const; + +private: + SkPMColor* fColors; + uint16_t* f16BitCache; + uint16_t fCount; + uint8_t fAlphaType; + SkDEBUGCODE(int fColorLockCount;) + SkDEBUGCODE(int f16BitCacheLockCount;) + + void inval16BitCache(); + + typedef SkRefCnt INHERITED; +}; + +#endif diff --git a/gfx/skia/include/core/SkComposeShader.h b/gfx/skia/trunk/include/core/SkComposeShader.h similarity index 93% rename from gfx/skia/include/core/SkComposeShader.h rename to gfx/skia/trunk/include/core/SkComposeShader.h index 524161b785b1..1fefd1369a1c 100644 --- a/gfx/skia/include/core/SkComposeShader.h +++ b/gfx/skia/trunk/include/core/SkComposeShader.h @@ -43,8 +43,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader) protected: - SkComposeShader(SkFlattenableReadBuffer& ); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkComposeShader(SkReadBuffer& ); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: diff --git a/gfx/skia/include/core/SkData.h b/gfx/skia/trunk/include/core/SkData.h similarity index 70% rename from gfx/skia/include/core/SkData.h rename to gfx/skia/trunk/include/core/SkData.h index 06edb020d80e..bee0fcdfa286 100644 --- a/gfx/skia/include/core/SkData.h +++ b/gfx/skia/trunk/include/core/SkData.h @@ -11,14 +11,16 @@ #ifndef SkData_DEFINED #define SkData_DEFINED -#include "SkFlattenable.h" +#include "SkRefCnt.h" + +struct SkFILE; /** * SkData holds an immutable data buffer. Not only is the data immutable, * but the actual ptr that is returned (by data() or bytes()) is guaranteed * to always be the same for the life of this instance. */ -class SK_API SkData : public SkFlattenable { +class SK_API SkData : public SkRefCnt { public: SK_DECLARE_INST_COUNT(SkData) @@ -89,10 +91,28 @@ public: static SkData* NewFromMalloc(const void* data, size_t length); /** - * Create a new dataref from a pointer allocated by mmap. The Data object - * will handle calling munmap(). + * Create a new dataref the file with the specified path. + * If the file cannot be opened, this returns NULL. */ - static SkData* NewFromMMap(const void* data, size_t length); + static SkData* NewFromFileName(const char path[]); + + /** + * Create a new dataref from a SkFILE. + * This does not take ownership of the SkFILE, nor close it. + * The caller is free to close the SkFILE at its convenience. + * The SkFILE must be open for reading only. + * Returns NULL on failure. + */ + static SkData* NewFromFILE(SkFILE* f); + + /** + * Create a new dataref from a file descriptor. + * This does not take ownership of the file descriptor, nor close it. + * The caller is free to close the file descriptor at its convenience. + * The file descriptor must be open for reading only. + * Returns NULL on failure. + */ + static SkData* NewFromFD(int fd); /** * Create a new dataref using a subset of the data in the specified @@ -106,12 +126,6 @@ public: */ static SkData* NewEmpty(); - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkData) - -protected: - SkData(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - private: ReleaseProc fReleaseProc; void* fReleaseProcContext; @@ -122,41 +136,13 @@ private: SkData(const void* ptr, size_t size, ReleaseProc, void* context); virtual ~SkData(); - // This is here because SkAutoTUnref creates an internal helper class - // that derives from SkData (i.e., BlockRef) to prevent refs\unrefs. - // This helper class generates a compiler warning on Windows since the - // SkData's destructor is private. This friending gives the helper class - // access to the destructor. - friend class SkAutoTUnref::BlockRef; + // Called the first time someone calls NewEmpty to initialize the singleton. + static void NewEmptyImpl(int/*unused*/); - typedef SkFlattenable INHERITED; + typedef SkRefCnt INHERITED; }; -/** - * Specialized version of SkAutoTUnref for automatically unref-ing a - * SkData. - */ -class SkAutoDataUnref : SkNoncopyable { -public: - SkAutoDataUnref(SkData* data) : fRef(data) {} - ~SkAutoDataUnref() { - SkSafeUnref(fRef); - } - - SkData* get() const { return fRef; } - - void release() { - if (fRef) { - fRef->unref(); - fRef = NULL; - } - } - - SkData *operator->() const { return fRef; } - operator SkData*() { return fRef; } - -private: - SkData* fRef; -}; +/** Typedef of SkAutoTUnref for automatically unref-ing a SkData. */ +typedef SkAutoTUnref SkAutoDataUnref; #endif diff --git a/gfx/skia/trunk/include/core/SkDataTable.h b/gfx/skia/trunk/include/core/SkDataTable.h new file mode 100644 index 000000000000..9440000e00b4 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkDataTable.h @@ -0,0 +1,177 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkDataTable_DEFINED +#define SkDataTable_DEFINED + +#include "SkChunkAlloc.h" +#include "SkData.h" +#include "SkString.h" +#include "SkTDArray.h" + +/** + * Like SkData, SkDataTable holds an immutable data buffer. The data buffer is + * organized into a table of entries, each with a length, so the entries are + * not required to all be the same size. + */ +class SK_API SkDataTable : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkDataTable) + + /** + * Returns true if the table is empty (i.e. has no entries). + */ + bool isEmpty() const { return 0 == fCount; } + + /** + * Return the number of entries in the table. 0 for an empty table + */ + int count() const { return fCount; } + + /** + * Return the size of the index'th entry in the table. The caller must + * ensure that index is valid for this table. + */ + size_t atSize(int index) const; + + /** + * Return a pointer to the data of the index'th entry in the table. + * The caller must ensure that index is valid for this table. + * + * @param size If non-null, this returns the byte size of this entry. This + * will be the same value that atSize(index) would return. + */ + const void* at(int index, size_t* size = NULL) const; + + template + const T* atT(int index, size_t* size = NULL) const { + return reinterpret_cast(this->at(index, size)); + } + + /** + * Returns the index'th entry as a c-string, and assumes that the trailing + * null byte had been copied into the table as well. + */ + const char* atStr(int index) const { + size_t size; + const char* str = this->atT(index, &size); + SkASSERT(strlen(str) + 1 == size); + return str; + } + + typedef void (*FreeProc)(void* context); + + static SkDataTable* NewEmpty(); + + /** + * Return a new DataTable that contains a copy of the data stored in each + * "array". + * + * @param ptrs array of points to each element to be copied into the table. + * @param sizes array of byte-lengths for each entry in the corresponding + * ptrs[] array. + * @param count the number of array elements in ptrs[] and sizes[] to copy. + */ + static SkDataTable* NewCopyArrays(const void * const * ptrs, + const size_t sizes[], int count); + + /** + * Return a new table that contains a copy of the data in array. + * + * @param array contiguous array of data for all elements to be copied. + * @param elemSize byte-length for a given element. + * @param count the number of entries to be copied out of array. The number + * of bytes that will be copied is count * elemSize. + */ + static SkDataTable* NewCopyArray(const void* array, size_t elemSize, + int count); + + static SkDataTable* NewArrayProc(const void* array, size_t elemSize, + int count, FreeProc proc, void* context); + +private: + struct Dir { + const void* fPtr; + uintptr_t fSize; + }; + + int fCount; + size_t fElemSize; + union { + const Dir* fDir; + const char* fElems; + } fU; + + FreeProc fFreeProc; + void* fFreeProcContext; + + SkDataTable(); + SkDataTable(const void* array, size_t elemSize, int count, + FreeProc, void* context); + SkDataTable(const Dir*, int count, FreeProc, void* context); + virtual ~SkDataTable(); + + friend class SkDataTableBuilder; // access to Dir + + typedef SkRefCnt INHERITED; +}; + +/** + * Helper class that allows for incrementally building up the data needed to + * create a SkDataTable. + */ +class SK_API SkDataTableBuilder : SkNoncopyable { +public: + SkDataTableBuilder(size_t minChunkSize); + ~SkDataTableBuilder(); + + int count() const { return fDir.count(); } + size_t minChunkSize() const { return fMinChunkSize; } + + /** + * Forget any previously appended entries, setting count() back to 0. + */ + void reset(size_t minChunkSize); + void reset() { + this->reset(fMinChunkSize); + } + + /** + * Copy size-bytes from data, and append it to the growing SkDataTable. + */ + void append(const void* data, size_t size); + + /** + * Helper version of append() passes strlen() + 1 for the size, + * so the trailing-zero will be copied as well. + */ + void appendStr(const char str[]) { + this->append(str, strlen(str) + 1); + } + + /** + * Helper version of append() passes string.size() + 1 for the size, + * so the trailing-zero will be copied as well. + */ + void appendString(const SkString& string) { + this->append(string.c_str(), string.size() + 1); + } + + /** + * Return an SkDataTable from the accumulated entries that were added by + * calls to append(). This call also clears any accumluated entries from + * this builder, so its count() will be 0 after this call. + */ + SkDataTable* detachDataTable(); + +private: + SkTDArray fDir; + SkChunkAlloc* fHeap; + size_t fMinChunkSize; +}; + +#endif diff --git a/gfx/skia/include/core/SkDeque.h b/gfx/skia/trunk/include/core/SkDeque.h similarity index 99% rename from gfx/skia/include/core/SkDeque.h rename to gfx/skia/trunk/include/core/SkDeque.h index eef335d0e511..0b3e37f3d099 100644 --- a/gfx/skia/include/core/SkDeque.h +++ b/gfx/skia/trunk/include/core/SkDeque.h @@ -81,7 +81,7 @@ public: void reset(const SkDeque& d, IterStart startLoc); private: - SkDeque::Block* fCurBlock; + SkDeque::Block* fCurBlock; char* fPos; size_t fElemSize; }; diff --git a/gfx/skia/include/core/SkDevice.h b/gfx/skia/trunk/include/core/SkDevice.h similarity index 69% rename from gfx/skia/include/core/SkDevice.h rename to gfx/skia/trunk/include/core/SkDevice.h index 40931091c448..016e2babc88d 100644 --- a/gfx/skia/include/core/SkDevice.h +++ b/gfx/skia/trunk/include/core/SkDevice.h @@ -23,60 +23,23 @@ class SkMatrix; class SkMetaData; class SkRegion; -// This is an opaque class, not interpreted by skia -class SkGpuRenderTarget; +class GrRenderTarget; -class SK_API SkDevice : public SkRefCnt { +class SK_API SkBaseDevice : public SkRefCnt { public: - SK_DECLARE_INST_COUNT(SkDevice) + SK_DECLARE_INST_COUNT(SkBaseDevice) /** - * Construct a new device with the specified bitmap as its backend. It is - * valid for the bitmap to have no pixels associated with it. In that case, - * any drawing to this device will have no effect. + * Construct a new device. */ - SkDevice(const SkBitmap& bitmap); + SkBaseDevice(); /** - * Construct a new device with the specified bitmap as its backend. It is - * valid for the bitmap to have no pixels associated with it. In that case, - * any drawing to this device will have no effect. + * Construct a new device. */ - SkDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties); + SkBaseDevice(const SkDeviceProperties& deviceProperties); - /** - * Create a new raster device and have the pixels be automatically - * allocated. The rowBytes of the device will be computed automatically - * based on the config and the width. - * - * @param config The desired config for the pixels. If the request cannot - * be met, the closest matching support config will be used. - * @param width width (in pixels) of the device - * @param height height (in pixels) of the device - * @param isOpaque Set to true if it is known that all of the pixels will - * be drawn to opaquely. Used as an accelerator when drawing - * these pixels to another device. - */ - SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false); - - /** - * Create a new raster device and have the pixels be automatically - * allocated. The rowBytes of the device will be computed automatically - * based on the config and the width. - * - * @param config The desired config for the pixels. If the request cannot - * be met, the closest matching support config will be used. - * @param width width (in pixels) of the device - * @param height height (in pixels) of the device - * @param isOpaque Set to true if it is known that all of the pixels will - * be drawn to opaquely. Used as an accelerator when drawing - * these pixels to another device. - * @param deviceProperties Properties which affect compositing. - */ - SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque, - const SkDeviceProperties& deviceProperties); - - virtual ~SkDevice(); + virtual ~SkBaseDevice(); /** * Creates a device that is of the same type as this device (e.g. SW-raster, @@ -89,25 +52,23 @@ public: * draw into this device such that all of the pixels will * be opaque. */ - SkDevice* createCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque); + SkBaseDevice* createCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque); SkMetaData& getMetaData(); enum Capabilities { - kGL_Capability = 0x1, //!< mask indicating GL support - kVector_Capability = 0x2, //!< mask indicating a vector representation - kAll_Capabilities = 0x3 + kVector_Capability = 0x1, //!< mask indicating a vector representation }; - virtual uint32_t getDeviceCapabilities() { return 0; } + virtual uint32_t getDeviceCapabilities() = 0; /** Return the width of the device (in pixels). */ - virtual int width() const { return fBitmap.width(); } + virtual int width() const = 0; /** Return the height of the device (in pixels). */ - virtual int height() const { return fBitmap.height(); } + virtual int height() const = 0; /** Return the image properties of the device. */ virtual const SkDeviceProperties& getDeviceProperties() const { @@ -120,16 +81,22 @@ public: * canvas. The root device will have its top-left at 0,0, but other devices * such as those associated with saveLayer may have a non-zero origin. */ - void getGlobalBounds(SkIRect* bounds) const; + void getGlobalBounds(SkIRect* bounds) const { + SkASSERT(bounds); + const SkIPoint& origin = this->getOrigin(); + bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height()); + } - /** Returns true if the device's bitmap's config treats every pixels as + + /** Returns true if the device's bitmap's config treats every pixel as implicitly opaque. */ - bool isOpaque() const { return fBitmap.isOpaque(); } + virtual bool isOpaque() const = 0; /** Return the bitmap config of the device's pixels - */ - SkBitmap::Config config() const { return fBitmap.getConfig(); } + */ + SK_ATTR_DEPRECATED("want to hide configness of the device -- don't use") + virtual SkBitmap::Config config() const = 0; /** Return the bitmap associated with this device. Call this each time you need to access the bitmap, as it notifies the subclass to perform any flushing @@ -155,12 +122,12 @@ public: * not kARGB_8888_Config then this parameter is ignored. */ virtual void writePixels(const SkBitmap& bitmap, int x, int y, - SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888); + SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888) = 0; /** * Return the device's associated gpu render target, or NULL. */ - virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; } + virtual GrRenderTarget* accessRenderTarget() = 0; /** @@ -172,7 +139,7 @@ public: /** * onAttachToCanvas is invoked whenever a device is installed in a canvas * (i.e., setDevice, saveLayer (for the new device created by the save), - * and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the + * and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the * devices to prepare for drawing (e.g., locking their pixels, etc.) */ virtual void onAttachToCanvas(SkCanvas*) { @@ -214,9 +181,9 @@ protected: * textflags parameter (output) and return true. If the paint is fine as * is, then ignore the textflags parameter and return false. * - * The baseclass SkDevice filters based on its depth and blitters. + * The baseclass SkBaseDevice filters based on its depth and blitters. */ - virtual bool filterTextFlags(const SkPaint& paint, TextFlags*); + virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) = 0; /** * @@ -235,16 +202,14 @@ protected: * passed in). */ virtual void setMatrixClip(const SkMatrix&, const SkRegion&, - const SkClipStack&); + const SkClipStack&) {}; /** Clears the entire device to the specified color (including alpha). * Ignores the clip. */ - virtual void clear(SkColor color); + virtual void clear(SkColor color) = 0; - /** - * Deprecated name for clear. - */ + SK_ATTR_DEPRECATED("use clear() instead") void eraseColor(SkColor eraseColor) { this->clear(eraseColor); } /** These are called inside the per-device-layer loop for each draw call. @@ -252,13 +217,16 @@ protected: and are handling any looping from the paint, and any effects from the DrawFilter. */ - virtual void drawPaint(const SkDraw&, const SkPaint& paint); + virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0; virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, - const SkPoint[], const SkPaint& paint); + const SkPoint[], const SkPaint& paint) = 0; virtual void drawRect(const SkDraw&, const SkRect& r, - const SkPaint& paint); + const SkPaint& paint) = 0; virtual void drawOval(const SkDraw&, const SkRect& oval, - const SkPaint& paint); + const SkPaint& paint) = 0; + virtual void drawRRect(const SkDraw&, const SkRRect& rr, + const SkPaint& paint) = 0; + /** * If pathIsMutable, then the implementation is allowed to cast path to a * non-const pointer and modify it in place (as an optimization). Canvas @@ -273,12 +241,11 @@ protected: virtual void drawPath(const SkDraw&, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix = NULL, - bool pathIsMutable = false); + bool pathIsMutable = false) = 0; virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, - const SkMatrix& matrix, const SkPaint& paint); + const SkMatrix& matrix, const SkPaint& paint) = 0; virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint); + int x, int y, const SkPaint& paint) = 0; /** * The default impl. will create a bitmap-shader from the bitmap, @@ -286,35 +253,31 @@ protected: */ virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* srcOrNull, const SkRect& dst, - const SkPaint& paint); + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) = 0; /** * Does not handle text decoration. * Decorations (underline and stike-thru) will be handled by SkCanvas. */ virtual void drawText(const SkDraw&, const void* text, size_t len, - SkScalar x, SkScalar y, const SkPaint& paint); + SkScalar x, SkScalar y, const SkPaint& paint) = 0; virtual void drawPosText(const SkDraw&, const void* text, size_t len, const SkScalar pos[], SkScalar constY, - int scalarsPerPos, const SkPaint& paint); + int scalarsPerPos, const SkPaint& paint) = 0; virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath& path, const SkMatrix* matrix, - const SkPaint& paint); -#ifdef SK_BUILD_FOR_ANDROID - virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix); -#endif + const SkPaint& paint) = 0; virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, const SkPoint verts[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, - const SkPaint& paint); + const SkPaint& paint) = 0; /** The SkDevice passed will be an SkDevice which was returned by a call to onCreateCompatibleDevice on this device with kSaveLayer_Usage. */ - virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, - const SkPaint&); + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, + const SkPaint&) = 0; /** * On success (returns true), copy the device pixels into the bitmap. @@ -350,20 +313,10 @@ protected: /////////////////////////////////////////////////////////////////////////// /** Update as needed the pixel value in the bitmap, so that the caller can - access the pixels directly. Note: only the pixels field should be - altered. The config/width/height/rowbytes must remain unchanged. - @param bitmap The device's bitmap - @return Echo the bitmap parameter, or an alternate (shadow) bitmap - maintained by the subclass. + access the pixels directly. + @return The device contents as a bitmap */ - virtual const SkBitmap& onAccessBitmap(SkBitmap*); - - SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } - // just for subclasses, to assign a custom pixelref - SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) { - fBitmap.setPixelRef(pr, offset); - return pr; - } + virtual const SkBitmap& onAccessBitmap() = 0; /** * Implements readPixels API. The caller will ensure that: @@ -374,13 +327,13 @@ protected: */ virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, - SkCanvas::Config8888 config8888); + SkCanvas::Config8888 config8888) = 0; - /** Called when this device is installed into a Canvas. Balanaced by a call + /** Called when this device is installed into a Canvas. Balanced by a call to unlockPixels() when the device is removed from a Canvas. */ - virtual void lockPixels(); - virtual void unlockPixels(); + virtual void lockPixels() = 0; + virtual void unlockPixels() = 0; /** * Returns true if the device allows processing of this imagefilter. If @@ -388,7 +341,7 @@ protected: * some subclasses that do not support pixel manipulations after drawing * has occurred (e.g. printing). The default implementation returns true. */ - virtual bool allowImageFilter(SkImageFilter*); + virtual bool allowImageFilter(const SkImageFilter*) = 0; /** * Override and return true for filters that the device can handle @@ -397,7 +350,7 @@ protected: * Returning false means the SkCanvas will have apply the filter itself, * and just pass the resulting image to the device. */ - virtual bool canHandleImageFilter(SkImageFilter*); + virtual bool canHandleImageFilter(const SkImageFilter*) = 0; /** * Related (but not required) to canHandleImageFilter, this method returns @@ -406,13 +359,25 @@ protected: * If the device does not recognize or support this filter, * it just returns false and leaves result and offset unchanged. */ - virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&, - SkBitmap* result, SkIPoint* offset); + virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) = 0; // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if // either is identical to kNative_Premul_Config8888. Otherwise, -1. static const SkCanvas::Config8888 kPMColorAlias; +protected: + // default impl returns NULL + virtual SkSurface* newSurface(const SkImageInfo&); + + /** + * Leaky properties are those which the device should be applying but it isn't. + * These properties will be applied by the draw, when and as it can. + * If the device does handle a property, that property should be set to the identity value + * for that property, effectively making it non-leaky. + */ + SkDeviceProperties fLeakyProperties; + private: friend class SkCanvas; friend struct DeviceCM; //for setMatrixClip @@ -420,42 +385,37 @@ private: friend class SkDrawIter; friend class SkDeviceFilteredPaint; friend class SkDeviceImageFilterProxy; + friend class DeferredDevice; // for newSurface friend class SkSurface_Raster; + // used to change the backend's pixels (and possibly config/rowbytes) // but cannot change the width/height, so there should be no change to // any clip information. - void replaceBitmapBackendForRasterSurface(const SkBitmap&); + // TODO: move to SkBitmapDevice + virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) = 0; // just called by SkCanvas when built as a layer void setOrigin(int x, int y) { fOrigin.set(x, y); } // just called by SkCanvas for saveLayer - SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config, - int width, int height, - bool isOpaque); + SkBaseDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config, + int width, int height, + bool isOpaque); /** * Subclasses should override this to implement createCompatibleDevice. */ - virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque, - Usage usage); + virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) = 0; /** Causes any deferred drawing to the device to be completed. */ - virtual void flush() {} + virtual void flush() = 0; - SkBitmap fBitmap; SkIPoint fOrigin; SkMetaData* fMetaData; - /** - * Leaky properties are those which the device should be applying but it isn't. - * These properties will be applied by the draw, when and as it can. - * If the device does handle a property, that property should be set to the identity value - * for that property, effectively making it non-leaky. - */ - SkDeviceProperties fLeakyProperties; #ifdef SK_DEBUG bool fAttachedToCanvas; diff --git a/gfx/skia/include/core/SkDeviceProperties.h b/gfx/skia/trunk/include/core/SkDeviceProperties.h similarity index 96% rename from gfx/skia/include/core/SkDeviceProperties.h rename to gfx/skia/trunk/include/core/SkDeviceProperties.h index 4382f539584e..fd573f41e957 100644 --- a/gfx/skia/include/core/SkDeviceProperties.h +++ b/gfx/skia/trunk/include/core/SkDeviceProperties.h @@ -46,10 +46,10 @@ struct SkDeviceProperties { }; Orientation getOrientation() { - return static_cast(fGeometry | kOrientationMask); + return static_cast(fGeometry & kOrientationMask); } Layout getLayout() { - return static_cast(fGeometry | kLayoutMask); + return static_cast(fGeometry & kLayoutMask); } bool isOrientationKnown() { diff --git a/gfx/skia/include/core/SkDither.h b/gfx/skia/trunk/include/core/SkDither.h similarity index 100% rename from gfx/skia/include/core/SkDither.h rename to gfx/skia/trunk/include/core/SkDither.h diff --git a/gfx/skia/trunk/include/core/SkDocument.h b/gfx/skia/trunk/include/core/SkDocument.h new file mode 100644 index 000000000000..dbf4bc5957e7 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkDocument.h @@ -0,0 +1,140 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkDocument_DEFINED +#define SkDocument_DEFINED + +#include "SkBitmap.h" +#include "SkPicture.h" +#include "SkRect.h" +#include "SkRefCnt.h" + +class SkCanvas; +class SkWStream; + +/** SK_ScalarDefaultDPI is 72 DPI. +*/ +#define SK_ScalarDefaultRasterDPI 72.0f + +/** + * High-level API for creating a document-based canvas. To use.. + * + * 1. Create a document, specifying a stream to store the output. + * 2. For each "page" of content: + * a. canvas = doc->beginPage(...) + * b. draw_my_content(canvas); + * c. doc->endPage(); + * 3. Close the document with doc->close(). + */ +class SkDocument : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkDocument) + + /** + * Create a PDF-backed document, writing the results into a file. + * If there is an error trying to create the doc, returns NULL. + * encoder sets the DCTEncoder for images, to encode a bitmap + * as JPEG (DCT). + * rasterDpi - the DPI at which features without native PDF support + * will be rasterized (e.g. draw image with perspective, + * draw text with perspective, ...) + * A larger DPI would create a PDF that reflects the original + * intent with better fidelity, but it can make for larger + * PDF files too, which would use more memory while rendering, + * and it would be slower to be processed or sent online or + * to printer. + */ + static SkDocument* CreatePDF( + const char filename[], + SkPicture::EncodeBitmap encoder = NULL, + SkScalar rasterDpi = SK_ScalarDefaultRasterDPI); + + /** + * Create a PDF-backed document, writing the results into a stream. + * If there is an error trying to create the doc, returns NULL. + * + * The document may write to the stream at anytime during its lifetime, + * until either close() is called or the document is deleted. Once close() + * has been called, and all of the data has been written to the stream, + * if there is a Done proc provided, it will be called with the stream. + * The proc can delete the stream, or whatever it needs to do. + * encoder sets the DCTEncoder for images, to encode a bitmap + * as JPEG (DCT). + * Done - clean up method intended to allow deletion of the stream. + * Its aborted parameter is true if the cleanup is due to an abort + * call. It is false otherwise. + * rasterDpi - the DPI at which features without native PDF support + * will be rasterized (e.g. draw image with perspective, + * draw text with perspective, ...) + * A larger DPI would create a PDF that reflects the original + * intent with better fidelity, but it can make for larger + * PDF files too, which would use more memory while rendering, + * and it would be slower to be processed or sent online or + * to printer. */ + static SkDocument* CreatePDF( + SkWStream*, void (*Done)(SkWStream*,bool aborted) = NULL, + SkPicture::EncodeBitmap encoder = NULL, + SkScalar rasterDpi = SK_ScalarDefaultRasterDPI); + + /** + * Begin a new page for the document, returning the canvas that will draw + * into the page. The document owns this canvas, and it will go out of + * scope when endPage() or close() is called, or the document is deleted. + */ + SkCanvas* beginPage(SkScalar width, SkScalar height, + const SkRect* content = NULL); + + /** + * Call endPage() when the content for the current page has been drawn + * (into the canvas returned by beginPage()). After this call the canvas + * returned by beginPage() will be out-of-scope. + */ + void endPage(); + + /** + * Call close() when all pages have been drawn. This will close the file + * or stream holding the document's contents. After close() the document + * can no longer add new pages. Deleting the document will automatically + * call close() if need be. + * Returns true on success or false on failure. + */ + bool close(); + + /** + * Call abort() to stop producing the document immediately. + * The stream output must be ignored, and should not be trusted. + */ + void abort(); + +protected: + SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted)); + // note: subclasses must call close() in their destructor, as the base class + // cannot do this for them. + virtual ~SkDocument(); + + virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height, + const SkRect& content) = 0; + virtual void onEndPage() = 0; + virtual bool onClose(SkWStream*) = 0; + virtual void onAbort() = 0; + + enum State { + kBetweenPages_State, + kInPage_State, + kClosed_State + }; + State getState() const { return fState; } + +private: + SkWStream* fStream; + void (*fDoneProc)(SkWStream*, bool aborted); + State fState; + + typedef SkRefCnt INHERITED; +}; + +#endif diff --git a/gfx/skia/include/core/SkDraw.h b/gfx/skia/trunk/include/core/SkDraw.h similarity index 75% rename from gfx/skia/include/core/SkDraw.h rename to gfx/skia/trunk/include/core/SkDraw.h index 43db02964bfa..f0759dc3c564 100644 --- a/gfx/skia/include/core/SkDraw.h +++ b/gfx/skia/trunk/include/core/SkDraw.h @@ -10,20 +10,21 @@ #ifndef SkDraw_DEFINED #define SkDraw_DEFINED -#include "SkBitmap.h" #include "SkCanvas.h" #include "SkMask.h" -#include "SkMatrix.h" #include "SkPaint.h" -#include "SkRect.h" +class SkBitmap; class SkBounder; class SkClipStack; -class SkDevice; +class SkBaseDevice; +class SkMatrix; class SkPath; class SkRegion; class SkRasterClip; struct SkDrawProcs; +struct SkRect; +class SkRRect; class SkDraw { public: @@ -34,6 +35,7 @@ public: void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[], const SkPaint&, bool forceUseDevice = false) const; void drawRect(const SkRect&, const SkPaint&) const; + void drawRRect(const SkRRect&, const SkPaint&) const; /** * To save on mallocs, we allow a flag that tells us that srcPath is * mutable, so that we don't have to make copies of it as we transform it. @@ -43,8 +45,15 @@ public: * affect the geometry/rasterization, then the pre matrix can just be * pre-concated with the current matrix. */ - void drawPath(const SkPath& srcPath, const SkPaint&, - const SkMatrix* prePathMatrix, bool pathIsMutable) const; + void drawPath(const SkPath& path, const SkPaint& paint, + const SkMatrix* prePathMatrix, bool pathIsMutable) const { + this->drawPath(path, paint, prePathMatrix, pathIsMutable, false); + } + + void drawPath(const SkPath& path, const SkPaint& paint) const { + this->drawPath(path, paint, NULL, false, false); + } + void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const; void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const; void drawText(const char text[], size_t byteLength, SkScalar x, @@ -54,19 +63,20 @@ public: int scalarsPerPosition, const SkPaint& paint) const; void drawTextOnPath(const char text[], size_t byteLength, const SkPath&, const SkMatrix*, const SkPaint&) const; -#ifdef SK_BUILD_FOR_ANDROID - void drawPosTextOnPath(const char text[], size_t byteLength, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix) const; -#endif void drawVertices(SkCanvas::VertexMode mode, int count, const SkPoint vertices[], const SkPoint textures[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int ptCount, const SkPaint& paint) const; - void drawPath(const SkPath& src, const SkPaint& paint) const { - this->drawPath(src, paint, NULL, false); + /** + * Overwrite the target with the path's coverage (i.e. its mask). + * Will overwrite the entire device, so it need not be zero'd first. + * + * Only device A8 is supported right now. + */ + void drawPathCoverage(const SkPath& src, const SkPaint& paint) const { + this->drawPath(src, paint, NULL, false, true); } /** Helper function that creates a mask from a path and an optional maskfilter. @@ -97,12 +107,20 @@ public: static RectType ComputeRectType(const SkPaint&, const SkMatrix&, SkPoint* strokeSize); + static bool ShouldDrawTextAsPaths(const SkPaint&, const SkMatrix&); + void drawText_asPaths(const char text[], size_t byteLength, + SkScalar x, SkScalar y, const SkPaint&) const; + void drawPosText_asPaths(const char text[], size_t byteLength, + const SkScalar pos[], SkScalar constY, + int scalarsPerPosition, const SkPaint&) const; + private: - void drawText_asPaths(const char text[], size_t byteLength, - SkScalar x, SkScalar y, const SkPaint&) const; void drawDevMask(const SkMask& mask, const SkPaint&) const; void drawBitmapAsMask(const SkBitmap&, const SkPaint&) const; + void drawPath(const SkPath&, const SkPaint&, const SkMatrix* preMatrix, + bool pathIsMutable, bool drawCoverage) const; + /** * Return the current clip bounds, in local coordinates, with slop to account * for antialiasing or hairlines (i.e. device-bounds outset by 1, and then @@ -121,7 +139,7 @@ public: const SkRasterClip* fRC; // required const SkClipStack* fClipStack; // optional - SkDevice* fDevice; // optional + SkBaseDevice* fDevice; // optional SkBounder* fBounder; // optional SkDrawProcs* fProcs; // optional diff --git a/gfx/skia/include/core/SkDrawFilter.h b/gfx/skia/trunk/include/core/SkDrawFilter.h similarity index 98% rename from gfx/skia/include/core/SkDrawFilter.h rename to gfx/skia/trunk/include/core/SkDrawFilter.h index 6a50ca7ac640..52cbba9d20f1 100644 --- a/gfx/skia/include/core/SkDrawFilter.h +++ b/gfx/skia/trunk/include/core/SkDrawFilter.h @@ -31,6 +31,7 @@ public: kLine_Type, kBitmap_Type, kRect_Type, + kRRect_Type, kOval_Type, kPath_Type, kText_Type, diff --git a/gfx/skia/include/core/SkDrawLooper.h b/gfx/skia/trunk/include/core/SkDrawLooper.h similarity index 96% rename from gfx/skia/include/core/SkDrawLooper.h rename to gfx/skia/trunk/include/core/SkDrawLooper.h index 2faf28b39953..4609c1dcf90d 100644 --- a/gfx/skia/include/core/SkDrawLooper.h +++ b/gfx/skia/trunk/include/core/SkDrawLooper.h @@ -64,10 +64,11 @@ public: const SkRect& src, SkRect* dst); SkDEVCODE(virtual void toString(SkString* str) const = 0;) + SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper) protected: SkDrawLooper() {} - SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {} private: typedef SkFlattenable INHERITED; diff --git a/gfx/skia/trunk/include/core/SkDynamicAnnotations.h b/gfx/skia/trunk/include/core/SkDynamicAnnotations.h new file mode 100644 index 000000000000..6d21cddb940b --- /dev/null +++ b/gfx/skia/trunk/include/core/SkDynamicAnnotations.h @@ -0,0 +1,46 @@ +/* + * 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 SkDynamicAnnotations_DEFINED +#define SkDynamicAnnotations_DEFINED + +// This file contains macros used to send out-of-band signals to dynamic instrumentation systems, +// namely thread sanitizer. This is a cut-down version of the full dynamic_annotations library with +// only the features used by Skia. + +// We check the same define to know to enable the annotations, but prefix all our macros with SK_. +#if DYNAMIC_ANNOTATIONS_ENABLED + +extern "C" { +// TSAN provides these hooks. +void AnnotateIgnoreReadsBegin(const char* file, int line); +void AnnotateIgnoreReadsEnd(const char* file, int line); +} // extern "C" + +// SK_ANNOTATE_UNPROTECTED_READ can wrap any variable read to tell TSAN to ignore that it appears to +// be a racy read. This should be used only when we can make an external guarantee that though this +// particular read is racy, it is being used as part of a mechanism which is thread safe. Examples: +// - the first check in double-checked locking; +// - checking if a ref count is equal to 1. +// Note that in both these cases, we must still add terrifyingly subtle memory barriers to provide +// that overall thread safety guarantee. Using this macro to shut TSAN up without providing such an +// external guarantee is pretty much never correct. +template +inline T SK_ANNOTATE_UNPROTECTED_READ(const volatile T& x) { + AnnotateIgnoreReadsBegin(__FILE__, __LINE__); + T read = x; + AnnotateIgnoreReadsEnd(__FILE__, __LINE__); + return read; +} + +#else // !DYNAMIC_ANNOTATIONS_ENABLED + +#define SK_ANNOTATE_UNPROTECTED_READ(x) (x) + +#endif + +#endif//SkDynamicAnnotations_DEFINED diff --git a/gfx/skia/include/core/SkEmptyShader.h b/gfx/skia/trunk/include/core/SkEmptyShader.h similarity index 93% rename from gfx/skia/include/core/SkEmptyShader.h rename to gfx/skia/trunk/include/core/SkEmptyShader.h index 08c131db1bc1..3f7dae41a9f4 100644 --- a/gfx/skia/include/core/SkEmptyShader.h +++ b/gfx/skia/trunk/include/core/SkEmptyShader.h @@ -34,7 +34,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader) protected: - SkEmptyShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkEmptyShader(SkReadBuffer& buffer) : INHERITED(buffer) {} private: typedef SkShader INHERITED; diff --git a/gfx/skia/include/core/SkEndian.h b/gfx/skia/trunk/include/core/SkEndian.h similarity index 68% rename from gfx/skia/include/core/SkEndian.h rename to gfx/skia/trunk/include/core/SkEndian.h index 01d21951da2a..6eba297548ee 100644 --- a/gfx/skia/include/core/SkEndian.h +++ b/gfx/skia/trunk/include/core/SkEndian.h @@ -65,7 +65,7 @@ template struct SkTEndianSwap32 { (N >> 24); }; -/** Vector version of SkEndianSwap16(), which swaps the +/** Vector version of SkEndianSwap32(), which swaps the bytes of each value in the array. */ static inline void SkEndianSwap32s(uint32_t array[], int count) { @@ -77,26 +77,70 @@ static inline void SkEndianSwap32s(uint32_t array[], int count) { } } +/** Reverse all 8 bytes in a 64bit value. + e.g. 0x1122334455667788 -> 0x8877665544332211 +*/ +static inline uint64_t SkEndianSwap64(uint64_t value) { + return (((value & 0x00000000000000FFULL) << (8*7)) | + ((value & 0x000000000000FF00ULL) << (8*5)) | + ((value & 0x0000000000FF0000ULL) << (8*3)) | + ((value & 0x00000000FF000000ULL) << (8*1)) | + ((value & 0x000000FF00000000ULL) >> (8*1)) | + ((value & 0x0000FF0000000000ULL) >> (8*3)) | + ((value & 0x00FF000000000000ULL) >> (8*5)) | + ((value) >> (8*7))); +} +template struct SkTEndianSwap64 { + static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) | + ((N & 0x000000000000FF00ULL) << (8*5)) | + ((N & 0x0000000000FF0000ULL) << (8*3)) | + ((N & 0x00000000FF000000ULL) << (8*1)) | + ((N & 0x000000FF00000000ULL) >> (8*1)) | + ((N & 0x0000FF0000000000ULL) >> (8*3)) | + ((N & 0x00FF000000000000ULL) >> (8*5)) | + ((N) >> (8*7))); +}; + +/** Vector version of SkEndianSwap64(), which swaps the + bytes of each value in the array. +*/ +static inline void SkEndianSwap64s(uint64_t array[], int count) { + SkASSERT(count == 0 || array != NULL); + + while (--count >= 0) { + *array = SkEndianSwap64(*array); + array += 1; + } +} + #ifdef SK_CPU_LENDIAN #define SkEndian_SwapBE16(n) SkEndianSwap16(n) #define SkEndian_SwapBE32(n) SkEndianSwap32(n) + #define SkEndian_SwapBE64(n) SkEndianSwap64(n) #define SkEndian_SwapLE16(n) (n) #define SkEndian_SwapLE32(n) (n) + #define SkEndian_SwapLE64(n) (n) #define SkTEndian_SwapBE16(n) SkTEndianSwap16::value #define SkTEndian_SwapBE32(n) SkTEndianSwap32::value + #define SkTEndian_SwapBE64(n) SkTEndianSwap64::value #define SkTEndian_SwapLE16(n) (n) #define SkTEndian_SwapLE32(n) (n) + #define SkTEndian_SwapLE64(n) (n) #else // SK_CPU_BENDIAN #define SkEndian_SwapBE16(n) (n) #define SkEndian_SwapBE32(n) (n) + #define SkEndian_SwapBE64(n) (n) #define SkEndian_SwapLE16(n) SkEndianSwap16(n) #define SkEndian_SwapLE32(n) SkEndianSwap32(n) + #define SkEndian_SwapLE64(n) SkEndianSwap64(n) #define SkTEndian_SwapBE16(n) (n) #define SkTEndian_SwapBE32(n) (n) + #define SkTEndian_SwapBE64(n) (n) #define SkTEndian_SwapLE16(n) SkTEndianSwap16::value #define SkTEndian_SwapLE32(n) SkTEndianSwap32::value + #define SkTEndian_SwapLE64(n) SkTEndianSwap64::value #endif // When a bytestream is embedded in a 32-bit word, how far we need to diff --git a/gfx/skia/trunk/include/core/SkError.h b/gfx/skia/trunk/include/core/SkError.h new file mode 100644 index 000000000000..678c910253cd --- /dev/null +++ b/gfx/skia/trunk/include/core/SkError.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 SkError_DEFINED +#define SkError_DEFINED + + +/** \file SkError.h +*/ + +enum SkError { + /** All is well + */ + kNoError_SkError=0, + + /** User argument passed to Skia function was invalid: NULL when that’s + * not allowed, out of numeric range, bad enum, or violating some + * other general precondition. + */ + kInvalidArgument_SkError, + + /** User tried to perform some operation in a state when the operation + * was not legal, or the operands make no sense (e.g., asking for + * pixels from an SkPictureCanvas). Other examples might be + * inset()’ing a rectangle to make it degenerate (negative width/height). + */ + kInvalidOperation_SkError, + + /** Probably not needed right now, but in the future we could have opaque + * handles for SkPictures floating around, and it would be a good idea + * to anticipate this kind of issue. + */ + kInvalidHandle_SkError, + + /** This is probably not possible because paint surely has defaults for + * everything, but perhaps a paint can get into a bad state somehow. + */ + kInvalidPaint_SkError, + + /** Skia was unable to allocate memory to perform some task. + */ + kOutOfMemory_SkError, + + /** Skia failed while trying to consume some external resource. + */ + kParseError_SkError, + + /** Something went wrong internally; could be resource exhaustion but + * will often be a bug. + */ + kInternalError_SkError +}; + +/** Return the current per-thread error code. Error codes are "sticky"; they + * are not not reset by subsequent successful operations. + */ +SkError SkGetLastError(); + +/** Clear the current per-thread error code back to kNoError_SkError. + */ +void SkClearLastError(); + +/** Type for callback functions to be invoked whenever an error is registered. + * Callback functions take the error code being set, as well as a context + * argument that is provided when the callback is registered. + */ +typedef void (*SkErrorCallbackFunction)(SkError, void *); + +/** Set the current per-thread error callback. + * + * @param cb The callback function to be invoked. Passing NULL + * for cb will revert to the default error callback which + * does nothing on release builds, but on debug builds will + * print an informative error message to the screen. + * @param context An arbitrary pointer that will be passed to + * the provided callback function. + */ +void SkSetErrorCallback(SkErrorCallbackFunction cb, void *context); + +/** Get a human-readable description of the last (per-thread) error that + * occurred. The returned error message will include not only a human + * readable version of the error code, but also information about the + * conditions that led to the error itself. + */ +const char *SkGetLastErrorString(); + +#endif /* SkError_DEFINED */ diff --git a/gfx/skia/include/core/SkFixed.h b/gfx/skia/trunk/include/core/SkFixed.h similarity index 51% rename from gfx/skia/include/core/SkFixed.h rename to gfx/skia/trunk/include/core/SkFixed.h index 0f8f7588872e..b5987fc208f3 100644 --- a/gfx/skia/include/core/SkFixed.h +++ b/gfx/skia/trunk/include/core/SkFixed.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkFixed_DEFINED #define SkFixed_DEFINED @@ -55,16 +53,6 @@ typedef int32_t SkFixed; #define SkFixedToDouble(x) ((x) * 1.5258789e-5) #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) -/** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point -*/ -typedef int32_t SkFract; -#define SK_Fract1 (1 << 30) -#define Sk_FracHalf (1 << 29) -#define SK_FractPIOver180 (0x11DF46A) - -#define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) -#define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) - /** Converts an integer to a SkFixed, asserting that the result does not overflow a 32 bit signed integer */ @@ -79,31 +67,6 @@ typedef int32_t SkFract; #define SkIntToFixed(n) (SkFixed)((n) << 16) #endif -/** Converts a SkFixed to a SkFract, asserting that the result does not overflow - a 32 bit signed integer -*/ -#ifdef SK_DEBUG - inline SkFract SkFixedToFract(SkFixed x) - { - SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1); - return x << 14; - } -#else - #define SkFixedToFract(x) ((x) << 14) -#endif - -/** Returns the signed fraction of a SkFixed -*/ -inline SkFixed SkFixedFraction(SkFixed x) -{ - SkFixed mask = x >> 31 << 16; - return (x & 0xFFFF) | mask; -} - -/** Converts a SkFract to a SkFixed -*/ -#define SkFractToFixed(x) ((x) >> 14) - #define SkFixedRoundToInt(x) (((x) + SK_FixedHalf) >> 16) #define SkFixedCeilToInt(x) (((x) + SK_Fixed1 - 1) >> 16) #define SkFixedFloorToInt(x) ((x) >> 16) @@ -112,62 +75,24 @@ inline SkFixed SkFixedFraction(SkFixed x) #define SkFixedCeilToFixed(x) (((x) + SK_Fixed1 - 1) & 0xFFFF0000) #define SkFixedFloorToFixed(x) ((x) & 0xFFFF0000) -// DEPRECATED -#define SkFixedFloor(x) SkFixedFloorToInt(x) -#define SkFixedCeil(x) SkFixedCeilToInt(x) -#define SkFixedRound(x) SkFixedRoundToInt(x) - #define SkFixedAbs(x) SkAbs32(x) #define SkFixedAve(a, b) (((a) + (b)) >> 1) SkFixed SkFixedMul_portable(SkFixed, SkFixed); -SkFract SkFractMul_portable(SkFract, SkFract); -inline SkFixed SkFixedSquare_portable(SkFixed value) -{ - uint32_t a = SkAbs32(value); - uint32_t ah = a >> 16; - uint32_t al = a & 0xFFFF; - SkFixed result = ah * a + al * ah + (al * al >> 16); - if (result >= 0) - return result; - else // Overflow. - return SK_FixedMax; -} #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) -SkFixed SkFixedDivInt(int32_t numer, int32_t denom); -SkFixed SkFixedMod(SkFixed numer, SkFixed denom); -#define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16) -SkFixed SkFixedFastInvert(SkFixed n); -#define SkFixedSqrt(n) SkSqrtBits(n, 23) -SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y) -int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound -#define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30) -#define SkFractSqrt(n) SkSqrtBits(n, 30) +/////////////////////////////////////////////////////////////////////////////// +// TODO: move fixed sin/cos into SkCosineMapper, as that is the only caller +// or rewrite SkCosineMapper to not use it at all SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull); #define SkFixedSin(radians) SkFixedSinCos(radians, NULL) -inline SkFixed SkFixedCos(SkFixed radians) -{ +static inline SkFixed SkFixedCos(SkFixed radians) { SkFixed cosValue; (void)SkFixedSinCos(radians, &cosValue); return cosValue; } -SkFixed SkFixedTan(SkFixed radians); -SkFixed SkFixedASin(SkFixed); -SkFixed SkFixedACos(SkFixed); -SkFixed SkFixedATan2(SkFixed y, SkFixed x); -SkFixed SkFixedExp(SkFixed); -SkFixed SkFixedLog(SkFixed); - -#define SK_FixedNearlyZero (SK_Fixed1 >> 12) - -inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) -{ - SkASSERT(tolerance > 0); - return SkAbs32(x) < tolerance; -} ////////////////////////////////////////////////////////////////////////////////////////////////////// // Now look for ASM overrides for our portable versions (should consider putting this in its own file) @@ -175,34 +100,25 @@ inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) #ifdef SkLONGLONG inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) { - return (SkFixed)((SkLONGLONG)a * b >> 16); - } - inline SkFract SkFractMul_longlong(SkFract a, SkFract b) - { - return (SkFixed)((SkLONGLONG)a * b >> 30); - } - inline SkFixed SkFixedSquare_longlong(SkFixed value) - { - return (SkFixed)((SkLONGLONG)value * value >> 16); + return (SkFixed)((int64_t)a * b >> 16); } #define SkFixedMul(a,b) SkFixedMul_longlong(a,b) - #define SkFractMul(a,b) SkFractMul_longlong(a,b) - #define SkFixedSquare(a) SkFixedSquare_longlong(a) #endif -#if defined(SK_CPU_ARM) && !defined(__thumb__) +#if defined(SK_CPU_ARM) /* This guy does not handle NaN or other obscurities, but is faster than - than (int)(x*65536) when we only have software floats + than (int)(x*65536) */ inline SkFixed SkFloatToFixed_arm(float x) { - register int32_t y, z; + int32_t y, z; asm("movs %1, %3, lsl #1 \n" "mov %2, #0x8E \n" "sub %1, %2, %1, lsr #24 \n" "mov %2, %3, lsl #8 \n" "orr %2, %2, #0x80000000 \n" "mov %1, %2, lsr %1 \n" + "it cs \n" "rsbcs %1, %1, #0 \n" : "=r"(x), "=&r"(y), "=&r"(z) : "r"(x) @@ -212,7 +128,7 @@ inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) } inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) { - register int32_t t; + int32_t t; asm("smull %0, %2, %1, %3 \n" "mov %0, %0, lsr #16 \n" "orr %0, %0, %2, lsl #16 \n" @@ -222,54 +138,16 @@ inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) ); return x; } - inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a) - { - register int32_t t; - asm("smull %0, %3, %1, %4 \n" - "add %0, %2, %0, lsr #16 \n" - "add %0, %0, %3, lsl #16 \n" - : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t) - : "%r"(x), "1"(y), "2"(a) - : - ); - return x; - } - inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y) - { - register int32_t t; - asm("smull %0, %2, %1, %3 \n" - "mov %0, %0, lsr #30 \n" - "orr %0, %0, %2, lsl #2 \n" - : "=r"(x), "=&r"(y), "=r"(t) - : "r"(x), "1"(y) - : - ); - return x; - } #undef SkFixedMul - #undef SkFractMul #define SkFixedMul(x, y) SkFixedMul_arm(x, y) - #define SkFractMul(x, y) SkFractMul_arm(x, y) - #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a) #undef SkFloatToFixed #define SkFloatToFixed(x) SkFloatToFixed_arm(x) #endif -/////////////////////// Now define our macros to the portable versions if they weren't overridden - -#ifndef SkFixedSquare - #define SkFixedSquare(x) SkFixedSquare_portable(x) -#endif #ifndef SkFixedMul #define SkFixedMul(x, y) SkFixedMul_portable(x, y) #endif -#ifndef SkFractMul - #define SkFractMul(x, y) SkFractMul_portable(x, y) -#endif -#ifndef SkFixedMulAdd - #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) -#endif /////////////////////////////////////////////////////////////////////////////// @@ -281,10 +159,6 @@ typedef int64_t SkFixed48; #define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32)) #define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f))) -#ifdef SK_SCALAR_IS_FLOAT - #define SkScalarToFixed48(x) SkFloatToFixed48(x) -#else - #define SkScalarToFixed48(x) SkFixedToFixed48(x) -#endif +#define SkScalarToFixed48(x) SkFloatToFixed48(x) #endif diff --git a/gfx/skia/include/core/SkFlate.h b/gfx/skia/trunk/include/core/SkFlate.h similarity index 100% rename from gfx/skia/include/core/SkFlate.h rename to gfx/skia/trunk/include/core/SkFlate.h diff --git a/gfx/skia/include/core/SkFlattenable.h b/gfx/skia/trunk/include/core/SkFlattenable.h similarity index 54% rename from gfx/skia/include/core/SkFlattenable.h rename to gfx/skia/trunk/include/core/SkFlattenable.h index 0b21abcc764c..ee7a4337100a 100644 --- a/gfx/skia/include/core/SkFlattenable.h +++ b/gfx/skia/trunk/include/core/SkFlattenable.h @@ -12,11 +12,12 @@ #include "SkRefCnt.h" -class SkFlattenableReadBuffer; -class SkFlattenableWriteBuffer; +class SkReadBuffer; +class SkWriteBuffer; #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \ - SkFlattenable::Registrar(#flattenable, flattenable::CreateProc); + SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \ + flattenable::GetFlattenableType()); #define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables(); @@ -27,14 +28,22 @@ class SkFlattenableWriteBuffer; } #define SK_DECLARE_UNFLATTENABLE_OBJECT() \ - virtual Factory getFactory() SK_OVERRIDE { return NULL; }; \ + virtual Factory getFactory() const SK_OVERRIDE { return NULL; } #define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \ - virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } \ - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { \ + virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; } \ + static SkFlattenable* CreateProc(SkReadBuffer& buffer) { \ return SkNEW_ARGS(flattenable, (buffer)); \ } +/** For SkFlattenable derived objects with a valid type + This macro should only be used in base class objects in core + */ +#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \ + static Type GetFlattenableType() { \ + return k##flattenable##_Type; \ + } + /** \class SkFlattenable SkFlattenable is the base class for objects that need to be flattened @@ -43,9 +52,22 @@ class SkFlattenableWriteBuffer; */ class SK_API SkFlattenable : public SkRefCnt { public: + enum Type { + kSkColorFilter_Type, + kSkDrawLooper_Type, + kSkImageFilter_Type, + kSkMaskFilter_Type, + kSkPathEffect_Type, + kSkPixelRef_Type, + kSkRasterizer_Type, + kSkShader_Type, + kSkUnitMapper_Type, + kSkXfermode_Type, + }; + SK_DECLARE_INST_COUNT(SkFlattenable) - typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&); + typedef SkFlattenable* (*Factory)(SkReadBuffer&); SkFlattenable() {} @@ -53,32 +75,38 @@ public: to recreate your class given a buffer (previously written to by your override of flatten(). */ - virtual Factory getFactory() = 0; + virtual Factory getFactory() const = 0; + + /** Returns the name of the object's class + */ + const char* getTypeName() const { return FactoryToName(getFactory()); } static Factory NameToFactory(const char name[]); static const char* FactoryToName(Factory); - static void Register(const char name[], Factory); + static bool NameToType(const char name[], Type* type); + + static void Register(const char name[], Factory, Type); class Registrar { public: - Registrar(const char name[], Factory factory) { - SkFlattenable::Register(name, factory); + Registrar(const char name[], Factory factory, Type type) { + SkFlattenable::Register(name, factory, type); } }; -protected: - SkFlattenable(SkFlattenableReadBuffer&) {} /** Override this to write data specific to your subclass into the buffer, being sure to call your super-class' version first. This data will later be passed to your Factory function, returned by getFactory(). */ - virtual void flatten(SkFlattenableWriteBuffer&) const; + virtual void flatten(SkWriteBuffer&) const; + +protected: + SkFlattenable(SkReadBuffer&) {} private: - static void InitializeFlattenables(); + static void InitializeFlattenablesIfNeeded(); friend class SkGraphics; - friend class SkFlattenableWriteBuffer; typedef SkRefCnt INHERITED; }; diff --git a/gfx/skia/trunk/include/core/SkFlattenableBuffers.h b/gfx/skia/trunk/include/core/SkFlattenableBuffers.h new file mode 100644 index 000000000000..3e5d5b94ee2c --- /dev/null +++ b/gfx/skia/trunk/include/core/SkFlattenableBuffers.h @@ -0,0 +1,10 @@ +// Temporary shim to keep a couple dependencies working in Chromium. +#ifndef SkFlattenableBuffers_DEFINED +#define SkFlattenableBuffers_DEFINED + +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" + +typedef SkReadBuffer SkFlattenableReadBuffer; + +#endif//SkFlattenableBuffers_DEFINED diff --git a/gfx/skia/trunk/include/core/SkFlattenableSerialization.h b/gfx/skia/trunk/include/core/SkFlattenableSerialization.h new file mode 100644 index 000000000000..ffb1b5ae9723 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkFlattenableSerialization.h @@ -0,0 +1,19 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkFlattenableSerialization_DEFINED +#define SkFlattenableSerialization_DEFINED + +#include "SkFlattenable.h" + +class SkData; + +SK_API SkData* SkValidatingSerializeFlattenable(SkFlattenable*); +SK_API SkFlattenable* SkValidatingDeserializeFlattenable(const void* data, size_t size, + SkFlattenable::Type type); + +#endif diff --git a/gfx/skia/include/core/SkFloatBits.h b/gfx/skia/trunk/include/core/SkFloatBits.h similarity index 93% rename from gfx/skia/include/core/SkFloatBits.h rename to gfx/skia/trunk/include/core/SkFloatBits.h index a1196caca7fc..552e712f53e5 100644 --- a/gfx/skia/include/core/SkFloatBits.h +++ b/gfx/skia/trunk/include/core/SkFloatBits.h @@ -127,12 +127,7 @@ static inline int32_t SkFloatToIntCeil(float x) { // Scalar wrappers for float-bit routines -#ifdef SK_SCALAR_IS_FLOAT - #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x) - #define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x) -#else - #define SkScalarAs2sCompliment(x) (x) - #define Sk2sComplimentAsScalar(x) (x) -#endif +#define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x) +#define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x) #endif diff --git a/gfx/skia/include/core/SkFloatingPoint.h b/gfx/skia/trunk/include/core/SkFloatingPoint.h similarity index 67% rename from gfx/skia/include/core/SkFloatingPoint.h rename to gfx/skia/trunk/include/core/SkFloatingPoint.h index 02880f3d23aa..7dfa9d8680e8 100644 --- a/gfx/skia/include/core/SkFloatingPoint.h +++ b/gfx/skia/trunk/include/core/SkFloatingPoint.h @@ -77,6 +77,8 @@ static inline float sk_float_copysign(float x, float y) { #define sk_float_isinf(x) isinf(x) #endif +#define sk_double_isnan(a) sk_float_isnan(a) + #ifdef SK_USE_FLOATBITS #define sk_float_floor2int(x) SkFloatToIntFloor(x) #define sk_float_round2int(x) SkFloatToIntRound(x) @@ -94,4 +96,45 @@ extern const uint32_t gIEEENegativeInfinity; #define SK_FloatNaN (*SkTCast(&gIEEENotANumber)) #define SK_FloatInfinity (*SkTCast(&gIEEEInfinity)) #define SK_FloatNegativeInfinity (*SkTCast(&gIEEENegativeInfinity)) + +#if defined(__SSE__) +#include +#elif defined(__ARM_NEON__) +#include +#endif + +// Fast, approximate inverse square root. +// Compare to name-brand "1.0f / sk_float_sqrt(x)". Should be around 10x faster on SSE, 2x on NEON. +static inline float sk_float_rsqrt(const float x) { +// We want all this inlined, so we'll inline SIMD and just take the hit when we don't know we've got +// it at compile time. This is going to be too fast to productively hide behind a function pointer. +// +// We do one step of Newton's method to refine the estimates in the NEON and null paths. No +// refinement is faster, but very innacurate. Two steps is more accurate, but slower than 1/sqrt. +#if defined(__SSE__) + float result; + _mm_store_ss(&result, _mm_rsqrt_ss(_mm_set_ss(x))); + return result; +#elif defined(__ARM_NEON__) + // Get initial estimate. + const float32x2_t xx = vdup_n_f32(x); // Clever readers will note we're doing everything 2x. + float32x2_t estimate = vrsqrte_f32(xx); + + // One step of Newton's method to refine. + const float32x2_t estimate_sq = vmul_f32(estimate, estimate); + estimate = vmul_f32(estimate, vrsqrts_f32(xx, estimate_sq)); + return vget_lane_f32(estimate, 0); // 1 will work fine too; the answer's in both places. +#else + // Get initial estimate. + int i = *SkTCast(&x); + i = 0x5f3759df - (i>>1); + float estimate = *SkTCast(&i); + + // One step of Newton's method to refine. + const float estimate_sq = estimate*estimate; + estimate *= (1.5f-0.5f*x*estimate_sq); + return estimate; +#endif +} + #endif diff --git a/gfx/skia/include/core/SkFontHost.h b/gfx/skia/trunk/include/core/SkFontHost.h similarity index 100% rename from gfx/skia/include/core/SkFontHost.h rename to gfx/skia/trunk/include/core/SkFontHost.h diff --git a/gfx/skia/include/core/SkFontLCDConfig.h b/gfx/skia/trunk/include/core/SkFontLCDConfig.h similarity index 100% rename from gfx/skia/include/core/SkFontLCDConfig.h rename to gfx/skia/trunk/include/core/SkFontLCDConfig.h diff --git a/gfx/skia/include/core/SkGeometry.h b/gfx/skia/trunk/include/core/SkGeometry.h similarity index 73% rename from gfx/skia/include/core/SkGeometry.h rename to gfx/skia/trunk/include/core/SkGeometry.h index 26f27babf701..d7836db735ea 100644 --- a/gfx/skia/include/core/SkGeometry.h +++ b/gfx/skia/trunk/include/core/SkGeometry.h @@ -72,6 +72,12 @@ int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValues[1]); 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 @@ -206,4 +212,96 @@ enum SkRotationDirection { int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop, SkRotationDirection, const SkMatrix*, SkPoint quadPoints[]); +// experimental +struct SkConic { + SkPoint fPts[3]; + SkScalar fW; + + void set(const SkPoint pts[3], SkScalar w) { + memcpy(fPts, pts, 3 * sizeof(SkPoint)); + fW = w; + } + + /** + * Given a t-value [0...1] return its position and/or tangent. + * If pos is not null, return its position at the t-value. + * If tangent is not null, return its tangent at the t-value. NOTE the + * tangent value's length is arbitrary, and only its direction should + * be used. + */ + void evalAt(SkScalar t, SkPoint* pos, SkVector* tangent = NULL) const; + void chopAt(SkScalar t, SkConic dst[2]) const; + void chop(SkConic dst[2]) const; + + void computeAsQuadError(SkVector* err) const; + bool asQuadTol(SkScalar tol) const; + + /** + * return the power-of-2 number of quads needed to approximate this conic + * with a sequence of quads. Will be >= 0. + */ + int computeQuadPOW2(SkScalar tol) const; + + /** + * Chop this conic into N quads, stored continguously in pts[], where + * N = 1 << pow2. The amount of storage needed is (1 + 2 * N) + */ + int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const; + + bool findXExtrema(SkScalar* t) const; + bool findYExtrema(SkScalar* t) const; + bool chopAtXExtrema(SkConic dst[2]) const; + bool chopAtYExtrema(SkConic dst[2]) const; + + void computeTightBounds(SkRect* bounds) const; + void computeFastBounds(SkRect* bounds) const; +}; + +#include "SkTemplates.h" + +/** + * Help class to allocate storage for approximating a conic with N quads. + */ +class SkAutoConicToQuads { +public: + SkAutoConicToQuads() : fQuadCount(0) {} + + /** + * Given a conic and a tolerance, return the array of points for the + * approximating quad(s). Call countQuads() to know the number of quads + * represented in these points. + * + * The quads are allocated to share end-points. e.g. if there are 4 quads, + * there will be 9 points allocated as follows + * quad[0] == pts[0..2] + * quad[1] == pts[2..4] + * quad[2] == pts[4..6] + * quad[3] == pts[6..8] + */ + const SkPoint* computeQuads(const SkConic& conic, SkScalar tol) { + int pow2 = conic.computeQuadPOW2(tol); + fQuadCount = 1 << pow2; + SkPoint* pts = fStorage.reset(1 + 2 * fQuadCount); + conic.chopIntoQuadsPOW2(pts, pow2); + return pts; + } + + const SkPoint* computeQuads(const SkPoint pts[3], SkScalar weight, + SkScalar tol) { + SkConic conic; + conic.set(pts, weight); + return computeQuads(conic, tol); + } + + int countQuads() const { return fQuadCount; } + +private: + enum { + kQuadCount = 8, // should handle most conics + kPointCount = 1 + 2 * kQuadCount, + }; + SkAutoSTMalloc fStorage; + int fQuadCount; // #quads for current usage +}; + #endif diff --git a/gfx/skia/include/core/SkGraphics.h b/gfx/skia/trunk/include/core/SkGraphics.h similarity index 80% rename from gfx/skia/include/core/SkGraphics.h rename to gfx/skia/trunk/include/core/SkGraphics.h index 87d66ad1f029..2667a388d2bb 100644 --- a/gfx/skia/include/core/SkGraphics.h +++ b/gfx/skia/trunk/include/core/SkGraphics.h @@ -53,6 +53,25 @@ public: */ static size_t GetFontCacheUsed(); + /** + * Return the number of entries in the font cache. + * A cache "entry" is associated with each typeface + pointSize + matrix. + */ + static int GetFontCacheCountUsed(); + + /** + * Return the current limit to the number of entries in the font cache. + * A cache "entry" is associated with each typeface + pointSize + matrix. + */ + static int GetFontCacheCountLimit(); + + /** + * Set the limit to the number of entries in the font cache, and return + * the previous value. If this new value is lower than the previous, + * it will automatically try to purge entries to meet the new limit. + */ + static int SetFontCacheCountLimit(int count); + /** * For debugging purposes, this will attempt to purge the font cache. It * does not change the limit, but will cause subsequent font measures and @@ -60,6 +79,10 @@ public: */ static void PurgeFontCache(); + static size_t GetImageCacheBytesUsed(); + static size_t GetImageCacheByteLimit(); + static size_t SetImageCacheByteLimit(size_t newLimit); + /** * Applications with command line options may pass optional state, such * as cache sizes, here, for instance: diff --git a/gfx/skia/trunk/include/core/SkImage.h b/gfx/skia/trunk/include/core/SkImage.h new file mode 100644 index 000000000000..c9f939616684 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkImage.h @@ -0,0 +1,142 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkImage_DEFINED +#define SkImage_DEFINED + +#include "SkImageInfo.h" +#include "SkImageEncoder.h" +#include "SkRefCnt.h" +#include "SkScalar.h" + +class SkData; +class SkCanvas; +class SkPaint; +class SkShader; +class GrContext; +class GrTexture; + +// need for TileMode +#include "SkShader.h" + +/** + * SkImage is an abstraction for drawing a rectagle of pixels, though the + * particular type of image could be actually storing its data on the GPU, or + * as drawing commands (picture or PDF or otherwise), ready to be played back + * into another canvas. + * + * The content of SkImage is always immutable, though the actual storage may + * change, if for example that image can be re-created via encoded data or + * other means. + */ +class SK_API SkImage : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkImage) + + typedef SkImageInfo Info; + + static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes); + static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes); + static SkImage* NewEncodedData(SkData*); + + /** + * GrTexture is a more logical parameter for this factory, but its + * interactions with scratch cache still has issues, so for now we take + * SkBitmap instead. This will be changed in the future. skbug.com/1449 + */ + static SkImage* NewTexture(const SkBitmap&); + + int width() const { return fWidth; } + int height() const { return fHeight; } + uint32_t uniqueID() const { return fUniqueID; } + + /** + * Return the GrTexture that stores the image pixels. Calling getTexture + * does not affect the reference count of the GrTexture object. + * Will return NULL if the image does not use a texture. + */ + GrTexture* getTexture(); + + SkShader* newShaderClamp() const; + SkShader* newShader(SkShader::TileMode, SkShader::TileMode) const; + + void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); + + /** + * Draw the image, cropped to the src rect, to the dst rect of a canvas. + * If src is larger than the bounds of the image, the rest of the image is + * filled with transparent black pixels. + * + * See SkCanvas::drawBitmapRectToRect for similar behavior. + */ + void draw(SkCanvas*, const SkRect* src, const SkRect& dst, const SkPaint*); + + /** + * If the image has direct access to its pixels (i.e. they are in local + * RAM) return the (const) address of those pixels, and if not null, return + * the ImageInfo and rowBytes. The returned address is only valid while + * the image object is in scope. + * + * On failure, returns NULL and the info and rowBytes parameters are + * ignored. + */ + const void* peekPixels(SkImageInfo* info, size_t* rowBytes) const; + + /** + * Encode the image's pixels and return the result as a new SkData, which + * the caller must manage (i.e. call unref() when they are done). + * + * If the image type cannot be encoded, or the requested encoder type is + * not supported, this will return NULL. + */ + SkData* encode(SkImageEncoder::Type t = SkImageEncoder::kPNG_Type, + int quality = 80) const; + +protected: + SkImage(int width, int height) : + fWidth(width), + fHeight(height), + fUniqueID(NextUniqueID()) { + + SkASSERT(width >= 0); + SkASSERT(height >= 0); + } + +private: + const int fWidth; + const int fHeight; + const uint32_t fUniqueID; + + static uint32_t NextUniqueID(); + + typedef SkRefCnt INHERITED; + + /** + * Return a copy of the image's pixels, limiting them to the subset + * rectangle's intersection wit the image bounds. If subset is NULL, then + * the entire image will be considered. + * + * If the bitmap's pixels have already been allocated, then readPixels() + * will succeed only if it can support converting the image's pixels into + * the bitmap's ColorType/AlphaType. Any pixels in the bitmap that do not + * intersect with the image's bounds and the subset (if not null) will be + * left untouched. + * + * If the bitmap is initially empty/unallocated, then it will be allocated + * using the default allocator, and the ColorType/AlphaType will be chosen + * to most closely fit the image's configuration. + * + * On failure, false will be returned, and bitmap will unmodified. + */ + // On ice for now: + // - should it respect the particular colortype/alphatype of the src + // - should it have separate entrypoints for preallocated and not bitmaps? + // - isn't it enough to allow the caller to draw() the image into a canvas? + bool readPixels(SkBitmap* bitmap, const SkIRect* subset = NULL) const; +}; + +#endif diff --git a/gfx/skia/include/images/SkImageDecoder.h b/gfx/skia/trunk/include/core/SkImageDecoder.h similarity index 63% rename from gfx/skia/include/images/SkImageDecoder.h rename to gfx/skia/trunk/include/core/SkImageDecoder.h index 33802ed03cc8..bec40631e7c4 100644 --- a/gfx/skia/include/images/SkImageDecoder.h +++ b/gfx/skia/trunk/include/core/SkImageDecoder.h @@ -11,22 +11,23 @@ #define SkImageDecoder_DEFINED #include "SkBitmap.h" -#include "SkBitmapFactory.h" #include "SkImage.h" #include "SkRect.h" #include "SkRefCnt.h" +#include "SkTRegistry.h" +#include "SkTypes.h" class SkStream; +class SkStreamRewindable; /** \class SkImageDecoder Base class for decoding compressed images into a SkBitmap */ -class SkImageDecoder { +class SkImageDecoder : public SkNoncopyable { public: virtual ~SkImageDecoder(); - // Should be consistent with kFormatName enum Format { kUnknown_Format, kBMP_Format, @@ -37,17 +38,44 @@ public: kWBMP_Format, kWEBP_Format, - kLastKnownFormat = kWEBP_Format + kLastKnownFormat = kWEBP_Format, }; - /** Return the compressed data's format (see Format enum) + /** Return the format of image this decoder can decode. If this decoder can decode multiple + formats, kUnknown_Format will be returned. */ virtual Format getFormat() const; - /** Return the compressed data's format name. + /** Return the format of the SkStreamRewindable or kUnknown_Format if it cannot be determined. + Rewinds the stream before returning. + */ + static Format GetStreamFormat(SkStreamRewindable*); + + /** Return a readable string of the Format provided. + */ + static const char* GetFormatName(Format); + + /** Return a readable string of the value returned by getFormat(). */ const char* getFormatName() const; + /** Whether the decoder should skip writing zeroes to output if possible. + */ + bool getSkipWritingZeroes() const { return fSkipWritingZeroes; } + + /** Set to true if the decoder should skip writing any zeroes when + creating the output image. + This is a hint that may not be respected by the decoder. + It should only be used if it is known that the memory to write + to has already been set to 0; otherwise the resulting image will + have garbage. + This is ideal for images that contain a lot of completely transparent + pixels, but may be a performance hit for an image that has only a + few transparent pixels. + The default is false. + */ + void setSkipWritingZeroes(bool skip) { fSkipWritingZeroes = skip; } + /** Returns true if the decoder should try to dither the resulting image. The default setting is true. */ @@ -72,6 +100,21 @@ public: fPreferQualityOverSpeed = qualityOverSpeed; } + /** Set to true to require the decoder to return a bitmap with unpremultiplied + colors. The default is false, meaning the resulting bitmap will have its + colors premultiplied. + NOTE: Passing true to this function may result in a bitmap which cannot + be properly used by Skia. + */ + void setRequireUnpremultipliedColors(bool request) { + fRequireUnpremultipliedColors = request; + } + + /** Returns true if the decoder will only return bitmaps with unpremultiplied + colors. + */ + bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; } + /** \class Peeker Base class for optional callbacks to retrieve meta/chunk data out of @@ -92,10 +135,10 @@ public: Peeker* getPeeker() const { return fPeeker; } Peeker* setPeeker(Peeker*); - /** \class Peeker + /** \class Chooser - Base class for optional callbacks to retrieve meta/chunk data out of - an image as it is being decoded. + Base class for optional callbacks to choose an image from a format that + contains multiple images. */ class Chooser : public SkRefCnt { public: @@ -114,32 +157,49 @@ public: Chooser* getChooser() const { return fChooser; } Chooser* setChooser(Chooser*); - /** This optional table describes the caller's preferred config based on - information about the src data. For this table, the src attributes are - described in terms of depth (index (8), 16, 32/24) and if there is - per-pixel alpha. These inputs combine to create an index into the - pref[] table, which contains the caller's preferred config for that - input, or kNo_Config if there is no preference. - - To specify no preferrence, call setPrefConfigTable(NULL), which is - the default. - - Note, it is still at the discretion of the codec as to what output - config is actually returned, as it may not be able to support the - caller's preference. - - Here is how the index into the table is computed from the src: - depth [8, 16, 32/24] -> 0, 2, 4 - alpha [no, yes] -> 0, 1 - The two index values are OR'd together. - src: 8-index, no-alpha -> 0 - src: 8-index, yes-alpha -> 1 - src: 16bit, no-alpha -> 2 // e.g. 565 - src: 16bit, yes-alpha -> 3 // e.g. 1555 - src: 32/24, no-alpha -> 4 - src: 32/24, yes-alpha -> 5 + /** + * Optional table describing the caller's preferred config based on + * information about the src data. Each field should be set to the + * preferred config for a src described in the name of the field. The + * src attributes are described in terms of depth (8-index, + * 8bit-grayscale, or 8-bits/component) and whether there is per-pixel + * alpha (does not apply to grayscale). If the caller has no preference + * for a particular src type, its slot should be set to kNo_Config. + * + * NOTE ABOUT PREFERRED CONFIGS: + * If a config is preferred, either using a pref table or as a parameter + * to some flavor of decode, it is still at the discretion of the codec + * as to what output config is actually returned, as it may not be able + * to support the caller's preference. + * + * If a bitmap is decoded into SkBitmap::A8_Config, the resulting bitmap + * will either be a conversion of the grayscale in the case of a + * grayscale source or the alpha channel in the case of a source with + * an alpha channel. */ - void setPrefConfigTable(const SkBitmap::Config pref[6]); + struct PrefConfigTable { + SkBitmap::Config fPrefFor_8Index_NoAlpha_src; + SkBitmap::Config fPrefFor_8Index_YesAlpha_src; + SkBitmap::Config fPrefFor_8Gray_src; + SkBitmap::Config fPrefFor_8bpc_NoAlpha_src; + SkBitmap::Config fPrefFor_8bpc_YesAlpha_src; + }; + + /** + * Set an optional table for specifying the caller's preferred config + * based on information about the src data. + * + * The default is no preference, which will assume the config set by + * decode is preferred. + */ + void setPrefConfigTable(const PrefConfigTable&); + + /** + * Do not use a PrefConfigTable to determine the output config. This + * is the default, so there is no need to call unless a PrefConfigTable + * was previously set. + */ + void resetPrefConfigTable() { fUsePrefTable = false; } SkBitmap::Allocator* getAllocator() const { return fAllocator; } SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*); @@ -194,11 +254,20 @@ public: * to pref if possible. Whether a conversion is feasible is * tested by Bitmap::canCopyTo(pref). - note: document use of Allocator, Peeker and Chooser + If an SkBitmap::Allocator is installed via setAllocator, it will be + used to allocate the pixel memory. A clever allocator can be used + to allocate the memory from a cache, volatile memory, or even from + an existing bitmap's memory. + + If a Peeker is installed via setPeeker, it may be used to peek into + meta data during the decode. + + If a Chooser is installed via setChooser, it may be used to select + which image to return from a format that contains multiple images. */ - bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode, bool reuseBitmap = false); - bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode, bool reuseBitmap = false) { - return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode, reuseBitmap); + bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode); + bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) { + return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode); } /** @@ -208,31 +277,32 @@ public: * * Return true for success or false on failure. */ - bool buildTileIndex(SkStream*, int *width, int *height); + bool buildTileIndex(SkStreamRewindable*, int *width, int *height); /** - * Decode a rectangle region in the image specified by rect. + * Decode a rectangle subset in the image. * The method can only be called after buildTileIndex(). * * Return true for success. * Return false if the index is never built or failing in decoding. */ - bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, SkBitmap::Config pref); + bool decodeSubset(SkBitmap* bm, const SkIRect& subset, SkBitmap::Config pref); + + SK_ATTR_DEPRECATED("use decodeSubset() instead") + bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect, SkBitmap::Config pref) { + return this->decodeSubset(bitmap, rect, pref); + } /** Given a stream, this will try to find an appropriate decoder object. If none is found, the method returns NULL. */ - static SkImageDecoder* Factory(SkStream*); + static SkImageDecoder* Factory(SkStreamRewindable*); /** Decode the image stored in the specified file, and store the result in bitmap. Return true for success or false on failure. - If pref is kNo_Config, then the decoder is free to choose the most natural - config given the image data. If pref something other than kNo_Config, - the decoder will attempt to decode the image into that format, unless - there is a conflict (e.g. the image has per-pixel alpha and the bitmap's - config does not support that), in which case the decoder will choose a - closest match configuration. + @param prefConfig If the PrefConfigTable is not set, prefer this config. + See NOTE ABOUT PREFERRED CONFIGS. @param format On success, if format is non-null, it is set to the format of the decoded file. On failure it is ignored. @@ -247,12 +317,8 @@ public: /** Decode the image stored in the specified memory buffer, and store the result in bitmap. Return true for success or false on failure. - If pref is kNo_Config, then the decoder is free to choose the most natural - config given the image data. If pref something other than kNo_Config, - the decoder will attempt to decode the image into that format, unless - there is a conflict (e.g. the image has per-pixel alpha and the bitmap's - config does not support that), in which case the decoder will choose a - closest match configuration. + @param prefConfig If the PrefConfigTable is not set, prefer this config. + See NOTE ABOUT PREFERRED CONFIGS. @param format On success, if format is non-null, it is set to the format of the decoded buffer. On failure it is ignored. @@ -266,49 +332,33 @@ public: } /** - * Decode memory. - * @param info Output parameter. Returns info about the encoded image. - * @param target Contains the address of pixel memory to decode into - * (which must be large enough to hold the width in info) and - * the row bytes to use. If NULL, returns info and does not - * decode pixels. - * @return bool Whether the function succeeded. - * - * Sample usage: - * - * // Determine the image's info: width/height/config - * SkImage::Info info; - * bool success = DecodeMemoryToTarget(src, size, &info, NULL); - * if (!success) return; - * // Allocate space for the result: - * SkBitmapFactory::Target target; - * target.fAddr = malloc/other allocation - * target.fRowBytes = ... - * // Now decode the actual pixels into target. &info is optional, - * // and could be NULL - * success = DecodeMemoryToTarget(src, size, &info, &target); - * + * Struct containing information about a pixel destination. */ - static bool DecodeMemoryToTarget(const void* buffer, size_t size, SkImage::Info* info, - const SkBitmapFactory::Target* target); + struct Target { + /** + * Pre-allocated memory. + */ + void* fAddr; - /** Decode the image stored in the specified SkStream, and store the result + /** + * Rowbytes of the allocated memory. + */ + size_t fRowBytes; + }; + + /** Decode the image stored in the specified SkStreamRewindable, and store the result in bitmap. Return true for success or false on failure. - If pref is kNo_Config, then the decoder is free to choose the most - natural config given the image data. If pref something other than - kNo_Config, the decoder will attempt to decode the image into that - format, unless there is a conflict (e.g. the image has per-pixel alpha - and the bitmap's config does not support that), in which case the - decoder will choose a closest match configuration. + @param prefConfig If the PrefConfigTable is not set, prefer this config. + See NOTE ABOUT PREFERRED CONFIGS. @param format On success, if format is non-null, it is set to the format of the decoded stream. On failure it is ignored. */ - static bool DecodeStream(SkStream* stream, SkBitmap* bitmap, + static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap, SkBitmap::Config prefConfig, Mode, Format* format = NULL); - static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) { + static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap) { return DecodeStream(stream, bitmap, SkBitmap::kNo_Config, kDecodePixels_Mode, NULL); } @@ -333,13 +383,13 @@ protected: // If the decoder wants to support tiled based decoding, // this method must be overridden. This guy is called by buildTileIndex(...) - virtual bool onBuildTileIndex(SkStream*, int *width, int *height) { + virtual bool onBuildTileIndex(SkStreamRewindable*, int *width, int *height) { return false; } // If the decoder wants to support tiled based decoding, // this method must be overridden. This guy is called by decodeRegion(...) - virtual bool onDecodeRegion(SkBitmap* bitmap, const SkIRect& rect) { + virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) { return false; } @@ -354,14 +404,25 @@ protected: * @param (dstX, dstY) the upper-left point of the dest bitmap in terms of * the coordinate in the original bitmap. * @param (width, height) the width and height of the unsampled dst. - * @param (srcX, srcY) the upper-left point of the src bitimap in terms of + * @param (srcX, srcY) the upper-left point of the src bitmap in terms of * the coordinate in the original bitmap. + * @return bool Whether or not it succeeded. */ - void cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, + bool cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, int dstX, int dstY, int width, int height, int srcX, int srcY); + /** + * Copy all fields on this decoder to the other decoder. Used by subclasses + * to decode a subimage using a different decoder, but with the same settings. + */ + void copyFieldsToOther(SkImageDecoder* other); + /** + * Return the default preference being used by the current or latest call to + * decode. + */ + SkBitmap::Config getDefaultPref() { return fDefaultPref; } /** Can be queried from within onDecode, to see if the user (possibly in a different thread) has requested the decode to cancel. If this returns @@ -388,10 +449,16 @@ protected: */ bool allocPixelRef(SkBitmap*, SkColorTable*) const; + /** + * The raw data of the src image. + */ enum SrcDepth { + // Color-indexed. kIndex_SrcDepth, - k16Bit_SrcDepth, - k32Bit_SrcDepth + // Grayscale in 8 bits. + k8BitGray_SrcDepth, + // 8 bits per component. Used for 24 bit if there is no alpha. + k32Bit_SrcDepth, }; /** The subclass, inside onDecode(), calls this to determine the config of the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the @@ -409,22 +476,13 @@ private: SkBitmap::Allocator* fAllocator; int fSampleSize; SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false - SkBitmap::Config fPrefTable[6]; // use if fUsePrefTable is true + PrefConfigTable fPrefTable; // use if fUsePrefTable is true bool fDitherImage; bool fUsePrefTable; + bool fSkipWritingZeroes; mutable bool fShouldCancelDecode; bool fPreferQualityOverSpeed; - - /** Contains the image format name. - * This should be consistent with Format. - * - * The format name gives a more meaningful error message than enum. - */ - static const char* sFormatName[]; - - // illegal - SkImageDecoder(const SkImageDecoder&); - SkImageDecoder& operator=(const SkImageDecoder&); + bool fRequireUnpremultipliedColors; }; /** Calling newDecoder with a stream returns a new matching imagedecoder @@ -437,7 +495,7 @@ class SkImageDecoderFactory : public SkRefCnt { public: SK_DECLARE_INST_COUNT(SkImageDecoderFactory) - virtual SkImageDecoder* newDecoder(SkStream*) = 0; + virtual SkImageDecoder* newDecoder(SkStreamRewindable*) = 0; private: typedef SkRefCnt INHERITED; @@ -446,7 +504,7 @@ private: class SkDefaultImageDecoderFactory : SkImageDecoderFactory { public: // calls SkImageDecoder::Factory(stream) - virtual SkImageDecoder* newDecoder(SkStream* stream) { + virtual SkImageDecoder* newDecoder(SkStreamRewindable* stream) { return SkImageDecoder::Factory(stream); } }; @@ -473,4 +531,10 @@ DECLARE_DECODER_CREATOR(PNGImageDecoder); DECLARE_DECODER_CREATOR(WBMPImageDecoder); DECLARE_DECODER_CREATOR(WEBPImageDecoder); + +// Typedefs to make registering decoder and formatter callbacks easier. +// These have to be defined outside SkImageDecoder. :( +typedef SkTRegistry SkImageDecoder_DecodeReg; +typedef SkTRegistry SkImageDecoder_FormatReg; + #endif diff --git a/gfx/skia/include/images/SkImageEncoder.h b/gfx/skia/trunk/include/core/SkImageEncoder.h similarity index 69% rename from gfx/skia/include/images/SkImageEncoder.h rename to gfx/skia/trunk/include/core/SkImageEncoder.h index d4d71695654b..5622eee7e0a2 100644 --- a/gfx/skia/include/images/SkImageEncoder.h +++ b/gfx/skia/trunk/include/core/SkImageEncoder.h @@ -9,16 +9,23 @@ #define SkImageEncoder_DEFINED #include "SkTypes.h" +#include "SkTRegistry.h" class SkBitmap; +class SkData; class SkWStream; class SkImageEncoder { public: enum Type { + kUnknown_Type, + kBMP_Type, + kGIF_Type, + kICO_Type, kJPEG_Type, kPNG_Type, - kWEBP_Type + kWBMP_Type, + kWEBP_Type, }; static SkImageEncoder* Create(Type); @@ -29,26 +36,29 @@ public: kDefaultQuality = 80 }; + /** + * Encode bitmap 'bm', returning the results in an SkData, at quality level + * 'quality' (which can be in range 0-100). If the bitmap cannot be + * encoded, return null. On success, the caller is responsible for + * calling unref() on the data when they are finished. + */ + SkData* encodeData(const SkBitmap&, int quality); + /** * Encode bitmap 'bm' in the desired format, writing results to * file 'file', at quality level 'quality' (which can be in range - * 0-100). - * - * Calls the particular implementation's onEncode() method to - * actually do the encoding. + * 0-100). Returns false on failure. */ bool encodeFile(const char file[], const SkBitmap& bm, int quality); /** * Encode bitmap 'bm' in the desired format, writing results to * stream 'stream', at quality level 'quality' (which can be in - * range 0-100). - * - * Calls the particular implementation's onEncode() method to - * actually do the encoding. + * range 0-100). Returns false on failure. */ bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality); + static SkData* EncodeData(const SkBitmap&, Type, int quality); static bool EncodeFile(const char file[], const SkBitmap&, Type, int quality); static bool EncodeStream(SkWStream*, const SkBitmap&, Type, @@ -79,8 +89,16 @@ protected: // All the encoders known by Skia. Note that, depending on the compiler settings, // not all of these will be available +/** An ARGBImageEncoder will always write out + * bitmap.width() * bitmap.height() * 4 + * bytes. + */ +DECLARE_ENCODER_CREATOR(ARGBImageEncoder); DECLARE_ENCODER_CREATOR(JPEGImageEncoder); DECLARE_ENCODER_CREATOR(PNGImageEncoder); DECLARE_ENCODER_CREATOR(WEBPImageEncoder); +// Typedef to make registering encoder callback easier +// This has to be defined outside SkImageEncoder. :( +typedef SkTRegistry SkImageEncoder_EncodeReg; #endif diff --git a/gfx/skia/trunk/include/core/SkImageFilter.h b/gfx/skia/trunk/include/core/SkImageFilter.h new file mode 100644 index 000000000000..a3e5a62ee505 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkImageFilter.h @@ -0,0 +1,232 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkImageFilter_DEFINED +#define SkImageFilter_DEFINED + +#include "SkFlattenable.h" +#include "SkRect.h" + +class SkBitmap; +class SkColorFilter; +class SkBaseDevice; +class SkMatrix; +struct SkIPoint; +class SkShader; +class GrEffectRef; +class GrTexture; + +/** + * Base class for image filters. If one is installed in the paint, then + * all drawing occurs as usual, but it is as if the drawing happened into an + * offscreen (before the xfermode is applied). This offscreen bitmap will + * then be handed to the imagefilter, who in turn creates a new bitmap which + * is what will finally be drawn to the device (using the original xfermode). + */ +class SK_API SkImageFilter : public SkFlattenable { +public: + SK_DECLARE_INST_COUNT(SkImageFilter) + + class CropRect { + public: + enum CropEdge { + kHasLeft_CropEdge = 0x01, + kHasTop_CropEdge = 0x02, + kHasRight_CropEdge = 0x04, + kHasBottom_CropEdge = 0x08, + kHasAll_CropEdge = 0x0F, + }; + CropRect() {} + explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {} + uint32_t flags() const { return fFlags; } + const SkRect& rect() const { return fRect; } + private: + SkRect fRect; + uint32_t fFlags; + }; + + class Proxy { + public: + virtual ~Proxy() {}; + + virtual SkBaseDevice* createDevice(int width, int height) = 0; + // returns true if the proxy can handle this filter natively + virtual bool canHandleImageFilter(const SkImageFilter*) = 0; + // returns true if the proxy handled the filter itself. if this returns + // false then the filter's code will be called. + virtual bool filterImage(const SkImageFilter*, const SkBitmap& src, + const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) = 0; + }; + + /** + * Request a new (result) image to be created from the src image. + * If the src has no pixels (isNull()) then the request just wants to + * receive the config and width/height of the result. + * + * The matrix is the current matrix on the canvas. + * + * Offset is the amount to translate the resulting image relative to the + * src when it is drawn. This is an out-param. + * + * If the result image cannot be created, return false, in which case both + * the result and offset parameters will be ignored by the caller. + */ + bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const; + + /** + * Given the src bounds of an image, this returns the bounds of the result + * image after the filter has been applied. + */ + bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const; + + /** + * Returns true if the filter can be processed on the GPU. This is most + * often used for multi-pass effects, where intermediate results must be + * rendered to textures. For single-pass effects, use asNewEffect(). + * The default implementation returns asNewEffect(NULL, NULL, SkMatrix::I(), + * SkIRect()). + */ + virtual bool canFilterImageGPU() const; + + /** + * Process this image filter on the GPU. This is most often used for + * multi-pass effects, where intermediate results must be rendered to + * textures. For single-pass effects, use asNewEffect(). src is the + * source image for processing, as a texture-backed bitmap. result is + * the destination bitmap, which should contain a texture-backed pixelref + * on success. offset is the amount to translate the resulting image + * relative to the src when it is drawn. The default implementation does + * single-pass processing using asNewEffect(). + */ + virtual bool filterImageGPU(Proxy*, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const; + + /** + * Returns whether this image filter is a color filter and puts the color filter into the + * "filterPtr" parameter if it can. Does nothing otherwise. + * If this returns false, then the filterPtr is unchanged. + * If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler + * (i.e. it may not be set to NULL). + */ + virtual bool asColorFilter(SkColorFilter** filterPtr) const; + + /** + * Returns the number of inputs this filter will accept (some inputs can + * be NULL). + */ + int countInputs() const { return fInputCount; } + + /** + * Returns the input filter at a given index, or NULL if no input is + * connected. The indices used are filter-specific. + */ + SkImageFilter* getInput(int i) const { + SkASSERT(i < fInputCount); + return fInputs[i]; + } + + /** + * Returns whether any edges of the crop rect have been set. The crop + * rect is set at construction time, and determines which pixels from the + * input image will be processed. The size of the crop rect should be + * used as the size of the destination image. The origin of this rect + * should be used to offset access to the input images, and should also + * be added to the "offset" parameter in onFilterImage and + * filterImageGPU(). (The latter ensures that the resulting buffer is + * drawn in the correct location.) + */ + bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } + + // Default impl returns union of all input bounds. + virtual void computeFastBounds(const SkRect&, SkRect*) const; + + SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) + +protected: + SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); + + // Convenience constructor for 1-input filters. + explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL); + + // Convenience constructor for 2-input filters. + SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL); + + virtual ~SkImageFilter(); + + /** + * Constructs a new SkImageFilter read from an SkReadBuffer object. + * + * @param inputCount The exact number of inputs expected for this SkImageFilter object. + * -1 can be used if the filter accepts any number of inputs. + * @param rb SkReadBuffer object from which the SkImageFilter is read. + */ + explicit SkImageFilter(int inputCount, SkReadBuffer& rb); + + virtual void flatten(SkWriteBuffer& wb) const SK_OVERRIDE; + + /** + * This is the virtual which should be overridden by the derived class + * to perform image filtering. + * + * src is the original primitive bitmap. If the filter has a connected + * input, it should recurse on that input and use that in place of src. + * + * The matrix is the current matrix on the canvas. + * + * Offset is the amount to translate the resulting image relative to the + * src when it is drawn. This is an out-param. + * + * If the result image cannot be created, this should false, in which + * case both the result and offset parameters will be ignored by the + * caller. + */ + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) const; + // Given the bounds of the destination rect to be filled in device + // coordinates (first parameter), and the CTM, compute (conservatively) + // which rect of the source image would be required (third parameter). + // Used for clipping and temp-buffer allocations, so the result need not + // be exact, but should never be smaller than the real answer. The default + // implementation recursively unions all input bounds, or returns false if + // no inputs. + virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const; + + // Applies "matrix" to the crop rect, and sets "rect" to the intersection of + // "rect" and the transformed crop rect. If there is no overlap, returns + // false and leaves "rect" unchanged. + bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const; + + /** + * Returns true if the filter can be expressed a single-pass + * GrEffect, used to process this filter on the GPU, or false if + * not. + * + * If effect is non-NULL, a new GrEffect instance is stored + * in it. The caller assumes ownership of the stage, and it is up to the + * caller to unref it. + * + * The effect can assume its vertexCoords space maps 1-to-1 with texels + * in the texture. "matrix" is a transformation to apply to filter + * parameters before they are used in the effect. Note that this function + * will be called with (NULL, NULL, SkMatrix::I()) to query for support, + * so returning "true" indicates support for all possible matrices. + */ + virtual bool asNewEffect(GrEffectRef** effect, + GrTexture*, + const SkMatrix& matrix, + const SkIRect& bounds) const; + +private: + typedef SkFlattenable INHERITED; + int fInputCount; + SkImageFilter** fInputs; + CropRect fCropRect; +}; + +#endif diff --git a/gfx/skia/include/effects/SkImageFilterUtils.h b/gfx/skia/trunk/include/core/SkImageFilterUtils.h similarity index 77% rename from gfx/skia/include/effects/SkImageFilterUtils.h rename to gfx/skia/trunk/include/core/SkImageFilterUtils.h index 72a25fef7777..b533c3bca25e 100644 --- a/gfx/skia/include/effects/SkImageFilterUtils.h +++ b/gfx/skia/trunk/include/core/SkImageFilterUtils.h @@ -28,7 +28,9 @@ public: * this function returns src. If the filter has no GPU implementation, it * will be processed in software and uploaded to the GPU. */ - static bool GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result); + static bool GetInputResultGPU(const SkImageFilter* filter, SkImageFilter::Proxy* proxy, + const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, + SkIPoint* offset); }; #endif diff --git a/gfx/skia/trunk/include/core/SkImageGenerator.h b/gfx/skia/trunk/include/core/SkImageGenerator.h new file mode 100644 index 000000000000..220973a0f852 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkImageGenerator.h @@ -0,0 +1,101 @@ +/* + * 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 SkImageGenerator_DEFINED +#define SkImageGenerator_DEFINED + +#include "SkDiscardableMemory.h" +#include "SkImageInfo.h" + +class SkBitmap; +class SkData; +class SkImageGenerator; + +/** + * 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. + */ +SK_API bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, + SkBitmap* destination, + SkDiscardableMemory::Factory* factory = NULL); + + +/** + * An interface that allows a purgeable PixelRef (such as a + * SkDiscardablePixelRef) to decode and re-decode an image as needed. + */ +class SK_API SkImageGenerator { +public: + /** + * The PixelRef which takes ownership of this SkImageGenerator + * will call the image generator's destructor. + */ + virtual ~SkImageGenerator() { } + + /** + * Return a ref to the encoded (i.e. compressed) representation, + * of this data. + * + * If non-NULL is returned, the caller is responsible for calling + * unref() on the data when it is finished. + */ + virtual SkData* refEncodedData() { return NULL; } + + /** + * Return some information about the image, allowing the owner of + * this object to allocate pixels. + * + * Repeated calls to this function should give the same results, + * allowing the PixelRef to be immutable. + * + * @return false if anything goes wrong. + */ + virtual bool getInfo(SkImageInfo* info) = 0; + + /** + * Decode into the given pixels, a block of memory of size at + * least (info.fHeight - 1) * rowBytes + (info.fWidth * + * bytesPerPixel) + * + * Repeated calls to this function should give the same results, + * allowing the PixelRef to be immutable. + * + * @param info A description of the format (config, size) + * expected by the caller. This can simply be identical + * to the info returned by getInfo(). + * + * This contract also allows the caller to specify + * different output-configs, which the implementation can + * decide to support or not. + * + * @return false if anything goes wrong or if the image info is + * unsupported. + */ + virtual bool getPixels(const SkImageInfo& info, + void* pixels, + size_t rowBytes) = 0; +}; + +#endif // SkImageGenerator_DEFINED diff --git a/gfx/skia/trunk/include/core/SkImageInfo.h b/gfx/skia/trunk/include/core/SkImageInfo.h new file mode 100644 index 000000000000..2b449dc2132c --- /dev/null +++ b/gfx/skia/trunk/include/core/SkImageInfo.h @@ -0,0 +1,222 @@ +/* + * 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 SkImageInfo_DEFINED +#define SkImageInfo_DEFINED + +#include "SkMath.h" +#include "SkSize.h" + +class SkWriteBuffer; +class SkReadBuffer; + +/** + * Describes how to interpret the alpha compoent of a pixel. + */ +enum SkAlphaType { + /** + * All pixels should be treated as opaque, regardless of the value stored + * in their alpha field. Used for legacy images that wrote 0 or garbarge + * in their alpha field, but intended the RGB to be treated as opaque. + */ + kIgnore_SkAlphaType, + + /** + * All pixels are stored as opaque. This differs slightly from kIgnore in + * that kOpaque has correct "opaque" values stored in the pixels, while + * kIgnore may not, but in both cases the caller should treat the pixels + * as opaque. + */ + kOpaque_SkAlphaType, + + /** + * All pixels have their alpha premultiplied in their color components. + * This is the natural format for the rendering target pixels. + */ + kPremul_SkAlphaType, + + /** + * All pixels have their color components stored without any regard to the + * alpha. e.g. this is the default configuration for PNG images. + * + * This alpha-type is ONLY supported for input images. Rendering cannot + * generate this on output. + */ + kUnpremul_SkAlphaType, + + kLastEnum_SkAlphaType = kUnpremul_SkAlphaType +}; + +static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) { + SK_COMPILE_ASSERT(kIgnore_SkAlphaType < kOpaque_SkAlphaType, bad_alphatype_order); + SK_COMPILE_ASSERT(kPremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order); + SK_COMPILE_ASSERT(kUnpremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order); + + return (unsigned)at <= kOpaque_SkAlphaType; +} + +static inline bool SkAlphaTypeIsValid(unsigned value) { + return value <= kLastEnum_SkAlphaType; +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Describes how to interpret the components of a pixel. + */ +enum SkColorType { + kUnknown_SkColorType, + kAlpha_8_SkColorType, + kRGB_565_SkColorType, + kARGB_4444_SkColorType, + kRGBA_8888_SkColorType, + kBGRA_8888_SkColorType, + kIndex_8_SkColorType, + + kLastEnum_SkColorType = kIndex_8_SkColorType, + +#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) + kPMColor_SkColorType = kBGRA_8888_SkColorType +#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) + kPMColor_SkColorType = kRGBA_8888_SkColorType +#else +#error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order" +#endif +}; + +static int SkColorTypeBytesPerPixel(SkColorType ct) { + static const uint8_t gSize[] = { + 0, // Unknown + 1, // Alpha_8 + 2, // RGB_565 + 2, // ARGB_4444 + 4, // RGBA_8888 + 4, // BGRA_8888 + 1, // kIndex_8 + }; + SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1), + size_mismatch_with_SkColorType_enum); + + SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize)); + return gSize[ct]; +} + +static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) { + return width * SkColorTypeBytesPerPixel(ct); +} + +static inline bool SkColorTypeIsValid(unsigned value) { + return value <= kLastEnum_SkColorType; +} + +/////////////////////////////////////////////////////////////////////////////// + +/** + * Describe an image's dimensions and pixel type. + */ +struct SkImageInfo { + int fWidth; + int fHeight; + SkColorType fColorType; + SkAlphaType fAlphaType; + + static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at) { + SkImageInfo info = { + width, height, ct, at + }; + return info; + } + + /** + * Sets colortype to the native ARGB32 type. + */ + static SkImageInfo MakeN32(int width, int height, SkAlphaType at) { + SkImageInfo info = { + width, height, kPMColor_SkColorType, at + }; + return info; + } + + /** + * Sets colortype to the native ARGB32 type, and the alphatype to premul. + */ + static SkImageInfo MakeN32Premul(int width, int height) { + SkImageInfo info = { + width, height, kPMColor_SkColorType, kPremul_SkAlphaType + }; + return info; + } + + /** + * Sets colortype to the native ARGB32 type, and the alphatype to premul. + */ + static SkImageInfo MakeN32Premul(const SkISize& size) { + return MakeN32Premul(size.width(), size.height()); + } + + static SkImageInfo MakeA8(int width, int height) { + SkImageInfo info = { + width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType + }; + return info; + } + + int width() const { return fWidth; } + int height() const { return fHeight; } + SkColorType colorType() const { return fColorType; } + SkAlphaType alphaType() const { return fAlphaType; } + + bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; } + + bool isOpaque() const { + return SkAlphaTypeIsOpaque(fAlphaType); + } + + SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); } + + int bytesPerPixel() const { + return SkColorTypeBytesPerPixel(fColorType); + } + + uint64_t minRowBytes64() const { + return sk_64_mul(fWidth, this->bytesPerPixel()); + } + + size_t minRowBytes() const { + return (size_t)this->minRowBytes64(); + } + + bool operator==(const SkImageInfo& other) const { + return 0 == memcmp(this, &other, sizeof(other)); + } + bool operator!=(const SkImageInfo& other) const { + return 0 != memcmp(this, &other, sizeof(other)); + } + + void unflatten(SkReadBuffer&); + void flatten(SkWriteBuffer&) const; + + int64_t getSafeSize64(size_t rowBytes) const { + if (0 == fHeight) { + return 0; + } + return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel(); + } + + size_t getSafeSize(size_t rowBytes) const { + return (size_t)this->getSafeSize64(rowBytes); + } + + bool validRowBytes(size_t rowBytes) const { + uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel()); + return rowBytes >= rb; + } + + SkDEBUGCODE(void validate() const;) +}; + +#endif diff --git a/gfx/skia/include/core/SkInstCnt.h b/gfx/skia/trunk/include/core/SkInstCnt.h similarity index 53% rename from gfx/skia/include/core/SkInstCnt.h rename to gfx/skia/trunk/include/core/SkInstCnt.h index cab8ebb91650..7e5b454b15d6 100644 --- a/gfx/skia/include/core/SkInstCnt.h +++ b/gfx/skia/trunk/include/core/SkInstCnt.h @@ -14,62 +14,74 @@ * instance counting machinery. A class is added to the system by adding: * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class - * SK_DEFINE_INST_COUNT at the top of its .cpp file (for both kinds). * At the end of an application a call to all the "root" objects' * CheckInstanceCount methods should be made */ #include "SkTypes.h" #if SK_ENABLE_INST_COUNT -#include "SkTArray.h" -#include "SkThread_platform.h" +// Static variables inside member functions below may be defined multiple times +// if Skia is being used as a dynamic library. Instance counting should be on +// only for static builds. See bug skia:2058. +#if defined(SKIA_DLL) +#error Instance counting works only when Skia is built as a static library. +#endif +#include "SkOnce.h" +#include "SkTArray.h" +#include "SkThread.h" extern bool gPrintInstCount; // The non-root classes just register themselves with their parent #define SK_DECLARE_INST_COUNT(className) \ SK_DECLARE_INST_COUNT_INTERNAL(className, \ - INHERITED::AddInstChild(CheckInstanceCount);,\ - /**/) - -#define SK_DECLARE_INST_COUNT_TEMPLATE(className) \ - SK_DECLARE_INST_COUNT_INTERNAL(className, \ - INHERITED::AddInstChild(CheckInstanceCount);, \ - typename) + INHERITED::AddInstChild(CheckInstanceCount);) // The root classes registers a function to print out the memory stats when // the app ends #define SK_DECLARE_INST_COUNT_ROOT(className) \ - SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/) + SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) -#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \ +#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ class SkInstanceCountHelper { \ public: \ - typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \ SkInstanceCountHelper() { \ - if (!gInited) { \ - initStep \ - gChildren = new SkTArray; \ - gInited = true; \ - } \ - sk_atomic_inc(&gInstanceCount); \ + SK_DECLARE_STATIC_ONCE(once); \ + SkOnce(&once, init, 0); \ + sk_atomic_inc(GetInstanceCountPtr()); \ + } \ + \ + static void init(int) { \ + initStep \ } \ \ SkInstanceCountHelper(const SkInstanceCountHelper&) { \ - sk_atomic_inc(&gInstanceCount); \ + sk_atomic_inc(GetInstanceCountPtr()); \ } \ \ ~SkInstanceCountHelper() { \ - sk_atomic_dec(&gInstanceCount); \ + sk_atomic_dec(GetInstanceCountPtr()); \ + } \ + \ + static int32_t* GetInstanceCountPtr() { \ + static int32_t gInstanceCount; \ + return &gInstanceCount; \ + } \ + \ + static SkTArray*& GetChildren() { \ + static SkTArray* gChildren; \ + return gChildren; \ + } \ + \ + static SkBaseMutex& GetChildrenMutex() { \ + SK_DECLARE_STATIC_MUTEX(childrenMutex); \ + return childrenMutex; \ } \ \ - static int32_t gInstanceCount; \ - static bool gInited; \ - static SkTArray* gChildren; \ } fInstanceCountHelper; \ \ static int32_t GetInstanceCount() { \ - return SkInstanceCountHelper::gInstanceCount; \ + return *SkInstanceCountHelper::GetInstanceCountPtr(); \ } \ \ static void exitPrint() { \ @@ -77,57 +89,54 @@ extern bool gPrintInstCount; } \ \ static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ - if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\ + if (gPrintInstCount && 0 != GetInstanceCount()) { \ SkDebugf("%*c Leaked %s: %d\n", \ 4*level, ' ', #className, \ - SkInstanceCountHelper::gInstanceCount); \ + GetInstanceCount()); \ } \ - if (NULL == SkInstanceCountHelper::gChildren) { \ - return SkInstanceCountHelper::gInstanceCount; \ + if (NULL == SkInstanceCountHelper::GetChildren()) { \ + return GetInstanceCount(); \ } \ - int childCount = SkInstanceCountHelper::gChildren->count(); \ - int count = SkInstanceCountHelper::gInstanceCount; \ + SkTArray* children = \ + SkInstanceCountHelper::GetChildren(); \ + int childCount = children->count(); \ + int count = GetInstanceCount(); \ for (int i = 0; i < childCount; ++i) { \ - count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \ + count -= (*(*children)[i])(level+1, cleanUp); \ } \ SkASSERT(count >= 0); \ if (gPrintInstCount && childCount > 0 && count > 0) { \ SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ } \ if (cleanUp) { \ - delete SkInstanceCountHelper::gChildren; \ - SkInstanceCountHelper::gChildren = NULL; \ + delete children; \ + SkInstanceCountHelper::GetChildren() = NULL; \ } \ - return SkInstanceCountHelper::gInstanceCount; \ + return GetInstanceCount(); \ } \ \ - static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \ - childCheckInstCnt) { \ - if (CheckInstanceCount != childCheckInstCnt && \ - NULL != SkInstanceCountHelper::gChildren) { \ - SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \ + static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ + if (CheckInstanceCount != childCheckInstCnt) { \ + SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \ + if (NULL == SkInstanceCountHelper::GetChildren()) { \ + SkInstanceCountHelper::GetChildren() = \ + new SkTArray; \ + } \ + SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \ } \ } -#define SK_DEFINE_INST_COUNT(className) \ - int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \ - bool className::SkInstanceCountHelper::gInited = false; \ - SkTArray* \ - className::SkInstanceCountHelper::gChildren = NULL; - -#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) \ - templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\ - templateInfo bool className::SkInstanceCountHelper::gInited = false; \ - templateInfo \ - SkTArray*\ - className::SkInstanceCountHelper::gChildren = NULL; - #else -#define SK_DECLARE_INST_COUNT(className) -#define SK_DECLARE_INST_COUNT_TEMPLATE(className) -#define SK_DECLARE_INST_COUNT_ROOT(className) -#define SK_DEFINE_INST_COUNT(className) -#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) +// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by +// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays +// compiling. +#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); } +#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } #endif +// Following are deprecated. They are defined only for backwards API compatibility. +#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className) +#define SK_DEFINE_INST_COUNT(className) +#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) + #endif // SkInstCnt_DEFINED diff --git a/gfx/skia/include/core/SkLineClipper.h b/gfx/skia/trunk/include/core/SkLineClipper.h similarity index 100% rename from gfx/skia/include/core/SkLineClipper.h rename to gfx/skia/trunk/include/core/SkLineClipper.h diff --git a/gfx/skia/trunk/include/core/SkMallocPixelRef.h b/gfx/skia/trunk/include/core/SkMallocPixelRef.h new file mode 100644 index 000000000000..f6a57b3deac2 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkMallocPixelRef.h @@ -0,0 +1,116 @@ +/* + * Copyright 2008 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkMallocPixelRef_DEFINED +#define SkMallocPixelRef_DEFINED + +#include "SkPixelRef.h" + +/** We explicitly use the same allocator for our pixels that SkMask does, + so that we can freely assign memory allocated by one class to the other. +*/ +class SK_API SkMallocPixelRef : public SkPixelRef { +public: + SK_DECLARE_INST_COUNT(SkMallocPixelRef) + /** + * Return a new SkMallocPixelRef with the provided pixel storage, rowBytes, + * and optional colortable. The caller is responsible for managing the + * lifetime of the pixel storage buffer, as this pixelref will not try + * to delete it. + * + * The pixelref will ref() the colortable (if not NULL). + * + * Returns NULL on failure. + */ + static SkMallocPixelRef* NewDirect(const SkImageInfo&, void* addr, + size_t rowBytes, SkColorTable*); + + /** + * Return a new SkMallocPixelRef, automatically allocating storage for the + * pixels. If rowBytes are 0, an optimal value will be chosen automatically. + * If rowBytes is > 0, then it will be respected, or NULL will be returned + * if rowBytes is invalid for the specified info. + * + * This pixelref will ref() the specified colortable (if not NULL). + * + * Returns NULL on failure. + */ + static SkMallocPixelRef* NewAllocate(const SkImageInfo& info, + size_t rowBytes, SkColorTable*); + + /** + * Return a new SkMallocPixelRef with the provided pixel storage, + * rowBytes, and optional colortable. On destruction, ReleaseProc + * will be called. + * + * This pixelref will ref() the specified colortable (if not NULL). + * + * Returns NULL on failure. + */ + typedef void (*ReleaseProc)(void* addr, void* context); + static SkMallocPixelRef* NewWithProc(const SkImageInfo& info, + size_t rowBytes, SkColorTable*, + void* addr, ReleaseProc proc, + void* context); + + /** + * Return a new SkMallocPixelRef that will use the provided + * SkData, rowBytes, and optional colortable as pixel storage. + * The SkData will be ref()ed and on destruction of the PielRef, + * the SkData will be unref()ed. + * + * @param offset (in bytes) into the provided SkData that the + * first pixel is located at. + * + * This pixelref will ref() the specified colortable (if not NULL). + * + * Returns NULL on failure. + */ + static SkMallocPixelRef* NewWithData(const SkImageInfo& info, + size_t rowBytes, + SkColorTable* ctable, + SkData* data, + size_t offset = 0); + + void* getAddr() const { return fStorage; } + + class PRFactory : public SkPixelRefFactory { + public: + virtual SkPixelRef* create(const SkImageInfo&, + SkColorTable*) SK_OVERRIDE; + }; + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef) + +protected: + // The ownPixels version of this constructor is deprecated. + SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*, + bool ownPixels); + SkMallocPixelRef(SkReadBuffer& buffer); + virtual ~SkMallocPixelRef(); + + virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE; + virtual void onUnlockPixels() SK_OVERRIDE; + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE; + +private: + void* fStorage; + SkColorTable* fCTable; + size_t fRB; + ReleaseProc fReleaseProc; + void* fReleaseProcContext; + + SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, SkColorTable*, + ReleaseProc proc, void* context); + + typedef SkPixelRef INHERITED; +}; + + +#endif diff --git a/gfx/skia/include/core/SkMask.h b/gfx/skia/trunk/include/core/SkMask.h similarity index 89% rename from gfx/skia/include/core/SkMask.h rename to gfx/skia/trunk/include/core/SkMask.h index 4265595f267d..5cfef970c502 100644 --- a/gfx/skia/include/core/SkMask.h +++ b/gfx/skia/trunk/include/core/SkMask.h @@ -99,6 +99,19 @@ struct SkMask { return row + (x - fBounds.fLeft); } + /** + * Return the address of the specified 32bit mask. In the debug build, + * this asserts that the mask's format is 32bits, and that (x,y) + * are contained in the mask's fBounds. + */ + uint32_t* getAddr32(int x, int y) const { + SkASSERT(kLCD32_Format == fFormat || kARGB32_Format == fFormat); + SkASSERT(fBounds.contains(x, y)); + SkASSERT(fImage != NULL); + uint32_t* row = (uint32_t*)(fImage + (y - fBounds.fTop) * fRowBytes); + return row + (x - fBounds.fLeft); + } + /** * Returns the address of the specified pixel, computing the pixel-size * at runtime based on the mask format. This will be slightly slower than @@ -144,5 +157,6 @@ public: private: uint8_t* fImage; }; +#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage) #endif diff --git a/gfx/skia/include/core/SkMaskFilter.h b/gfx/skia/trunk/include/core/SkMaskFilter.h similarity index 57% rename from gfx/skia/include/core/SkMaskFilter.h rename to gfx/skia/trunk/include/core/SkMaskFilter.h index aa499ecd2399..b47e034e3cd6 100644 --- a/gfx/skia/include/core/SkMaskFilter.h +++ b/gfx/skia/trunk/include/core/SkMaskFilter.h @@ -14,11 +14,16 @@ #include "SkMask.h" #include "SkPaint.h" +class GrContext; +class GrPaint; +class SkBitmap; class SkBlitter; class SkBounder; class SkMatrix; class SkPath; class SkRasterClip; +class SkRRect; +class SkStrokeRec; /** \class SkMaskFilter @@ -58,27 +63,61 @@ public: virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkIPoint* margin) const; - enum BlurType { - kNone_BlurType, //!< this maskfilter is not a blur - kNormal_BlurType, //!< fuzzy inside and outside - kSolid_BlurType, //!< solid inside, fuzzy outside - kOuter_BlurType, //!< nothing inside, fuzzy outside - kInner_BlurType //!< fuzzy inside, nothing outside - }; - - struct BlurInfo { - SkScalar fRadius; - bool fIgnoreTransform; - bool fHighQuality; - }; +#if SK_SUPPORT_GPU + /** + * Returns true if the filter can be expressed a single-pass GrEffect without requiring an + * explicit input mask. Per-pixel, the effect receives the incoming mask's coverage as + * the input color and outputs the filtered covereage value. This means that each pixel's + * filtered coverage must only depend on the unfiltered mask value for that pixel and not on + * surrounding values. + * + * If effect is non-NULL, a new GrEffect instance is stored in it. The caller assumes ownership + * of the effect and must unref it. + */ + virtual bool asNewEffect(GrEffectRef** effect, + GrTexture*, + const SkMatrix& ctm) const; /** - * Optional method for maskfilters that can be described as a blur. If so, - * they return the corresponding BlurType and set the fields in BlurInfo - * (if not null). If they cannot be described as a blur, they return - * kNone_BlurType and ignore the info parameter. + * If asNewEffect() fails the filter may be implemented on the GPU by a subclass overriding + * filterMaskGPU (declared below). That code path requires constructing a src mask as input. + * Since that is a potentially expensive operation, the subclass must also override this + * function to indicate whether filterTextureMaskGPU would succeeed if the mask were to be + * created. + * + * 'maskRect' returns the device space portion of the mask that the filter needs. The mask + * passed into 'filterMaskGPU' should have the same extent as 'maskRect' but be translated + * to the upper-left corner of the mask (i.e., (maskRect.fLeft, maskRect.fTop) appears at + * (0, 0) in the mask). */ - virtual BlurType asABlur(BlurInfo*) const; + virtual bool canFilterMaskGPU(const SkRect& devBounds, + const SkIRect& clipBounds, + const SkMatrix& ctm, + SkRect* maskRect) const; + + /** + * Try to directly render the mask filter into the target. Returns + * true if drawing was successful. + */ + virtual bool directFilterMaskGPU(GrContext* context, + GrPaint* grp, + const SkStrokeRec& strokeRec, + const SkPath& path) const; + + /** + * This function is used to implement filters that require an explicit src mask. It should only + * be called if canFilterMaskGPU returned true and the maskRect param should be the output from + * that call. canOverwriteSrc indicates whether the implementation may treat src as a scratch + * texture and overwrite its contents. When true it is also legal to return src as the result. + * Implementations are free to get the GrContext from the src texture in order to create + * additional textures and perform multiple passes. + */ + virtual bool filterMaskGPU(GrTexture* src, + const SkMatrix& ctm, + const SkRect& maskRect, + GrTexture** result, + bool canOverwriteSrc) const; +#endif /** * The fast bounds function is used to enable the paint to be culled early @@ -94,10 +133,11 @@ public: virtual void computeFastBounds(const SkRect& src, SkRect* dest) const; SkDEVCODE(virtual void toString(SkString* str) const = 0;) + SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter) protected: // empty for now, but lets get our subclass to remember to init us for the future - SkMaskFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkMaskFilter(SkReadBuffer& buffer) : INHERITED(buffer) {} enum FilterReturn { kFalse_FilterReturn, @@ -130,6 +170,12 @@ protected: const SkMatrix&, const SkIRect& clipBounds, NinePatch*) const; + /** + * Similar to filterRectsToNine, except it performs the work on a round rect. + */ + virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&, + const SkIRect& clipBounds, + NinePatch*) const; private: friend class SkDraw; @@ -143,6 +189,14 @@ private: const SkRasterClip&, SkBounder*, SkBlitter* blitter, SkPaint::Style style) const; + /** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format + mask and then call filterMask(). If this returns true, the specified blitter will be called + to render that mask. Returns false if filterMask() returned false. + */ + bool filterRRect(const SkRRect& devRRect, const SkMatrix& devMatrix, + const SkRasterClip&, SkBounder*, SkBlitter* blitter, + SkPaint::Style style) const; + typedef SkFlattenable INHERITED; }; diff --git a/gfx/skia/include/core/SkMath.h b/gfx/skia/trunk/include/core/SkMath.h similarity index 60% rename from gfx/skia/include/core/SkMath.h rename to gfx/skia/trunk/include/core/SkMath.h index 314311f65501..ba6223ed06e7 100644 --- a/gfx/skia/include/core/SkMath.h +++ b/gfx/skia/trunk/include/core/SkMath.h @@ -35,17 +35,58 @@ int32_t SkSqrtBits(int32_t value, int bitBias); */ #define SkSqrt32(n) SkSqrtBits(n, 15) +// 64bit -> 32bit utilities + +/** + * Return true iff the 64bit value can exactly be represented in signed 32bits + */ +static inline bool sk_64_isS32(int64_t value) { + return (int32_t)value == value; +} + +/** + * Return the 64bit argument as signed 32bits, asserting in debug that the arg + * exactly fits in signed 32bits. In the release build, no checks are preformed + * and the return value if the arg does not fit is undefined. + */ +static inline int32_t sk_64_asS32(int64_t value) { + SkASSERT(sk_64_isS32(value)); + return (int32_t)value; +} + +// Handy util that can be passed two ints, and will automatically promote to +// 64bits before the multiply, so the caller doesn't have to remember to cast +// e.g. (int64_t)a * b; +static inline int64_t sk_64_mul(int64_t a, int64_t b) { + return a * b; +} + /////////////////////////////////////////////////////////////////////////////// //! Returns the number of leading zero bits (0...32) int SkCLZ_portable(uint32_t); -#if defined(SK_CPU_ARM) - #define SkCLZ(x) __builtin_clz(x) -#endif - #ifndef SkCLZ - #define SkCLZ(x) SkCLZ_portable(x) + #if defined(_MSC_VER) && _MSC_VER >= 1400 + #include + + static inline int SkCLZ(uint32_t mask) { + if (mask) { + DWORD index; + _BitScanReverse(&index, mask); + return index ^ 0x1F; + } else { + return 32; + } + } + #elif defined(SK_CPU_ARM) || defined(__GNUC__) || defined(__clang__) + static inline int SkCLZ(uint32_t mask) { + // __builtin_clz(0) is undefined, so we have to detect that case. + return mask ? __builtin_clz(mask) : 32; + } + #else + #define SkCLZ(x) SkCLZ_portable(x) + #endif #endif /** @@ -139,7 +180,7 @@ static inline bool SkIsPow2(int value) { * Return a*b/((1 << shift) - 1), rounding any fractional bits. * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8 */ -static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) { +static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) { SkASSERT(a <= 32767); SkASSERT(b <= 32767); SkASSERT(shift > 0 && shift <= 8); @@ -148,14 +189,36 @@ static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) { } /** - * Return a*b/255, rounding any fractional bits. Only valid if both - * a and b are 0..255 + * Return a*b/255, rounding any fractional bits. + * Only valid if a and b are unsigned and <= 32767. */ -static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) { - SkASSERT((uint8_t)a == a); - SkASSERT((uint8_t)b == b); +static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) { + SkASSERT(a <= 32767); + SkASSERT(b <= 32767); unsigned prod = SkMulS16(a, b) + 128; return (prod + (prod >> 8)) >> 8; } +/** + * Stores numer/denom and numer%denom into div and mod respectively. + */ +template +inline void SkTDivMod(In numer, In denom, Out* div, Out* mod) { +#ifdef SK_CPU_ARM + // If we wrote this as in the else branch, GCC won't fuse the two into one + // divmod call, but rather a div call followed by a divmod. Silly! This + // version is just as fast as calling __aeabi_[u]idivmod manually, but with + // prettier code. + // + // This benches as around 2x faster than the code in the else branch. + const In d = numer/denom; + *div = static_cast(d); + *mod = static_cast(numer-d*denom); +#else + // On x86 this will just be a single idiv. + *div = static_cast(numer/denom); + *mod = static_cast(numer%denom); +#endif // SK_CPU_ARM +} + #endif diff --git a/gfx/skia/include/core/SkMatrix.h b/gfx/skia/trunk/include/core/SkMatrix.h similarity index 91% rename from gfx/skia/include/core/SkMatrix.h rename to gfx/skia/trunk/include/core/SkMatrix.h index 87599d4cfb21..9bbbc1745b3d 100644 --- a/gfx/skia/include/core/SkMatrix.h +++ b/gfx/skia/trunk/include/core/SkMatrix.h @@ -14,15 +14,10 @@ class SkString; -#ifdef SK_SCALAR_IS_FLOAT - typedef SkScalar SkPersp; - #define SkScalarToPersp(x) (x) - #define SkPerspToScalar(x) (x) -#else - typedef SkFract SkPersp; - #define SkScalarToPersp(x) SkFixedToFract(x) - #define SkPerspToScalar(x) SkFractToFixed(x) -#endif +// TODO: can we remove these 3 (need to check chrome/android) +typedef SkScalar SkPersp; +#define SkScalarToPersp(x) (x) +#define SkPerspToScalar(x) (x) /** \class SkMatrix @@ -90,6 +85,12 @@ public: */ bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const; + /** Returns true if the matrix contains only translation, rotation or scale + (non-uniform scale is allowed). + Returns false if other transformation types are included or is degenerate + */ + bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const; + enum { kMScaleX, kMSkewX, @@ -417,6 +418,19 @@ public: } } + /** Apply this matrix to the array of homogeneous points, specified by src, + where a homogeneous point is defined by 3 contiguous scalar values, + and write the transformed points into the array of scalars specified by dst. + dst[] = M * src[] + @param dst Where the transformed coordinates are written. It must + contain at least 3 * count entries + @param src The original coordinates that are to be transformed. It + must contain at least 3 * count entries + @param count The number of triples (homogeneous points) in src to read, + and then transform into dst. + */ + void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const; + void mapXY(SkScalar x, SkScalar y, SkPoint* result) const { SkASSERT(result); this->getMapXYProc()(*this, x, y, result); @@ -464,6 +478,18 @@ public: return this->mapRect(rect, *rect); } + /** Apply this matrix to the src rectangle, and write the four transformed + points into dst. The points written to dst will be the original top-left, top-right, + bottom-right, and bottom-left points transformed by the matrix. + @param dst Where the transformed quad is written. + @param rect The original rectangle to be transformed. + */ + void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const { + // This could potentially be faster if we only transformed each x and y of the rect once. + rect.toQuad(dst); + this->mapPoints(dst, 4); + } + /** Return the mean radius of a circle after it has been mapped by this matrix. NOTE: in perspective this value assumes the circle has its center at the origin. @@ -512,13 +538,7 @@ public: return 0 == memcmp(fMat, m.fMat, sizeof(fMat)); } -#ifdef SK_SCALAR_IS_FIXED - friend bool operator==(const SkMatrix& a, const SkMatrix& b) { - return a.cheapEqualTo(b); - } -#else friend bool operator==(const SkMatrix& a, const SkMatrix& b); -#endif friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { return !(a == b); } @@ -528,13 +548,28 @@ public: kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t) }; // return the number of bytes written, whether or not buffer is null - uint32_t writeToMemory(void* buffer) const; - // return the number of bytes read - uint32_t readFromMemory(const void* buffer); + size_t writeToMemory(void* buffer) const; + /** + * Reads data from the buffer parameter + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available + */ + size_t readFromMemory(const void* buffer, size_t length); SkDEVCODE(void dump() const;) SkDEVCODE(void toString(SkString*) const;) + /** + * Calculates the minimum stretching factor of the matrix. If the matrix has + * perspective -1 is returned. + * + * @return minumum strecthing factor + */ + SkScalar getMinStretch() const; + /** * Calculates the maximum stretching factor of the matrix. If the matrix has * perspective -1 is returned. diff --git a/gfx/skia/include/core/SkMetaData.h b/gfx/skia/trunk/include/core/SkMetaData.h similarity index 100% rename from gfx/skia/include/core/SkMetaData.h rename to gfx/skia/trunk/include/core/SkMetaData.h diff --git a/gfx/skia/include/core/SkOSFile.h b/gfx/skia/trunk/include/core/SkOSFile.h similarity index 56% rename from gfx/skia/include/core/SkOSFile.h rename to gfx/skia/trunk/include/core/SkOSFile.h index 257b66ae67b3..b75fe6cf7c96 100644 --- a/gfx/skia/include/core/SkOSFile.h +++ b/gfx/skia/trunk/include/core/SkOSFile.h @@ -48,9 +48,35 @@ char* sk_fgets(char* str, int size, SkFILE* f); void sk_fflush(SkFILE*); -int sk_fseek(SkFILE*, size_t, int); +bool sk_fseek(SkFILE*, size_t); +bool sk_fmove(SkFILE*, long); size_t sk_ftell(SkFILE*); +/** Maps a file into memory. Returns the address and length on success, NULL otherwise. + * The mapping is read only. + * When finished with the mapping, free the returned pointer with sk_fmunmap. + */ +void* sk_fmmap(SkFILE* f, size_t* length); + +/** Maps a file descriptor into memory. Returns the address and length on success, NULL otherwise. + * The mapping is read only. + * When finished with the mapping, free the returned pointer with sk_fmunmap. + */ +void* sk_fdmmap(int fd, size_t* length); + +/** Unmaps a file previously mapped by sk_fmmap or sk_fdmmap. + * The length parameter must be the same as returned from sk_fmmap. + */ +void sk_fmunmap(const void* addr, size_t length); + +/** Returns true if the two point at the exact same filesystem object. */ +bool sk_fidentical(SkFILE* a, SkFILE* b); + +/** Returns the underlying file descriptor for the given file. + * The return value will be < 0 on failure. + */ +int sk_fileno(SkFILE* f); + // Returns true if something (file, directory, ???) exists at this path. bool sk_exists(const char *path); @@ -105,4 +131,29 @@ private: uint16_t* fStr; }; +/** + * Functions for modifying SkStrings which represent paths on the filesystem. + */ +class SkOSPath { +public: + /** + * Assembles rootPath and relativePath into a single path, like this: + * rootPath/relativePath. + * It is okay to call with a NULL rootPath and/or relativePath. A path + * separator will still be inserted. + * + * Uses SkPATH_SEPARATOR, to work on all platforms. + */ + static SkString SkPathJoin(const char *rootPath, const char *relativePath); + + /** + * Return the name of the file, ignoring the directory structure. + * Behaves like python's os.path.basename. If the fullPath is + * /dir/subdir/, an empty string is returned. + * @param fullPath Full path to the file. + * @return SkString The basename of the file - anything beyond the + * final slash, or the full name if there is no slash. + */ + static SkString SkBasename(const char* fullPath); +}; #endif diff --git a/gfx/skia/trunk/include/core/SkOnce.h b/gfx/skia/trunk/include/core/SkOnce.h new file mode 100644 index 000000000000..daeb819d4284 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkOnce.h @@ -0,0 +1,179 @@ +/* + * 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. +// +// You may optionally pass SkOnce a second function to be called at exit for cleanup. + +#include "SkDynamicAnnotations.h" +#include "SkThread.h" +#include "SkTypes.h" + +#define SK_ONCE_INIT { false, { 0, SkDEBUGCODE(0) } } +#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 +inline void SkOnce(SkOnceFlag* once, Func f, Arg arg, void(*atExit)() = NULL); + +// If you've already got a lock and a flag to use, this variant lets you avoid an extra SkOnceFlag. +template +inline void SkOnce(bool* done, Lock* lock, Func f, Arg arg, void(*atExit)() = NULL); + +// ---------------------- Implementation details below here. ----------------------------- + +// This is POD and must be zero-initialized. +struct SkSpinlock { + void acquire() { + SkASSERT(shouldBeZero == 0); + // No memory barrier needed, but sk_atomic_cas gives us at least release anyway. + while (!sk_atomic_cas(&thisIsPrivate, 0, 1)) { + // spin + } + } + + void release() { + SkASSERT(shouldBeZero == 0); + // This requires a release memory barrier before storing, which sk_atomic_cas guarantees. + SkAssertResult(sk_atomic_cas(&thisIsPrivate, 1, 0)); + } + + int32_t thisIsPrivate; + SkDEBUGCODE(int32_t shouldBeZero;) +}; + +struct SkOnceFlag { + bool done; + SkSpinlock lock; +}; + +// TODO(bungeman, mtklein): move all these *barrier* functions to SkThread when refactoring lands. + +#ifdef SK_BUILD_FOR_WIN +# include +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(); +} + +// Works with SkSpinlock or SkMutex. +template +class SkAutoLockAcquire { +public: + explicit SkAutoLockAcquire(Lock* lock) : fLock(lock) { fLock->acquire(); } + ~SkAutoLockAcquire() { fLock->release(); } +private: + Lock* fLock; +}; + +// 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 +static void sk_once_slow(bool* done, Lock* lock, Func f, Arg arg, void (*atExit)()) { + const SkAutoLockAcquire locked(lock); + if (!*done) { + f(arg); + if (atExit != NULL) { + atexit(atExit); + } + // 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(); + *done = true; + } +} + +// This is our fast path, called all the time. We do really want it to be inlined. +template +inline void SkOnce(bool* done, Lock* lock, Func f, Arg arg, void(*atExit)()) { + if (!SK_ANNOTATE_UNPROTECTED_READ(*done)) { + sk_once_slow(done, lock, f, arg, atExit); + } + // 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(); +} + +template +inline void SkOnce(SkOnceFlag* once, Func f, Arg arg, void(*atExit)()) { + return SkOnce(&once->done, &once->lock, f, arg, atExit); +} + +#undef SK_ANNOTATE_BENIGN_RACE + +#endif // SkOnce_DEFINED diff --git a/gfx/skia/include/core/SkPackBits.h b/gfx/skia/trunk/include/core/SkPackBits.h similarity index 100% rename from gfx/skia/include/core/SkPackBits.h rename to gfx/skia/trunk/include/core/SkPackBits.h diff --git a/gfx/skia/include/core/SkPaint.h b/gfx/skia/trunk/include/core/SkPaint.h similarity index 89% rename from gfx/skia/include/core/SkPaint.h rename to gfx/skia/trunk/include/core/SkPaint.h index a73a46a2c6d3..abb859950c5b 100644 --- a/gfx/skia/include/core/SkPaint.h +++ b/gfx/skia/trunk/include/core/SkPaint.h @@ -13,21 +13,24 @@ #include "SkColor.h" #include "SkDrawLooper.h" +#include "SkMatrix.h" #include "SkXfermode.h" +#ifdef SK_BUILD_FOR_ANDROID +#include "SkPaintOptionsAndroid.h" +#endif class SkAnnotation; class SkAutoGlyphCache; class SkColorFilter; class SkDescriptor; struct SkDeviceProperties; -class SkFlattenableReadBuffer; -class SkFlattenableWriteBuffer; +class SkReadBuffer; +class SkWriteBuffer; struct SkGlyph; struct SkRect; class SkGlyphCache; class SkImageFilter; class SkMaskFilter; -class SkMatrix; class SkPath; class SkPathEffect; struct SkPoint; @@ -40,12 +43,23 @@ typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**, typedef const SkGlyph& (*SkMeasureCacheProc)(SkGlyphCache*, const char**); +#define kBicubicFilterBitmap_Flag kHighQualityFilterBitmap_Flag + /** \class SkPaint The SkPaint class holds the style and color information about how to draw geometries, text and bitmaps. */ + class SK_API SkPaint { + enum { + // DEPRECATED -- use setFilterLevel instead + kFilterBitmap_Flag = 0x02, // temporary flag + // DEPRECATED -- use setFilterLevel instead + kHighQualityFilterBitmap_Flag = 0x4000, // temporary flag + // DEPRECATED -- use setFilterLevel instead + kHighQualityDownsampleBitmap_Flag = 0x8000, // temporary flag + }; public: SkPaint(); SkPaint(const SkPaint& paint); @@ -58,8 +72,8 @@ public: return !(a == b); } - void flatten(SkFlattenableWriteBuffer&) const; - void unflatten(SkFlattenableReadBuffer&); + void flatten(SkWriteBuffer&) const; + void unflatten(SkReadBuffer&); /** Restores the paint to its initial settings. */ @@ -92,7 +106,6 @@ public: */ enum Flags { kAntiAlias_Flag = 0x01, //!< mask to enable antialiasing - kFilterBitmap_Flag = 0x02, //!< mask to enable bitmap filtering kDither_Flag = 0x04, //!< mask to enable dithering kUnderlineText_Flag = 0x08, //!< mask to enable underline text kStrikeThruText_Flag = 0x10, //!< mask to enable strike-thru text @@ -105,11 +118,10 @@ public: kAutoHinting_Flag = 0x800, //!< mask to force Freetype's autohinter kVerticalText_Flag = 0x1000, kGenA8FromLCD_Flag = 0x2000, // hack for GDI -- do not use if you can help it - // when adding extra flags, note that the fFlags member is specified // with a bit-width and you'll have to expand it. - kAllFlags = 0x3FFF + kAllFlags = 0xFFFF }; /** Return the paint's flags. Use the Flag enum to test flag values. @@ -272,11 +284,41 @@ public: */ void setDevKernText(bool devKernText); - bool isFilterBitmap() const { - return SkToBool(this->getFlags() & kFilterBitmap_Flag); + enum FilterLevel { + kNone_FilterLevel, + kLow_FilterLevel, + kMedium_FilterLevel, + kHigh_FilterLevel + }; + + /** + * Return the filter level. This affects the quality (and performance) of + * drawing scaled images. + */ + FilterLevel getFilterLevel() const; + + /** + * Set the filter level. This affects the quality (and performance) of + * drawing scaled images. + */ + void setFilterLevel(FilterLevel); + + /** + * If the predicate is true, set the filterLevel to Low, else set it to + * None. + */ + SK_ATTR_DEPRECATED("use setFilterLevel") + void setFilterBitmap(bool doFilter) { + this->setFilterLevel(doFilter ? kLow_FilterLevel : kNone_FilterLevel); } - void setFilterBitmap(bool filterBitmap); + /** + * Returns true if getFilterLevel() returns anything other than None. + */ + SK_ATTR_DEPRECATED("use getFilterLevel") + bool isFilterBitmap() const { + return kNone_FilterLevel != this->getFilterLevel(); + } /** Styles apply to rect, oval, path, and text. Bitmaps are always drawn in "fill", and lines are always drawn in @@ -597,9 +639,8 @@ public: * Returns true if there is an annotation installed on this paint, and * the annotation specifics no-drawing. */ - bool isNoDrawAnnotation() const { - return SkToBool(fPrivFlags & kNoDrawAnnotation_PrivFlag); - } + SK_ATTR_DEPRECATED("use getAnnotation and check for non-null") + bool isNoDrawAnnotation() const { return this->getAnnotation() != NULL; } /** * Return the paint's SkDrawLooper (if any). Does not affect the looper's @@ -624,8 +665,9 @@ public: kLeft_Align, kCenter_Align, kRight_Align, - - kAlignCount + }; + enum { + kAlignCount = 3 }; /** Return the paint's Align value for drawing text. @@ -674,20 +716,6 @@ public: */ void setTextSkewX(SkScalar skewX); -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - /** Return the paint's scale factor used for correctly rendering - glyphs in high DPI mode without text subpixel positioning. - @return the scale factor used for rendering glyphs in high DPI mode. - */ - SkScalar getHintingScaleFactor() const { return fHintingScaleFactor; } - - /** Set the paint's scale factor used for correctly rendering - glyphs in high DPI mode without text subpixel positioning. - @param the scale factor used for rendering glyphs in high DPI mode. - */ - void setHintingScaleFactor(SkScalar hintingScaleFactor); -#endif - /** Describes how to interpret the text parameters that are passed to paint methods like measureText() and getTextWidths(). */ @@ -709,9 +737,11 @@ public: SkScalar fBottom; //!< The greatest distance below the baseline for any glyph (will be >= 0) SkScalar fLeading; //!< The recommended distance to add between lines of text (will be >= 0) SkScalar fAvgCharWidth; //!< the average charactor width (>= 0) + SkScalar fMaxCharWidth; //!< the max charactor width (>= 0) SkScalar fXMin; //!< The minimum bounding box x value for all glyphs SkScalar fXMax; //!< The maximum bounding box x value for all glyphs - SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face + SkScalar fXHeight; //!< The height of an 'x' in px, or 0 if no 'x' in face + SkScalar fCapHeight; //!< The cap height (> 0), or 0 if cannot be determined. }; /** Return the recommend spacing between lines (which will be @@ -860,6 +890,11 @@ public: /** Returns the base glyph count for the strike associated with this paint */ unsigned getBaseGlyphCount(SkUnichar text) const; + + const SkPaintOptionsAndroid& getPaintOptionsAndroid() const { + return fPaintOptionsAndroid; + } + void setPaintOptionsAndroid(const SkPaintOptionsAndroid& options); #endif // returns true if the paint's settings (e.g. xfermode + alpha) resolve to @@ -908,6 +943,7 @@ public: uintptr_t effects = reinterpret_cast(this->getLooper()); effects |= reinterpret_cast(this->getMaskFilter()); effects |= reinterpret_cast(this->getPathEffect()); + effects |= reinterpret_cast(this->getImageFilter()); if (!effects) { return orig; } @@ -926,6 +962,22 @@ public: const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage, Style) const; + /** + * Return a matrix that applies the paint's text values: size, scale, skew + */ + static SkMatrix* SetTextMatrix(SkMatrix* matrix, SkScalar size, + SkScalar scaleX, SkScalar skewX) { + matrix->setScale(size * scaleX, size); + if (skewX) { + matrix->postSkew(skewX, 0); + } + return matrix; + } + + SkMatrix* setTextMatrix(SkMatrix* matrix) const { + return SetTextMatrix(matrix, fTextSize, fTextScaleX, fTextSkewX); + } + SkDEVCODE(void toString(SkString*) const;) private: @@ -933,9 +985,6 @@ private: SkScalar fTextSize; SkScalar fTextScaleX; SkScalar fTextSkewX; -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - SkScalar fHintingScaleFactor; -#endif SkPathEffect* fPathEffect; SkShader* fShader; @@ -958,11 +1007,8 @@ private: unsigned fStyle : 2; unsigned fTextEncoding : 2; // 3 values unsigned fHinting : 2; - unsigned fPrivFlags : 4; // these are not flattened/unflattened + //unsigned fFreeBits : 4; - enum PrivFlags { - kNoDrawAnnotation_PrivFlag = 1 << 0, - }; SkDrawCacheProc getDrawCacheProc() const; SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir, @@ -980,16 +1026,59 @@ private: static void Term(); enum { - kCanonicalTextSizeForPaths = 64 + /* This is the size we use when we ask for a glyph's path. We then + * post-transform it as we draw to match the request. + * This is done to try to re-use cache entries for the path. + * + * This value is somewhat arbitrary. In theory, it could be 1, since + * we store paths as floats. However, we get the path from the font + * scaler, and it may represent its paths as fixed-point (or 26.6), + * so we shouldn't ask for something too big (might overflow 16.16) + * or too small (underflow 26.6). + * + * This value could track kMaxSizeForGlyphCache, assuming the above + * constraints, but since we ask for unhinted paths, the two values + * need not match per-se. + */ + kCanonicalTextSizeForPaths = 64, + + /* + * Above this size (taking into account CTM and textSize), we never use + * the cache for bits or metrics (we might overflow), so we just ask + * for a caononical size and post-transform that. + */ + kMaxSizeForGlyphCache = 256, }; + + static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM); + + bool tooBigToUseCache() const; + bool tooBigToUseCache(const SkMatrix& ctm) const; + + // Set flags/hinting/textSize up to use for drawing text as paths. + // Returns scale factor to restore the original textSize, since will will + // have change it to kCanonicalTextSizeForPaths. + SkScalar setupForAsPaths(); + + static SkScalar MaxCacheSize2() { + static const SkScalar kMaxSize = SkIntToScalar(kMaxSizeForGlyphCache); + static const SkScalar kMag2Max = kMaxSize * kMaxSize; + return kMag2Max; + } + friend class SkAutoGlyphCache; friend class SkCanvas; friend class SkDraw; friend class SkGraphics; // So Term() can be called. friend class SkPDFDevice; + friend class GrBitmapTextContext; + friend class GrDistanceFieldTextContext; friend class SkTextToPathIter; + friend class SkCanonicalizePaint; #ifdef SK_BUILD_FOR_ANDROID + SkPaintOptionsAndroid fPaintOptionsAndroid; + // In order for the == operator to work properly this must be the last field // in the struct so that we can do a memcmp to this field's offset. uint32_t fGenerationID; diff --git a/gfx/skia/trunk/include/core/SkPaintOptionsAndroid.h b/gfx/skia/trunk/include/core/SkPaintOptionsAndroid.h new file mode 100644 index 000000000000..ab84ec050e35 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkPaintOptionsAndroid.h @@ -0,0 +1,130 @@ + +/* + * Copyright 2012 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkPaintOptionsAndroid_DEFINED +#define SkPaintOptionsAndroid_DEFINED + +#include "SkTypes.h" +#include "SkString.h" + +class SkReadBuffer; +class SkWriteBuffer; + +/** \class SkLanguage + + The SkLanguage class represents a human written language, and is used by + text draw operations to determine which glyph to draw when drawing + characters with variants (ie Han-derived characters). +*/ +class SkLanguage { +public: + SkLanguage() { } + SkLanguage(const SkString& tag) : fTag(tag) { } + SkLanguage(const char* tag) : fTag(tag) { } + SkLanguage(const char* tag, size_t len) : fTag(tag, len) { } + SkLanguage(const SkLanguage& b) : fTag(b.fTag) { } + + /** Gets a BCP 47 language identifier for this SkLanguage. + @return a BCP 47 language identifier representing this language + */ + const SkString& getTag() const { return fTag; } + + /** Performs BCP 47 fallback to return an SkLanguage one step more general. + @return an SkLanguage one step more general + */ + SkLanguage getParent() const; + + bool operator==(const SkLanguage& b) const { + return fTag == b.fTag; + } + bool operator!=(const SkLanguage& b) const { + return fTag != b.fTag; + } + SkLanguage& operator=(const SkLanguage& b) { + fTag = b.fTag; + return *this; + } + +private: + //! BCP 47 language identifier + SkString fTag; +}; + +class SkPaintOptionsAndroid { +public: + SkPaintOptionsAndroid() { + fFontVariant = kDefault_Variant; + fUseFontFallbacks = false; + } + + SkPaintOptionsAndroid& operator=(const SkPaintOptionsAndroid& b) { + fLanguage = b.fLanguage; + fFontVariant = b.fFontVariant; + fUseFontFallbacks = b.fUseFontFallbacks; + return *this; + } + + bool operator==(const SkPaintOptionsAndroid& b) const { + return !(*this != b); + } + + bool operator!=(const SkPaintOptionsAndroid& b) const { + return fLanguage != b.fLanguage || + fFontVariant != b.fFontVariant || + fUseFontFallbacks != b.fUseFontFallbacks; + } + + void flatten(SkWriteBuffer&) const; + void unflatten(SkReadBuffer&); + + /** Return the paint's language value used for drawing text. + @return the paint's language value used for drawing text. + */ + const SkLanguage& getLanguage() const { return fLanguage; } + + /** Set the paint's language value used for drawing text. + @param language set the paint's language value for drawing text. + */ + void setLanguage(const SkLanguage& language) { fLanguage = language; } + void setLanguage(const char* languageTag) { fLanguage = SkLanguage(languageTag); } + + + enum FontVariant { + kDefault_Variant = 0x01, + kCompact_Variant = 0x02, + kElegant_Variant = 0x04, + kLast_Variant = kElegant_Variant, + }; + + /** Return the font variant + @return the font variant used by this paint object + */ + FontVariant getFontVariant() const { return fFontVariant; } + + /** Set the font variant + @param fontVariant set the paint's font variant for choosing fonts + */ + void setFontVariant(FontVariant fontVariant) { + SkASSERT((unsigned)fontVariant <= kLast_Variant); + fFontVariant = fontVariant; + } + + bool isUsingFontFallbacks() const { return fUseFontFallbacks; } + + void setUseFontFallbacks(bool useFontFallbacks) { + fUseFontFallbacks = useFontFallbacks; + } + +private: + SkLanguage fLanguage; + FontVariant fFontVariant; + bool fUseFontFallbacks; +}; + +#endif // #ifndef SkPaintOptionsAndroid_DEFINED diff --git a/gfx/skia/include/core/SkPath.h b/gfx/skia/trunk/include/core/SkPath.h similarity index 84% rename from gfx/skia/include/core/SkPath.h rename to gfx/skia/trunk/include/core/SkPath.h index 3b5424fe8f39..d78cd8829677 100644 --- a/gfx/skia/include/core/SkPath.h +++ b/gfx/skia/trunk/include/core/SkPath.h @@ -12,28 +12,16 @@ #include "SkInstCnt.h" #include "SkMatrix.h" +#include "SkPathRef.h" #include "SkTDArray.h" #include "SkRefCnt.h" -#ifdef SK_BUILD_FOR_ANDROID -#define GEN_ID_INC fGenerationID++ -#define GEN_ID_PTR_INC(ptr) ptr->fGenerationID++ -#else -#define GEN_ID_INC -#define GEN_ID_PTR_INC(ptr) -#endif - class SkReader32; class SkWriter32; class SkAutoPathBoundsUpdate; class SkString; -class SkPathRef; class SkRRect; -#ifndef SK_DEBUG_PATH_REF - #define SK_DEBUG_PATH_REF 0 -#endif - /** \class SkPath The SkPath class encapsulates compound (multiple contour) geometric paths @@ -48,7 +36,6 @@ public: ~SkPath(); SkPath& operator=(const SkPath&); - friend SK_API bool operator==(const SkPath&, const SkPath&); friend bool operator!=(const SkPath& a, const SkPath& b) { return !(a == b); @@ -85,7 +72,6 @@ public: */ void setFillType(FillType ft) { fFillType = SkToU8(ft); - GEN_ID_INC; } /** Returns true if the filltype is one of the Inverse variants */ @@ -97,8 +83,7 @@ public: */ void toggleInverseFillType() { fFillType ^= 2; - GEN_ID_INC; - } + } enum Convexity { kUnknown_Convexity, @@ -138,7 +123,6 @@ public: void setConvexity(Convexity); /** - * DEPRECATED: use getConvexity() * Returns true if the path is flagged as being convex. This is not a * confirmed by any analysis, it is just the value set earlier. */ @@ -147,12 +131,12 @@ public: } /** - * DEPRECATED: use setConvexity() * Set the isConvex flag to true or false. Convex paths may draw faster if * this flag is set, though setting this to true on a path that is in fact * not convex can give undefined results when drawn. Paths default to * isConvex == false */ + SK_ATTR_DEPRECATED("use setConvexity") void setIsConvex(bool isConvex) { this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity); } @@ -167,18 +151,18 @@ public: * optimization for performance and so some paths that are in * fact ovals can report false. */ - bool isOval(SkRect* rect) const; + bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); } /** Clear any lines and curves from the path, making it empty. This frees up internal storage associated with those segments. - This does NOT change the fill-type setting nor isConvex + On Android, does not change fSourcePath. */ void reset(); /** Similar to reset(), in that all lines and curves are removed from the path. However, any internal storage for those lines/curves is retained, making reuse of the path potentially faster. - This does NOT change the fill-type setting nor isConvex + On Android, does not change fSourcePath. */ void rewind(); @@ -186,17 +170,18 @@ public: @return true if the path is empty (contains no lines or curves) */ - bool isEmpty() const; + bool isEmpty() const { + SkDEBUGCODE(this->validate();) + return 0 == fPathRef->countVerbs(); + } /** * Returns true if all of the points in this path are finite, meaning there * are no infinities and no NaNs. */ bool isFinite() const { - if (fBoundsIsDirty) { - this->computeBounds(); - } - return SkToBool(fIsFinite); + SkDEBUGCODE(this->validate();) + return fPathRef->isFinite(); } /** Test a line for zero length @@ -246,16 +231,6 @@ public: */ bool isRect(SkRect* rect) const; - /** Returns true if the path specifies a pair of nested rectangles. If so, and if - rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner - rectangle. If the path does not specify a pair of nested rectangles, return - false and ignore rect. - - @param rect If not null, returns the path as a pair of nested rectangles - @return true if the path describes a pair of nested rectangles - */ - bool isNestedRects(SkRect rect[2]) const; - /** Return the number of points in the path */ int countPoints() const; @@ -296,10 +271,7 @@ public: do not extend as far as their control points. */ const SkRect& getBounds() const { - if (fBoundsIsDirty) { - this->computeBounds(); - } - return fBounds; + return fPathRef->getBounds(); } /** Calling this will, if the internal cache of the bounds is out of date, @@ -423,6 +395,14 @@ public: */ void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2); + void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, + SkScalar w); + void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) { + this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w); + } + void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, + SkScalar w); + /** Add a cubic bezier from the last point, approaching control points (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been made for this contour, the first point is automatically set to (0,0). @@ -466,8 +446,8 @@ public: @param dy3 The amount to add to the y-coordinate of the last point on this contour, to specify the end point of a cubic curve */ - void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, - SkScalar x3, SkScalar y3); + void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, + SkScalar x3, SkScalar y3); /** Append the specified arc to the path as a new contour. If the start of the path is different from the path's current last point, then an @@ -481,8 +461,8 @@ public: treated mod 360. @param forceMoveTo If true, always begin a new contour with the arc */ - void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, - bool forceMoveTo); + void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, + bool forceMoveTo); /** Append a line and arc to the current path. This is the same as the PostScript call "arct". @@ -575,6 +555,25 @@ public: return computedDir == dir; } + enum PathAsRect { + /** The path can not draw the same as its bounds. */ + kNone_PathAsRect, + /** The path draws the same as its bounds when filled. */ + kFill_PathAsRect, + /** The path draws the same as its bounds when stroked or filled. */ + kStroke_PathAsRect, + }; + + /** Returns kFill_PathAsRect or kStroke_PathAsRect if drawing the path (either filled or + stroked) will be equivalent to filling/stroking the path's bounding rect. If + either is true, and direction is not null, sets the direction of the contour. If the + path is not drawn equivalent to a rect, returns kNone_PathAsRect and ignores direction. + + @param direction If not null, set to the contour's direction when it is drawn as a rect + @return the path's PathAsRect type + */ + PathAsRect asRect(Direction* direction = NULL) const; + /** Returns true if the path specifies a rectangle. If so, and if isClosed is not null, set isClosed to true if the path is closed. Also, if returning true and direction is not null, return the rect direction. If the path does not @@ -586,13 +585,26 @@ public: */ bool isRect(bool* isClosed, Direction* direction) const; + /** Returns true if the path specifies a pair of nested rectangles. If so, and if + rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner + rectangle. If so, and dirs is not null, set dirs[0] to the direction of + the outer rectangle and dirs[1] to the direction of the inner rectangle. If + the path does not specify a pair of nested rectangles, return + false and ignore rect and dirs. + + @param rect If not null, returns the path as a pair of nested rectangles + @param dirs If not null, returns the direction of the rects + @return true if the path describes a pair of nested rectangles + */ + bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const; + /** * Add a closed rectangle contour to the path * @param rect The rectangle to add as a closed contour to the path * @param dir The direction to wind the rectangle's contour. Cannot be * kUnknown_Direction. */ - void addRect(const SkRect& rect, Direction dir = kCW_Direction); + void addRect(const SkRect& rect, Direction dir = kCW_Direction); /** * Add a closed rectangle contour to the path @@ -651,8 +663,8 @@ public: * @param dir The direction to wind the rectangle's contour. Cannot be * kUnknown_Direction. */ - void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, - Direction dir = kCW_Direction); + void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, + Direction dir = kCW_Direction); /** * Add a closed round-rectangle contour to the path. Each corner receives @@ -690,25 +702,41 @@ public: */ void addPoly(const SkPoint pts[], int count, bool close); + enum AddPathMode { + /** Source path contours are added as new contours. + */ + kAppend_AddPathMode, + /** Path is added by extending the last contour of the destination path + with the first contour of the source path. If the last contour of + the destination path is closed, then it will not be extended. + Instead, the start of source path will be extended by a straight + line to the end point of the destination path. + */ + kExtend_AddPathMode + }; + /** Add a copy of src to the path, offset by (dx,dy) @param src The path to add as a new contour @param dx The amount to translate the path in X as it is added @param dx The amount to translate the path in Y as it is added */ - void addPath(const SkPath& src, SkScalar dx, SkScalar dy); + void addPath(const SkPath& src, SkScalar dx, SkScalar dy, + AddPathMode mode = kAppend_AddPathMode); /** Add a copy of src to the path */ - void addPath(const SkPath& src) { + void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) { SkMatrix m; m.reset(); - this->addPath(src, m); + this->addPath(src, m, mode); } /** Add a copy of src to the path, transformed by matrix @param src The path to add as a new contour + @param matrix Transform applied to src + @param mode Determines how path is added */ - void addPath(const SkPath& src, const SkMatrix& matrix); + void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode); /** * Same as addPath(), but reverses the src input @@ -776,7 +804,8 @@ public: enum SegmentMask { kLine_SegmentMask = 1 << 0, kQuad_SegmentMask = 1 << 1, - kCubic_SegmentMask = 1 << 2 + kConic_SegmentMask = 1 << 2, + kCubic_SegmentMask = 1 << 3, }; /** @@ -784,15 +813,16 @@ public: * set if the path contains 1 or more segments of that type. * Returns 0 for an empty path (no segments). */ - uint32_t getSegmentMasks() const { return fSegmentMask; } + uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); } enum Verb { kMove_Verb, //!< iter.next returns 1 point kLine_Verb, //!< iter.next returns 2 points kQuad_Verb, //!< iter.next returns 3 points + kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight() kCubic_Verb, //!< iter.next returns 4 points kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt) - kDone_Verb //!< iter.next returns 0 points + kDone_Verb, //!< iter.next returns 0 points }; /** Iterate through all of the segments (lines, quadratics, cubics) of @@ -826,6 +856,12 @@ public: return this->doNext(pts); } + /** + * Return the weight for the current conic. Only valid if the current + * segment return by next() was a conic. + */ + SkScalar conicWeight() const { return *fConicWeights; } + /** If next() returns kLine_Verb, then this query returns true if the line was the result of a close() command (i.e. the end point is the initial moveto for this contour). If next() returned a different @@ -845,6 +881,7 @@ public: const SkPoint* fPts; const uint8_t* fVerbs; const uint8_t* fVerbStop; + const SkScalar* fConicWeights; SkPoint fMoveTo; SkPoint fLastPt; SkBool8 fForceClose; @@ -876,10 +913,13 @@ public: */ Verb next(SkPoint pts[4]); + SkScalar conicWeight() const { return *fConicWeights; } + private: const SkPoint* fPts; const uint8_t* fVerbs; const uint8_t* fVerbStop; + const SkScalar* fConicWeights; SkPoint fMoveTo; SkPoint fLastPt; }; @@ -894,84 +934,73 @@ public: void dump() const; /** - * Write the region to the buffer, and return the number of bytes written. + * Write the path to the buffer, and return the number of bytes written. * If buffer is NULL, it still returns the number of bytes. */ - uint32_t writeToMemory(void* buffer) const; + size_t writeToMemory(void* buffer) const; /** - * Initialized the region from the buffer, returning the number - * of bytes actually read. + * Initializes the path from the buffer + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); + + /** Returns a non-zero, globally unique value corresponding to the set of verbs + and points in the path (but not the fill type [except on Android skbug.com/1762]). + Each time the path is modified, a different generation ID will be returned. + */ + uint32_t getGenerationID() const; #ifdef SK_BUILD_FOR_ANDROID - uint32_t getGenerationID() const; + static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762) const SkPath* getSourcePath() const; void setSourcePath(const SkPath* path); +#else + static const int kPathRefGenIDBitCnt = 32; #endif SkDEBUGCODE(void validate() const;) private: enum SerializationOffsets { + // 1 free bit at 29 + kUnused1_SerializationShift = 28, // 1 free bit kDirection_SerializationShift = 26, // requires 2 bits - kIsFinite_SerializationShift = 25, // requires 1 bit - kIsOval_SerializationShift = 24, // requires 1 bit - kConvexity_SerializationShift = 16, // requires 2 bits - kFillType_SerializationShift = 8, // requires 2 bits - kSegmentMask_SerializationShift = 0 // requires 3 bits + kUnused2_SerializationShift = 25, // 1 free bit + // 1 free bit at 24 + kConvexity_SerializationShift = 16, // requires 8 bits + kFillType_SerializationShift = 8, // requires 8 bits + // 8 free bits at 0 }; -#if SK_DEBUG_PATH_REF -public: - /** Debugging wrapper for SkAutoTUnref used to track owners (SkPaths) - of SkPathRefs */ - class PathRefDebugRef { - public: - PathRefDebugRef(SkPath* owner); - PathRefDebugRef(SkPathRef* pr, SkPath* owner); - ~PathRefDebugRef(); - void reset(SkPathRef* ref); - void swap(PathRefDebugRef* other); - SkPathRef* get() const; - SkAutoTUnref::BlockRefType *operator->() const; - operator SkPathRef*(); - private: - SkAutoTUnref fPathRef; - SkPath* fOwner; - }; - -private: - PathRefDebugRef fPathRef; -#else SkAutoTUnref fPathRef; -#endif - mutable SkRect fBounds; int fLastMoveToIndex; uint8_t fFillType; - uint8_t fSegmentMask; - mutable uint8_t fBoundsIsDirty; mutable uint8_t fConvexity; mutable uint8_t fDirection; - mutable SkBool8 fIsFinite; // only meaningful if bounds are valid - mutable SkBool8 fIsOval; #ifdef SK_BUILD_FOR_ANDROID - uint32_t fGenerationID; const SkPath* fSourcePath; #endif - // called, if dirty, by getBounds() - void computeBounds() const; + /** Resets all fields other than fPathRef to their initial 'empty' values. + * Assumes the caller has already emptied fPathRef. + * On Android increments fGenerationID without reseting it. + */ + void resetFields(); + + /** Sets all fields other than fPathRef to the values in 'that'. + * Assumes the caller has already set fPathRef. + * Doesn't change fGenerationID or fSourcePath on Android. + */ + void copyFields(const SkPath& that); friend class Iter; friend class SkPathStroker; - /* Append the first contour of path, ignoring path's initial point. If no - moveTo() call has been made for this contour, the first point is - automatically set to (0,0). - */ - void pathTo(const SkPath& path); /* Append, in reverse order, the first contour of path, ignoring path's last point. If no moveTo() call has been made for this contour, the @@ -994,10 +1023,27 @@ private: bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts, bool* isClosed, Direction* direction) const; + /** Returns if the path can return a bound at no cost (true) or will have to + perform some computation (false). + */ + bool hasComputedBounds() const { + SkDEBUGCODE(this->validate();) + return fPathRef->hasComputedBounds(); + } + + + // 'rect' needs to be sorted + void setBounds(const SkRect& rect) { + SkPathRef::Editor ed(&fPathRef); + + ed.setBounds(rect); + } + friend class SkAutoPathBoundsUpdate; friend class SkAutoDisableOvalCheck; friend class SkAutoDisableDirectionCheck; - friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo + friend class SkBench_AddPathTest; // perf test reversePathTo + friend class PathTest_Private; // unit test reversePathTo }; #endif diff --git a/gfx/skia/include/core/SkPathEffect.h b/gfx/skia/trunk/include/core/SkPathEffect.h similarity index 95% rename from gfx/skia/include/core/SkPathEffect.h rename to gfx/skia/trunk/include/core/SkPathEffect.h index 3b4541de5681..3f38f3a101a5 100644 --- a/gfx/skia/include/core/SkPathEffect.h +++ b/gfx/skia/trunk/include/core/SkPathEffect.h @@ -106,8 +106,10 @@ public: const SkStrokeRec&, const SkMatrix&, const SkRect* cullR) const; + SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect) + protected: - SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} private: // illegal @@ -129,8 +131,8 @@ public: virtual ~SkPairPathEffect(); protected: - SkPairPathEffect(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkPairPathEffect(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // these are visible to our subclasses SkPathEffect* fPE0, *fPE1; @@ -160,7 +162,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) protected: - SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkComposePathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} private: // illegal @@ -191,7 +193,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) protected: - SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkSumPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} private: // illegal diff --git a/gfx/skia/include/core/SkPathMeasure.h b/gfx/skia/trunk/include/core/SkPathMeasure.h similarity index 98% rename from gfx/skia/include/core/SkPathMeasure.h rename to gfx/skia/trunk/include/core/SkPathMeasure.h index 6866ccedae56..bc46b4a38b19 100644 --- a/gfx/skia/include/core/SkPathMeasure.h +++ b/gfx/skia/trunk/include/core/SkPathMeasure.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,14 +5,13 @@ * found in the LICENSE file. */ - #ifndef SkPathMeasure_DEFINED #define SkPathMeasure_DEFINED #include "SkPath.h" #include "SkTDArray.h" -class SkPathMeasure : SkNoncopyable { +class SK_API SkPathMeasure : SkNoncopyable { public: SkPathMeasure(); /** Initialize the pathmeasure with the specified path. The path must remain valid diff --git a/gfx/skia/trunk/include/core/SkPathRef.h b/gfx/skia/trunk/include/core/SkPathRef.h new file mode 100644 index 000000000000..880271424309 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkPathRef.h @@ -0,0 +1,458 @@ + +/* + * 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 SkPathRef_DEFINED +#define SkPathRef_DEFINED + +#include "SkMatrix.h" +#include "SkPoint.h" +#include "SkRect.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" +#include // ptrdiff_t + +class SkRBuffer; +class SkWBuffer; + +/** + * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods + * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an + * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs + * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's + * constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef after the editor's + * constructor returns. + * + * The points and verbs are stored in a single allocation. The points are at the begining of the + * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points + * and verbs both grow into the middle of the allocation until the meet. To access verb i in the + * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first + * logical verb or the last verb in memory). + */ + +class SK_API SkPathRef : public ::SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkPathRef); + + class Editor { + public: + Editor(SkAutoTUnref* pathRef, + int incReserveVerbs = 0, + int incReservePoints = 0); + + ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) } + + /** + * Returns the array of points. + */ + SkPoint* points() { return fPathRef->getPoints(); } + const SkPoint* points() const { return fPathRef->points(); } + + /** + * Gets the ith point. Shortcut for this->points() + i + */ + SkPoint* atPoint(int i) { + SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); + return this->points() + i; + }; + const SkPoint* atPoint(int i) const { + SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt); + return this->points() + i; + }; + + /** + * Adds the verb and allocates space for the number of points indicated by the verb. The + * return value is a pointer to where the points for the verb should be written. + * 'weight' is only used if 'verb' is kConic_Verb + */ + SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) { + SkDEBUGCODE(fPathRef->validate();) + return fPathRef->growForVerb(verb, weight); + } + + /** + * Allocates space for multiple instances of a particular verb and the + * requisite points & weights. + * The return pointer points at the first new point (indexed normally []). + * If 'verb' is kConic_Verb, 'weights' will return a pointer to the + * space for the conic weights (indexed normally). + */ + SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, + int numVbs, + SkScalar** weights = NULL) { + return fPathRef->growForRepeatedVerb(verb, numVbs, weights); + } + + /** + * Resets the path ref to a new verb and point count. The new verbs and points are + * uninitialized. + */ + void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) { + fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount); + } + + /** + * Gets the path ref that is wrapped in the Editor. + */ + SkPathRef* pathRef() { return fPathRef; } + + void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); } + + void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); } + + private: + SkPathRef* fPathRef; + }; + +public: + /** + * Gets a path ref with no verbs or points. + */ + static SkPathRef* CreateEmpty(); + + /** + * Returns true if all of the points in this path are finite, meaning there + * are no infinities and no NaNs. + */ + bool isFinite() const { + if (fBoundsIsDirty) { + this->computeBounds(); + } + return SkToBool(fIsFinite); + } + + /** + * Returns a mask, where each bit corresponding to a SegmentMask is + * set if the path contains 1 or more segments of that type. + * Returns 0 for an empty path (no segments). + */ + uint32_t getSegmentMasks() const { return fSegmentMask; } + + /** Returns true if the path is an oval. + * + * @param rect returns the bounding rect of this oval. It's a circle + * if the height and width are the same. + * + * @return true if this path is an oval. + * Tracking whether a path is an oval is considered an + * optimization for performance and so some paths that are in + * fact ovals can report false. + */ + bool isOval(SkRect* rect) const { + if (fIsOval && NULL != rect) { + *rect = getBounds(); + } + + return SkToBool(fIsOval); + } + + bool hasComputedBounds() const { + return !fBoundsIsDirty; + } + + /** Returns the bounds of the path's points. If the path contains 0 or 1 + points, the bounds is set to (0,0,0,0), and isEmpty() will return true. + Note: this bounds may be larger than the actual shape, since curves + do not extend as far as their control points. + */ + const SkRect& getBounds() const { + if (fBoundsIsDirty) { + this->computeBounds(); + } + return fBounds; + } + + /** + * Transforms a path ref by a matrix, allocating a new one only if necessary. + */ + static void CreateTransformedCopy(SkAutoTUnref* dst, + const SkPathRef& src, + const SkMatrix& matrix); + + static SkPathRef* CreateFromBuffer(SkRBuffer* buffer); + + /** + * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be + * repopulated with approximately the same number of verbs and points. A new path ref is created + * only if necessary. + */ + static void Rewind(SkAutoTUnref* pathRef); + + virtual ~SkPathRef() { + SkDEBUGCODE(this->validate();) + sk_free(fPoints); + + SkDEBUGCODE(fPoints = NULL;) + SkDEBUGCODE(fVerbs = NULL;) + SkDEBUGCODE(fVerbCnt = 0x9999999;) + SkDEBUGCODE(fPointCnt = 0xAAAAAAA;) + SkDEBUGCODE(fPointCnt = 0xBBBBBBB;) + SkDEBUGCODE(fGenerationID = 0xEEEEEEEE;) + SkDEBUGCODE(fEditorsAttached = 0x7777777;) + } + + int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; } + int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; } + int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); } + + /** + * Returns a pointer one beyond the first logical verb (last verb in memory order). + */ + const uint8_t* verbs() const { SkDEBUGCODE(this->validate();) return fVerbs; } + + /** + * Returns a const pointer to the first verb in memory (which is the last logical verb). + */ + const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; } + + /** + * Returns a const pointer to the first point. + */ + const SkPoint* points() const { SkDEBUGCODE(this->validate();) return fPoints; } + + /** + * Shortcut for this->points() + this->countPoints() + */ + const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); } + + const SkScalar* conicWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.begin(); } + const SkScalar* conicWeightsEnd() const { SkDEBUGCODE(this->validate();) return fConicWeights.end(); } + + /** + * Convenience methods for getting to a verb or point by index. + */ + uint8_t atVerb(int index) const { + SkASSERT((unsigned) index < (unsigned) fVerbCnt); + return this->verbs()[~index]; + } + const SkPoint& atPoint(int index) const { + SkASSERT((unsigned) index < (unsigned) fPointCnt); + return this->points()[index]; + } + + bool operator== (const SkPathRef& ref) const; + + /** + * Writes the path points and verbs to a buffer. + */ + void writeToBuffer(SkWBuffer* buffer) const; + + /** + * Gets the number of bytes that would be written in writeBuffer() + */ + uint32_t writeSize() const; + + /** + * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the + * same ID then they have the same verbs and points. However, two path refs may have the same + * contents but different genIDs. + */ + uint32_t genID() const; + +private: + enum SerializationOffsets { + kIsFinite_SerializationShift = 25, // requires 1 bit + kIsOval_SerializationShift = 24, // requires 1 bit + kSegmentMask_SerializationShift = 0 // requires 4 bits + }; + + SkPathRef() { + fBoundsIsDirty = true; // this also invalidates fIsFinite + fPointCnt = 0; + fVerbCnt = 0; + fVerbs = NULL; + fPoints = NULL; + fFreeSpace = 0; + fGenerationID = kEmptyGenID; + fSegmentMask = 0; + fIsOval = false; + SkDEBUGCODE(fEditorsAttached = 0;) + SkDEBUGCODE(this->validate();) + } + + void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints); + + // Return true if the computed bounds are finite. + static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) { + int count = ref.countPoints(); + if (count <= 1) { // we ignore just 1 point (moveto) + bounds->setEmpty(); + return count ? ref.points()->isFinite() : true; + } else { + return bounds->setBoundsCheck(ref.points(), count); + } + } + + // called, if dirty, by getBounds() + void computeBounds() const { + SkDEBUGCODE(this->validate();) + SkASSERT(fBoundsIsDirty); + + fIsFinite = ComputePtBounds(&fBounds, *this); + fBoundsIsDirty = false; + } + + void setBounds(const SkRect& rect) { + SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom); + fBounds = rect; + fBoundsIsDirty = false; + fIsFinite = fBounds.isFinite(); + } + + /** Makes additional room but does not change the counts or change the genID */ + void incReserve(int additionalVerbs, int additionalPoints) { + SkDEBUGCODE(this->validate();) + size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint); + this->makeSpace(space); + SkDEBUGCODE(this->validate();) + } + + /** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also + * allocates space for reserveVerb additional verbs and reservePoints additional points.*/ + void resetToSize(int verbCount, int pointCount, int conicCount, + int reserveVerbs = 0, int reservePoints = 0) { + SkDEBUGCODE(this->validate();) + fBoundsIsDirty = true; // this also invalidates fIsFinite + fGenerationID = 0; + + fSegmentMask = 0; + fIsOval = false; + + size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount; + size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints; + size_t minSize = newSize + newReserve; + + ptrdiff_t sizeDelta = this->currSize() - minSize; + + if (sizeDelta < 0 || static_cast(sizeDelta) >= 3 * minSize) { + sk_free(fPoints); + fPoints = NULL; + fVerbs = NULL; + fFreeSpace = 0; + fVerbCnt = 0; + fPointCnt = 0; + this->makeSpace(minSize); + fVerbCnt = verbCount; + fPointCnt = pointCount; + fFreeSpace -= newSize; + } else { + fPointCnt = pointCount; + fVerbCnt = verbCount; + fFreeSpace = this->currSize() - minSize; + } + fConicWeights.setCount(conicCount); + SkDEBUGCODE(this->validate();) + } + + /** + * Increases the verb count by numVbs and point count by the required amount. + * The new points are uninitialized. All the new verbs are set to the specified + * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the + * uninitialized conic weights. + */ + SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights); + + /** + * Increases the verb count 1, records the new verb, and creates room for the requisite number + * of additional points. A pointer to the first point is returned. Any new points are + * uninitialized. + */ + SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight); + + /** + * Ensures that the free space available in the path ref is >= size. The verb and point counts + * are not changed. + */ + void makeSpace(size_t size) { + SkDEBUGCODE(this->validate();) + ptrdiff_t growSize = size - fFreeSpace; + if (growSize <= 0) { + return; + } + size_t oldSize = this->currSize(); + // round to next multiple of 8 bytes + growSize = (growSize + 7) & ~static_cast(7); + // we always at least double the allocation + if (static_cast(growSize) < oldSize) { + growSize = oldSize; + } + if (growSize < kMinSize) { + growSize = kMinSize; + } + size_t newSize = oldSize + growSize; + // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO: + // encapsulate this. + fPoints = reinterpret_cast(sk_realloc_throw(fPoints, newSize)); + size_t oldVerbSize = fVerbCnt * sizeof(uint8_t); + void* newVerbsDst = reinterpret_cast( + reinterpret_cast(fPoints) + newSize - oldVerbSize); + void* oldVerbsSrc = reinterpret_cast( + reinterpret_cast(fPoints) + oldSize - oldVerbSize); + memmove(newVerbsDst, oldVerbsSrc, oldVerbSize); + fVerbs = reinterpret_cast(reinterpret_cast(fPoints) + newSize); + fFreeSpace += growSize; + SkDEBUGCODE(this->validate();) + } + + /** + * Private, non-const-ptr version of the public function verbsMemBegin(). + */ + uint8_t* verbsMemWritable() { + SkDEBUGCODE(this->validate();) + return fVerbs - fVerbCnt; + } + + /** + * Gets the total amount of space allocated for verbs, points, and reserve. + */ + size_t currSize() const { + return reinterpret_cast(fVerbs) - reinterpret_cast(fPoints); + } + + SkDEBUGCODE(void validate() const;) + + /** + * Called the first time someone calls CreateEmpty to actually create the singleton. + */ + static void CreateEmptyImpl(int/*unused*/); + + void setIsOval(bool isOval) { fIsOval = isOval; } + + SkPoint* getPoints() { + SkDEBUGCODE(this->validate();) + fIsOval = false; + return fPoints; + } + + enum { + kMinSize = 256, + }; + + mutable SkRect fBounds; + uint8_t fSegmentMask; + mutable uint8_t fBoundsIsDirty; + mutable SkBool8 fIsFinite; // only meaningful if bounds are valid + mutable SkBool8 fIsOval; + + SkPoint* fPoints; // points to begining of the allocation + uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards) + int fVerbCnt; + int fPointCnt; + size_t fFreeSpace; // redundant but saves computation + SkTDArray fConicWeights; + + enum { + kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs. + }; + mutable uint32_t fGenerationID; + SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time. + + friend class PathRefTest_Private; + typedef SkRefCnt INHERITED; +}; + +#endif diff --git a/gfx/skia/include/core/SkPicture.h b/gfx/skia/trunk/include/core/SkPicture.h similarity index 63% rename from gfx/skia/include/core/SkPicture.h rename to gfx/skia/trunk/include/core/SkPicture.h index 792955727068..a717153dbed9 100644 --- a/gfx/skia/include/core/SkPicture.h +++ b/gfx/skia/trunk/include/core/SkPicture.h @@ -11,15 +11,20 @@ #define SkPicture_DEFINED #include "SkBitmap.h" +#include "SkImageDecoder.h" #include "SkRefCnt.h" class SkBBoxHierarchy; class SkCanvas; +class SkDrawPictureCallback; +class SkData; class SkPicturePlayback; class SkPictureRecord; class SkStream; class SkWStream; +struct SkPictInfo; + /** \class SkPicture The SkPicture class records the drawing commands made to a canvas, to @@ -39,13 +44,6 @@ public: */ SkPicture(const SkPicture& src); - /** - * Recreate a picture that was serialized into a stream. - * On failure, silently creates an empty picture. - * @param SkStream Serialized picture data. - */ - explicit SkPicture(SkStream*); - /** * Function signature defining a function that sets up an SkBitmap from encoded data. On * success, the SkBitmap should have its Config, width, height, rowBytes and pixelref set. @@ -62,12 +60,23 @@ public: /** * Recreate a picture that was serialized into a stream. * @param SkStream Serialized picture data. - * @param success Output parameter. If non-NULL, will be set to true if the picture was - * deserialized successfully and false otherwise. * @param proc Function pointer for installing pixelrefs on SkBitmaps representing the * encoded bitmap data from the stream. + * @return A new SkPicture representing the serialized data, or NULL if the stream is + * invalid. */ - SkPicture(SkStream*, bool* success, InstallPixelRefProc proc); + static SkPicture* CreateFromStream(SkStream*, + InstallPixelRefProc proc = &SkImageDecoder::DecodeMemory); + + /** + * Recreate a picture that was serialized into a buffer. If the creation requires bitmap + * decoding, the decoder must be set on the SkReadBuffer parameter by calling + * SkReadBuffer::setBitmapDecoder() before calling SkPicture::CreateFromBuffer(). + * @param SkReadBuffer Serialized picture data. + * @return A new SkPicture representing the serialized data, or NULL if the buffer is + * invalid. + */ + static SkPicture* CreateFromBuffer(SkReadBuffer&); virtual ~SkPicture(); @@ -115,7 +124,16 @@ public: Note: Currently this is not serializable, the bounding data will be discarded if you serialize into a stream and then deserialize. */ - kOptimizeForClippedPlayback_RecordingFlag = 0x02 + kOptimizeForClippedPlayback_RecordingFlag = 0x02, + /* + This flag disables all the picture recording optimizations (i.e., + those in SkPictureRecord). It is mainly intended for testing the + existing optimizations (i.e., to actually have the pattern + appear in an .skp we have to disable the optimization). This + option doesn't affect the optimizations controlled by + 'kOptimizeForClippedPlayback_RecordingFlag'. + */ + kDisableRecordOptimizations_RecordingFlag = 0x04 }; /** Returns the canvas that records the drawing commands. @@ -141,9 +159,9 @@ public: /** Replays the drawing commands on the specified canvas. This internally calls endRecording() if that has not already been called. - @param surface the canvas receiving the drawing commands. + @param canvas the canvas receiving the drawing commands. */ - void draw(SkCanvas* surface); + void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL); /** Return the width of the picture's recording canvas. This value reflects what was passed to setSize(), and does not necessarily @@ -160,20 +178,36 @@ public: int height() const { return fHeight; } /** - * Function to encode an SkBitmap to an SkWStream. A function with this - * signature can be passed to serialize() and SkOrderedWriteBuffer. The - * function should return true if it succeeds. Otherwise it should return - * false so that SkOrderedWriteBuffer can switch to another method of - * storing SkBitmaps. + * Function to encode an SkBitmap to an SkData. A function with this + * signature can be passed to serialize() and SkWriteBuffer. + * Returning NULL will tell the SkWriteBuffer to use + * SkBitmap::flatten() to store the bitmap. + * + * @param pixelRefOffset DEPRECATED -- caller assumes it will return 0. + * @return SkData If non-NULL, holds encoded data representing the passed + * in bitmap. The caller is responsible for calling unref(). */ - typedef bool (*EncodeBitmap)(SkWStream*, const SkBitmap&); + typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm); /** * Serialize to a stream. If non NULL, encoder will be used to encode * any bitmaps in the picture. + * encoder will never be called with a NULL pixelRefOffset. */ void serialize(SkWStream*, EncodeBitmap encoder = NULL) const; + /** + * Serialize to a buffer. + */ + void flatten(SkWriteBuffer&) const; + + /** + * Returns true if any bitmaps may be produced when this SkPicture + * is replayed. + * Returns false if called while still recording. + */ + bool willPlayBackBitmaps() const; + #ifdef SK_BUILD_FOR_ANDROID /** Signals that the caller is prematurely done replaying the drawing commands. This can be called from a canvas virtual while the picture @@ -194,7 +228,18 @@ protected: // V9 : Allow the reader and writer of an SKP disagree on whether to support // SK_SUPPORT_HINTING_SCALE_FACTOR // V10: add drawRRect, drawOval, clipRRect - static const uint32_t PICTURE_VERSION = 10; + // V11: modify how readBitmap and writeBitmap store their info. + // V12: add conics to SkPath, use new SkPathRef flattening + // V13: add flag to drawBitmapRectToRect + // parameterize blurs by sigma rather than radius + // V14: Add flags word to PathRef serialization + // V15: Remove A1 bitmpa config (and renumber remaining configs) + // V16: Move SkPath's isOval flag to SkPathRef + // V17: SkPixelRef now writes SkImageInfo + // V18: SkBitmap now records x,y for its pixelref origin, instead of offset. + // V19: encode matrices and regions into the ops stream + // V20: added bool to SkPictureImageFilter's serialization (to allow SkPicture serialization) + static const uint32_t PICTURE_VERSION = 20; // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to // install their own SkPicturePlayback-derived players,SkPictureRecord-derived @@ -203,12 +248,22 @@ protected: SkPictureRecord* fRecord; int fWidth, fHeight; + // Create a new SkPicture from an existing SkPicturePlayback. Ref count of + // playback is unchanged. + SkPicture(SkPicturePlayback*, int width, int height); + // For testing. Derived classes may instantiate an alternate // SkBBoxHierarchy implementation virtual SkBBoxHierarchy* createBBoxHierarchy() const; + // Return true if the SkStream represents a serialized picture, and fills out + // SkPictInfo. After this function returns, the SkStream is not rewound; it + // will be ready to be parsed to create an SkPicturePlayback. + // If false is returned, SkPictInfo is unmodified. + static bool StreamIsSKP(SkStream*, SkPictInfo*); + static bool BufferIsSKP(SkReadBuffer&, SkPictInfo*); private: - void initFromStream(SkStream*, bool* success, InstallPixelRefProc); + void createHeader(void* header) const; friend class SkFlatPicture; friend class SkPicturePlayback; @@ -216,25 +271,22 @@ private: typedef SkRefCnt INHERITED; }; -class SkAutoPictureRecord : SkNoncopyable { +/** + * Subclasses of this can be passed to canvas.drawPicture. During the drawing + * of the picture, this callback will periodically be invoked. If its + * abortDrawing() returns true, then picture playback will be interrupted. + * + * The resulting drawing is undefined, as there is no guarantee how often the + * callback will be invoked. If the abort happens inside some level of nested + * calls to save(), restore will automatically be called to return the state + * to the same level it was before the drawPicture call was made. + */ +class SK_API SkDrawPictureCallback { public: - SkAutoPictureRecord(SkPicture* pict, int width, int height, - uint32_t recordingFlags = 0) { - fPicture = pict; - fCanvas = pict->beginRecording(width, height, recordingFlags); - } - ~SkAutoPictureRecord() { - fPicture->endRecording(); - } + SkDrawPictureCallback() {} + virtual ~SkDrawPictureCallback() {} - /** Return the canvas to draw into for recording into the picture. - */ - SkCanvas* getRecordingCanvas() const { return fCanvas; } - -private: - SkPicture* fPicture; - SkCanvas* fCanvas; + virtual bool abortDrawing() = 0; }; - #endif diff --git a/gfx/skia/include/core/SkPixelRef.h b/gfx/skia/trunk/include/core/SkPixelRef.h similarity index 51% rename from gfx/skia/include/core/SkPixelRef.h rename to gfx/skia/trunk/include/core/SkPixelRef.h index 89ce69ae5bd1..8319ec6da5ac 100644 --- a/gfx/skia/include/core/SkPixelRef.h +++ b/gfx/skia/trunk/include/core/SkPixelRef.h @@ -1,4 +1,3 @@ - /* * Copyright 2008 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkPixelRef_DEFINED #define SkPixelRef_DEFINED @@ -14,6 +12,10 @@ #include "SkRefCnt.h" #include "SkString.h" #include "SkFlattenable.h" +#include "SkImageInfo.h" +#include "SkTDArray.h" + +//#define xed #ifdef SK_DEBUG /** @@ -34,8 +36,7 @@ class SkData; struct SkIRect; class SkMutex; -// this is an opaque class, not interpreted by skia -class SkGpuTexture; +class GrTexture; /** \class SkPixelRef @@ -49,16 +50,40 @@ class SK_API SkPixelRef : public SkFlattenable { public: SK_DECLARE_INST_COUNT(SkPixelRef) - explicit SkPixelRef(SkBaseMutex* mutex = NULL); + explicit SkPixelRef(const SkImageInfo&); + SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex); + virtual ~SkPixelRef(); + + const SkImageInfo& info() const { + return fInfo; + } /** Return the pixel memory returned from lockPixels, or null if the lockCount is 0. */ - void* pixels() const { return fPixels; } + void* pixels() const { return fRec.fPixels; } /** Return the current colorTable (if any) if pixels are locked, or null. */ - SkColorTable* colorTable() const { return fColorTable; } + SkColorTable* colorTable() const { return fRec.fColorTable; } + + size_t rowBytes() const { return fRec.fRowBytes; } + + /** + * To access the actual pixels of a pixelref, it must be "locked". + * Calling lockPixels returns a LockRec struct (on success). + */ + struct LockRec { + void* fPixels; + SkColorTable* fColorTable; + size_t fRowBytes; + + void zero() { sk_bzero(this, sizeof(*this)); } + + bool isZero() const { + return NULL == fPixels && NULL == fColorTable && 0 == fRowBytes; + } + }; /** * Returns true if the lockcount > 0 @@ -67,10 +92,19 @@ public: SkDEBUGCODE(int getLockCount() const { return fLockCount; }) - /** Call to access the pixel memory, which is returned. Balance with a call - to unlockPixels(). - */ - void lockPixels(); + /** + * Call to access the pixel memory. Return true on success. Balance this + * with a call to unlockPixels(). + */ + bool lockPixels(); + + /** + * Call to access the pixel memory. On success, return true and fill out + * the specified rec. On failure, return false and ignore the rec parameter. + * Balance this with a call to unlockPixels(). + */ + bool lockPixels(LockRec* rec); + /** Call to balanace a previous call to lockPixels(). Returns the pixels (or null) after the unlock. NOTE: lock calls can be nested, but the matching number of unlock calls must be made in order to free the @@ -92,12 +126,20 @@ public: */ uint32_t getGenerationID() const; - /** Call this if you have changed the contents of the pixels. This will in- - turn cause a different generation ID value to be returned from - getGenerationID(). - */ + /** + * Call this if you have changed the contents of the pixels. This will in- + * turn cause a different generation ID value to be returned from + * getGenerationID(). + */ void notifyPixelsChanged(); + /** + * Change the info's AlphaType. Note that this does not automatically + * invalidate the generation ID. If the pixel values themselves have + * changed, then you must explicitly call notifyPixelsChanged() as well. + */ + void changeAlphaType(SkAlphaType at); + /** Returns true if this pixelref is marked as immutable, meaning that the contents of its pixels will not change for the lifetime of the pixelref. */ @@ -142,9 +184,40 @@ public: return this->onRefEncodedData(); } + /** + * Experimental -- tells the caller if it is worth it to call decodeInto(). + * Just an optimization at this point, to avoid checking the cache first. + * We may remove/change this call in the future. + */ + bool implementsDecodeInto() { + return this->onImplementsDecodeInto(); + } + + /** + * Return a decoded instance of this pixelRef in bitmap. If this cannot be + * done, return false and the bitmap parameter is ignored/unchanged. + * + * pow2 is the requeste power-of-two downscale that the caller needs. This + * can be ignored, and the "original" size can be returned, but if the + * underlying codec can efficiently return a smaller size, that should be + * done. Some examples: + * + * To request the "base" version (original scale), pass 0 for pow2 + * To request 1/2 scale version (1/2 width, 1/2 height), pass 1 for pow2 + * To request 1/4 scale version (1/4 width, 1/4 height), pass 2 for pow2 + * ... + * + * If this returns true, then bitmap must be "locked" such that + * bitmap->getPixels() will return the correct address. + */ + bool decodeInto(int pow2, SkBitmap* bitmap) { + SkASSERT(pow2 >= 0); + return this->onDecodeInto(pow2, bitmap); + } + /** Are we really wrapping a texture instead of a bitmap? */ - virtual SkGpuTexture* getTexture() { return NULL; } + virtual GrTexture* getTexture() { return NULL; } bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL); @@ -177,20 +250,52 @@ public: virtual void globalUnref(); #endif + SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef) + + // Register a listener that may be called the next time our generation ID changes. + // + // We'll only call the listener if we're confident that we are the only SkPixelRef with this + // generation ID. If our generation ID changes and we decide not to call the listener, we'll + // never call it: you must add a new listener for each generation ID change. We also won't call + // the listener when we're certain no one knows what our generation ID is. + // + // This can be used to invalidate caches keyed by SkPixelRef generation ID. + struct GenIDChangeListener { + virtual ~GenIDChangeListener() {} + virtual void onChange() = 0; + }; + + // Takes ownership of listener. + void addGenIDChangeListener(GenIDChangeListener* listener); + protected: - /** Called when the lockCount goes from 0 to 1. The caller will have already - acquire a mutex for thread safety, so this method need not do that. - */ - virtual void* onLockPixels(SkColorTable**) = 0; - /** Called when the lock count goes from 1 to 0. The caller will have - already acquire a mutex for thread safety, so this method need not do - that. - */ + /** + * On success, returns true and fills out the LockRec for the pixels. On + * failure returns false and ignores the LockRec parameter. + * + * The caller will have already acquired a mutex for thread safety, so this + * method need not do that. + */ + virtual bool onNewLockPixels(LockRec*) = 0; + + /** + * Balancing the previous successful call to onNewLockPixels. The locked + * pixel address will no longer be referenced, so the subclass is free to + * move or discard that memory. + * + * The caller will have already acquired a mutex for thread safety, so this + * method need not do that. + */ virtual void onUnlockPixels() = 0; /** Default impl returns true */ virtual bool onLockPixelsAreWritable() const; + // returns false; + virtual bool onImplementsDecodeInto(); + // returns false; + virtual bool onDecodeInto(int pow2, SkBitmap* bitmap); + /** * For pixelrefs that don't have access to their raw pixels, they may be * able to make a copy of them (e.g. if the pixels are on the GPU). @@ -202,32 +307,44 @@ protected: // default impl returns NULL. virtual SkData* onRefEncodedData(); + /** + * Returns the size (in bytes) of the internally allocated memory. + * This should be implemented in all serializable SkPixelRef derived classes. + * SkBitmap::fPixelRefOffset + SkBitmap::getSafeSize() should never overflow this value, + * otherwise the rendering code may attempt to read memory out of bounds. + * + * @return default impl returns 0. + */ + virtual size_t getAllocatedSizeInBytes() const; + /** Return the mutex associated with this pixelref. This value is assigned in the constructor, and cannot change during the lifetime of the object. */ SkBaseMutex* mutex() const { return fMutex; } // serialization - SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkPixelRef(SkReadBuffer&, SkBaseMutex*); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // only call from constructor. Flags this to always be locked, removing // the need to grab the mutex and call onLockPixels/onUnlockPixels. // Performance tweak to avoid those calls (esp. in multi-thread use case). - void setPreLocked(void* pixels, SkColorTable* ctable); + void setPreLocked(void*, size_t rowBytes, SkColorTable*); private: - SkBaseMutex* fMutex; // must remain in scope for the life of this object - void* fPixels; - SkColorTable* fColorTable; // we do not track ownership, subclass does + + // mostly const. fInfo.fAlpahType can be changed at runtime. + const SkImageInfo fInfo; + + // LockRec is only valid if we're in a locked state (isLocked()) + LockRec fRec; int fLockCount; mutable uint32_t fGenerationID; + mutable bool fUniqueGenerationID; - // SkBitmap is only a friend so that when copying, it can modify the new SkPixelRef to have the - // same fGenerationID as the original. - friend class SkBitmap; + SkTDArray fGenIDChangeListeners; // pointers are owned SkString fURI; @@ -236,9 +353,28 @@ private: // only ever set in constructor, const after that bool fPreLocked; + void needsNewGenID(); + void callGenIDChangeListeners(); + void setMutex(SkBaseMutex* mutex); + // When copying a bitmap to another with the same shape and config, we can safely + // clone the pixelref generation ID too, which makes them equivalent under caching. + friend class SkBitmap; // only for cloneGenID + void cloneGenID(const SkPixelRef&); + typedef SkFlattenable INHERITED; }; +class SkPixelRefFactory : public SkRefCnt { +public: + /** + * Allocate a new pixelref matching the specified ImageInfo, allocating + * the memory for the pixels. If the ImageInfo requires a ColorTable, + * the pixelref will ref() the colortable. + * On failure return NULL. + */ + virtual SkPixelRef* create(const SkImageInfo&, SkColorTable*) = 0; +}; + #endif diff --git a/gfx/skia/include/core/SkPoint.h b/gfx/skia/trunk/include/core/SkPoint.h similarity index 93% rename from gfx/skia/include/core/SkPoint.h rename to gfx/skia/trunk/include/core/SkPoint.h index 5eca72f6b63d..5dd331a14ca9 100644 --- a/gfx/skia/include/core/SkPoint.h +++ b/gfx/skia/trunk/include/core/SkPoint.h @@ -216,13 +216,10 @@ struct SK_API SkPoint { * Return true if the computed length of the vector is >= the internal * tolerance (used to avoid dividing by tiny values). */ - static bool CanNormalize(SkScalar dx, SkScalar dy) -#ifdef SK_SCALAR_IS_FLOAT - // Simple enough (and performance critical sometimes) so we inline it. - { return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero); } -#else - ; -#endif + static bool CanNormalize(SkScalar dx, SkScalar dy) { + // Simple enough (and performance critical sometimes) so we inline it. + return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero); + } bool canNormalize() const { return CanNormalize(fX, fY); @@ -252,6 +249,14 @@ struct SK_API SkPoint { */ bool setLength(SkScalar x, SkScalar y, SkScalar length); + /** Same as setLength, but favoring speed over accuracy. + */ + bool setLengthFast(SkScalar length); + + /** Same as setLength, but favoring speed over accuracy. + */ + bool setLengthFast(SkScalar x, SkScalar y, SkScalar length); + /** Scale the point's coordinates by scale, writing the answer into dst. It is legal for dst == this. */ @@ -316,7 +321,6 @@ struct SK_API SkPoint { * Returns true if both X and Y are finite (not infinity or NaN) */ bool isFinite() const { -#ifdef SK_SCALAR_IS_FLOAT SkScalar accum = 0; accum *= fX; accum *= fY; @@ -327,12 +331,6 @@ struct SK_API SkPoint { // value==value will be true iff value is not NaN // TODO: is it faster to say !accum or accum==accum? return accum == accum; -#else - // use bit-or for speed, since we don't care about short-circuting the - // tests, and we expect the common case will be that we need to check all. - int isNaN = (SK_FixedNaN == fX) | (SK_FixedNaN == fX)); - return !isNaN; -#endif } /** @@ -353,7 +351,7 @@ struct SK_API SkPoint { /** Return true if this point and the given point are far enough apart such that a vector between them would be non-degenerate. - WARNING: Unlike the deprecated version of equalsWithinTolerance(), + WARNING: Unlike the explicit tolerance version, this method does not use componentwise comparison. Instead, it uses a comparison designed to match judgments elsewhere regarding degeneracy ("points A and B are so close that the vector between them @@ -363,10 +361,7 @@ struct SK_API SkPoint { return !CanNormalize(fX - p.fX, fY - p.fY); } - /** DEPRECATED: Return true if this and the given point are componentwise - within tolerance "tol". - - WARNING: There is no guarantee that the result will reflect judgments + /** WARNING: There is no guarantee that the result will reflect judgments elsewhere regarding degeneracy ("points A and B are so close that the vector between them is essentially zero"). */ @@ -416,13 +411,13 @@ struct SK_API SkPoint { /** Returns the dot product of a and b, treating them as 2D vectors */ static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) { - return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY); + return a.fX * b.fX + a.fY * b.fY; } /** Returns the cross product of a and b, treating them as 2D vectors */ static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) { - return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX); + return a.fX * b.fY - a.fY * b.fX; } SkScalar cross(const SkPoint& vec) const { @@ -440,7 +435,7 @@ struct SK_API SkPoint { SkScalar distanceToSqd(const SkPoint& pt) const { SkScalar dx = fX - pt.fX; SkScalar dy = fY - pt.fY; - return SkScalarMul(dx, dx) + SkScalarMul(dy, dy); + return dx * dx + dy * dy; } /** diff --git a/gfx/skia/trunk/include/core/SkPostConfig.h b/gfx/skia/trunk/include/core/SkPostConfig.h new file mode 100644 index 000000000000..dc76522ac15a --- /dev/null +++ b/gfx/skia/trunk/include/core/SkPostConfig.h @@ -0,0 +1,394 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPostConfig_DEFINED +#define SkPostConfig_DEFINED + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE) +# define SK_BUILD_FOR_WIN +#endif + +#if defined(SK_DEBUG) && defined(SK_RELEASE) +# error "cannot define both SK_DEBUG and SK_RELEASE" +#elif !defined(SK_DEBUG) && !defined(SK_RELEASE) +# error "must define either SK_DEBUG or SK_RELEASE" +#endif + +#if defined(SK_SUPPORT_UNITTEST) && !defined(SK_DEBUG) +# error "can't have unittests without debug" +#endif + +/** + * Matrix calculations may be float or double. + * The default is double, as that is faster given our impl uses doubles + * for intermediate calculations. + */ +#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT) +# error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT" +#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT) +# define SK_MSCALAR_IS_DOUBLE +#endif + +#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) +# error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN" +#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) +# error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN" +#endif + +/** + * Ensure the port has defined all of SK_X32_SHIFT, or none of them. + */ +#ifdef SK_A32_SHIFT +# if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT) +# error "all or none of the 32bit SHIFT amounts must be defined" +# endif +#else +# if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT) +# error "all or none of the 32bit SHIFT amounts must be defined" +# endif +#endif + +#if !defined(SK_HAS_COMPILER_FEATURE) +# if defined(__has_feature) +# define SK_HAS_COMPILER_FEATURE(x) __has_feature(x) +# else +# define SK_HAS_COMPILER_FEATURE(x) 0 +# endif +#endif + +#if !defined(SK_ATTRIBUTE) +# if defined(__clang__) || defined(__GNUC__) +# define SK_ATTRIBUTE(attr) __attribute__((attr)) +# else +# define SK_ATTRIBUTE(attr) +# endif +#endif + +#if !defined(SK_SUPPORT_GPU) +# define SK_SUPPORT_GPU 1 +#endif + +/** + * The clang static analyzer likes to know that when the program is not + * expected to continue (crash, assertion failure, etc). It will notice that + * some combination of parameters lead to a function call that does not return. + * It can then make appropriate assumptions about the parameters in code + * executed only if the non-returning function was *not* called. + */ +#if !defined(SkNO_RETURN_HINT) +# if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn) + static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn)); + static inline void SkNO_RETURN_HINT() {} +# else +# define SkNO_RETURN_HINT() do {} while (false) +# endif +#endif + +#if defined(SK_ZLIB_INCLUDE) && defined(SK_SYSTEM_ZLIB) +# error "cannot define both SK_ZLIB_INCLUDE and SK_SYSTEM_ZLIB" +#elif defined(SK_ZLIB_INCLUDE) || defined(SK_SYSTEM_ZLIB) +# define SK_HAS_ZLIB +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#ifndef SkNEW +# define SkNEW(type_name) (new type_name) +# define SkNEW_ARGS(type_name, args) (new type_name args) +# define SkNEW_ARRAY(type_name, count) (new type_name[(count)]) +# define SkNEW_PLACEMENT(buf, type_name) (new (buf) type_name) +# define SkNEW_PLACEMENT_ARGS(buf, type_name, args) (new (buf) type_name args) +# define SkDELETE(obj) (delete (obj)) +# define SkDELETE_ARRAY(array) (delete[] (array)) +#endif + +#ifndef SK_CRASH +# if 1 // set to 0 for infinite loop, which can help connecting gdb +# define SK_CRASH() do { SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0; } while (false) +# else +# define SK_CRASH() do { SkNO_RETURN_HINT(); } while (true) +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////// + +/** + * SK_ENABLE_INST_COUNT controlls printing how many reference counted objects + * are still held on exit. + * Defaults to 1 in DEBUG and 0 in RELEASE. + */ +#ifndef SK_ENABLE_INST_COUNT +# ifdef SK_DEBUG +// Only enabled for static builds, because instance counting relies on static +// variables in functions defined in header files. +# define SK_ENABLE_INST_COUNT !defined(SKIA_DLL) +# else +# define SK_ENABLE_INST_COUNT 0 +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_BUILD_FOR_WIN +# 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 +# +# ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED +# undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED +# undef WIN32_LEAN_AND_MEAN +# endif +# ifdef NOMINMAX_WAS_LOCALLY_DEFINED +# undef NOMINMAX_WAS_LOCALLY_DEFINED +# undef NOMINMAX +# endif +# +# ifndef SK_DEBUGBREAK +# define SK_DEBUGBREAK(p) do { if (!(p)) { SkNO_RETURN_HINT(); __debugbreak(); }} while (false) +# endif +# +# ifndef SK_A32_SHIFT +# define SK_A32_SHIFT 24 +# define SK_R32_SHIFT 16 +# define SK_G32_SHIFT 8 +# define SK_B32_SHIFT 0 +# endif +# +#else +# ifdef SK_DEBUG +# include +# ifndef SK_DEBUGBREAK +# define SK_DEBUGBREAK(cond) do { if (cond) break; \ + SkDebugf("%s:%d: failed assertion \"%s\"\n", \ + __FILE__, __LINE__, #cond); SK_CRASH(); } while (false) +# endif +# endif +#endif + +/** + * We check to see if the SHIFT value has already been defined. + * if not, we define it ourself to some default values. We default to OpenGL + * order (in memory: r,g,b,a) + */ +#ifndef SK_A32_SHIFT +# ifdef SK_CPU_BENDIAN +# define SK_R32_SHIFT 24 +# define SK_G32_SHIFT 16 +# define SK_B32_SHIFT 8 +# define SK_A32_SHIFT 0 +# else +# define SK_R32_SHIFT 0 +# define SK_G32_SHIFT 8 +# define SK_B32_SHIFT 16 +# define SK_A32_SHIFT 24 +# endif +#endif + +/** + * SkColor has well defined shift values, but SkPMColor is configurable. This + * macro is a convenience that returns true if the shift values are equal while + * ignoring the machine's endianness. + */ +#define SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER \ + (SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 0) + +/** + * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The + * relationship between the byte order and shift values depends on machine endianness. If the shift + * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little + * endian machine and the A channel on a big endian machine. Thus, given those shifts values, + * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and + * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine. + */ +#ifdef SK_CPU_BENDIAN +# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \ + (SK_ ## C3 ## 32_SHIFT == 0 && \ + SK_ ## C2 ## 32_SHIFT == 8 && \ + SK_ ## C1 ## 32_SHIFT == 16 && \ + SK_ ## C0 ## 32_SHIFT == 24) +#else +# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \ + (SK_ ## C0 ## 32_SHIFT == 0 && \ + SK_ ## C1 ## 32_SHIFT == 8 && \ + SK_ ## C2 ## 32_SHIFT == 16 && \ + SK_ ## C3 ## 32_SHIFT == 24) +#endif + +////////////////////////////////////////////////////////////////////// + +// TODO: rebaseline as needed so we can remove this flag entirely. +// - all platforms have int64_t now +// - we have slightly different fixed math results because of this check +// since we don't define this for linux/android +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) +# ifndef SkLONGLONG +# define SkLONGLONG int64_t +# endif +#endif + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef SK_BUILD_FOR_WINCE +# include +# include +#else +# define _CMNINTRIN_DECLARE_ONLY +# include "cmnintrin.h" +#endif + +#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32 +# ifdef free +# undef free +# endif +# include +# undef free +# +# ifdef SK_DEBUGx +# if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus) + void * operator new( + size_t cb, + int nBlockUse, + const char * szFileName, + int nLine, + int foo + ); + void * operator new[]( + size_t cb, + int nBlockUse, + const char * szFileName, + int nLine, + int foo + ); + void operator delete( + void *pUserData, + int, const char*, int, int + ); + void operator delete( + void *pUserData + ); + void operator delete[]( void * p ); +# define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__, 0) +# else +# define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) +# endif +# define new DEBUG_CLIENTBLOCK +# else +# define DEBUG_CLIENTBLOCK +# endif +#endif + +////////////////////////////////////////////////////////////////////// + +#ifndef SK_OVERRIDE +# if defined(_MSC_VER) +# define SK_OVERRIDE override +# elif defined(__clang__) + // Using __attribute__((override)) on clang does not appear to always work. + // Clang defaults to C++03 and warns about using override. Squelch that. Intentionally no + // push/pop here so all users of SK_OVERRIDE ignore the warning too. This is like passing + // -Wno-c++11-extensions, except that GCC won't die (because it won't see this pragma). +# pragma clang diagnostic ignored "-Wc++11-extensions" +# +# if __has_feature(cxx_override_control) +# define SK_OVERRIDE override +# elif defined(__has_extension) && __has_extension(cxx_override_control) +# define SK_OVERRIDE override +# endif +# endif +# ifndef SK_OVERRIDE +# define SK_OVERRIDE +# endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_UNUSED) +# define SK_UNUSED SK_ATTRIBUTE(unused) +#endif + +#if !defined(SK_ATTR_DEPRECATED) + // FIXME: we ignore msg for now... +# define SK_ATTR_DEPRECATED(msg) SK_ATTRIBUTE(deprecated) +#endif + +/** + * If your judgment is better than the compiler's (i.e. you've profiled it), + * you can use SK_ALWAYS_INLINE to force inlining. E.g. + * inline void someMethod() { ... } // may not be inlined + * SK_ALWAYS_INLINE void someMethod() { ... } // should always be inlined + */ +#if !defined(SK_ALWAYS_INLINE) +# if defined(SK_BUILD_FOR_WIN) +# define SK_ALWAYS_INLINE __forceinline +# else +# define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline +# endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if defined(__clang__) || defined(__GNUC__) +# define SK_PREFETCH(ptr) __builtin_prefetch(ptr) +# define SK_WRITE_PREFETCH(ptr) __builtin_prefetch(ptr, 1) +#else +# define SK_PREFETCH(ptr) +# define SK_WRITE_PREFETCH(ptr) +#endif + +////////////////////////////////////////////////////////////////////// + +#ifndef SK_PRINTF_LIKE +# if defined(__clang__) || defined(__GNUC__) +# define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B)))) +# else +# define SK_PRINTF_LIKE(A, B) +# endif +#endif + +////////////////////////////////////////////////////////////////////// + +#ifndef SK_SIZE_T_SPECIFIER +# if defined(_MSC_VER) +# define SK_SIZE_T_SPECIFIER "%Iu" +# else +# define SK_SIZE_T_SPECIFIER "%zu" +# endif +#endif + +////////////////////////////////////////////////////////////////////// + +#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS +# define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1 +#endif + +////////////////////////////////////////////////////////////////////// + +#ifndef SK_ATOMICS_PLATFORM_H +# if defined(SK_BUILD_FOR_WIN) +# define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_win.h" +# elif defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) +# define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_android.h" +# else +# define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_sync.h" +# endif +#endif + +#ifndef SK_MUTEX_PLATFORM_H +# if defined(SK_BUILD_FOR_WIN) +# define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_win.h" +# else +# define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_pthread.h" +# endif +#endif + +#endif // SkPostConfig_DEFINED diff --git a/gfx/skia/include/core/SkPreConfig.h b/gfx/skia/trunk/include/core/SkPreConfig.h similarity index 86% rename from gfx/skia/include/core/SkPreConfig.h rename to gfx/skia/trunk/include/core/SkPreConfig.h index 7e95b99f62d7..1c2e24fba657 100644 --- a/gfx/skia/include/core/SkPreConfig.h +++ b/gfx/skia/trunk/include/core/SkPreConfig.h @@ -14,6 +14,13 @@ #include "config.h" #endif +// Allows embedders that want to disable macros that take arguments to just +// define that symbol to be one of these +// +#define SK_NOTHING_ARG1(arg1) +#define SK_NOTHING_ARG2(arg1, arg2) +#define SK_NOTHING_ARG3(arg1, arg2, arg3) + ////////////////////////////////////////////////////////////////////// #if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_SDL) && !defined(SK_BUILD_FOR_BREW) && !defined(SK_BUILD_FOR_NACL) @@ -53,13 +60,6 @@ #define SK_BUILD_FOR_ANDROID #endif - -// USE_CHROMIUM_SKIA is defined when building Skia for the Chromium -// browser. -#if defined(USE_CHROMIUM_SKIA) - #define SK_BUILD_FOR_CHROMIUM -#endif - ////////////////////////////////////////////////////////////////////// #if !defined(SK_DEBUG) && !defined(SK_RELEASE) @@ -77,7 +77,6 @@ #if !defined(SK_WARN_UNUSED_RESULT) #define SK_WARN_UNUSED_RESULT #endif - #include "sk_stdint.h" #endif ////////////////////////////////////////////////////////////////////// @@ -92,12 +91,6 @@ ////////////////////////////////////////////////////////////////////// -#if !defined(SK_SCALAR_IS_FLOAT) && !defined(SK_SCALAR_IS_FIXED) - #define SK_SCALAR_IS_FLOAT -#endif - -////////////////////////////////////////////////////////////////////// - #if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN) #if defined (__ppc__) || defined(__PPC__) || defined(__ppc64__) \ || defined(__PPC64__) @@ -109,17 +102,6 @@ ////////////////////////////////////////////////////////////////////// -#ifndef SK_MMAP_SUPPORT - #ifdef SK_BUILD_FOR_WIN32 - // by default, if we're windows, we assume we don't have mmap - #define SK_MMAP_SUPPORT 0 - #else - #define SK_MMAP_SUPPORT 1 - #endif -#endif - -////////////////////////////////////////////////////////////////////// - /** * SK_CPU_SSE_LEVEL * @@ -145,10 +127,12 @@ // Are we in VisualStudio? #ifndef SK_CPU_SSE_LEVEL - #if _M_IX86_FP == 1 - #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1 - #elif _M_IX86_FP >= 2 - #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2 + #if defined (_M_IX86_FP) + #if _M_IX86_FP == 1 + #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1 + #elif _M_IX86_FP >= 2 + #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2 + #endif #endif #endif @@ -160,6 +144,12 @@ #endif #endif +// Android x86 NDK ABI requires SSE3 support +#if defined(SK_BUILD_FOR_ANDROID) + #undef SK_CPU_SSE_LEVEL + #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE3 +#endif + ////////////////////////////////////////////////////////////////////// // ARM defines @@ -196,16 +186,6 @@ ////////////////////////////////////////////////////////////////////// -/** - * THUMB is the only known config where we avoid small branches in - * favor of more complex math. - */ -#if !(defined(__arm__) && defined(__thumb__)) - #define SK_CPU_HAS_CONDITIONAL_INSTR -#endif - -////////////////////////////////////////////////////////////////////// - #if !defined(SKIA_IMPLEMENTATION) #define SKIA_IMPLEMENTATION 0 #endif diff --git a/gfx/skia/include/core/SkRRect.h b/gfx/skia/trunk/include/core/SkRRect.h similarity index 86% rename from gfx/skia/include/core/SkRRect.h rename to gfx/skia/trunk/include/core/SkRRect.h index fafe01924daf..66c433f43b8d 100644 --- a/gfx/skia/include/core/SkRRect.h +++ b/gfx/skia/trunk/include/core/SkRRect.h @@ -12,6 +12,7 @@ #include "SkPoint.h" class SkPath; +class SkMatrix; // Path forward: // core work @@ -25,7 +26,7 @@ class SkPath; // use growToInclude to fit skp round rects & generate stats (RRs vs. real paths) // check on # of rectorus's the RRs could handle // rendering work -// add entry points (clipRRect, drawRRect) - plumb down to SkDevice +// add entry points (clipRRect, drawRRect) - plumb down to SkBaseDevice // update SkPath.addRRect() to take an SkRRect - only use quads // -- alternatively add addRRectToPath here // add GM and bench @@ -198,30 +199,6 @@ public: b.fRadii[0].asScalars(), 8); } - /** - * Returns true if (p.fX,p.fY) is inside the RR, and the RR - * is not empty. - * - * Contains treats the left and top differently from the right and bottom. - * The left and top coordinates of the RR are themselves considered - * to be inside, while the right and bottom are not. All the points on the - * edges of the corners are considered to be inside. - */ - bool contains(const SkPoint& p) const { - return contains(p.fX, p.fY); - } - - /** - * Returns true if (x,y) is inside the RR, and the RR - * is not empty. - * - * Contains treats the left and top differently from the right and bottom. - * The left and top coordinates of the RR are themselves considered - * to be inside, while the right and bottom are not. All the points on the - * edges of the corners are considered to be inside. - */ - bool contains(SkScalar x, SkScalar y) const; - /** * Call inset on the bounds, and adjust the radii to reflect what happens * in stroking: If the corner is sharp (no curvature), leave it alone, @@ -251,6 +228,12 @@ public: this->inset(-dx, -dy, this); } + /** + * Returns true if 'rect' is wholy inside the RR, and both + * are not empty. + */ + bool contains(const SkRect& rect) const; + SkDEBUGCODE(void validate() const;) enum { @@ -262,14 +245,31 @@ public: * write kSizeInMemory bytes, and that value is guaranteed to always be * a multiple of 4. Return kSizeInMemory. */ - uint32_t writeToMemory(void* buffer) const; + size_t writeToMemory(void* buffer) const; /** - * Read the rrect from the specified buffer. This is guaranteed to always - * read kSizeInMemory bytes, and that value is guaranteed to always be - * a multiple of 4. Return kSizeInMemory. + * Reads the rrect from the specified buffer + * + * If the specified buffer is large enough, this will read kSizeInMemory bytes, + * and that value is guaranteed to always be a multiple of 4. + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); + + /** + * Transform by the specified matrix, and put the result in dst. + * + * @param matrix SkMatrix specifying the transform. Must only contain + * scale and/or translate, or this call will fail. + * @param dst SkRRect to store the result. It is an error to use this, + * which would make this function no longer const. + * @return true on success, false on failure. If false, dst is unmodified. + */ + bool transform(const SkMatrix& matrix, SkRRect* dst) const; private: SkRect fRect; @@ -280,6 +280,7 @@ private: // uninitialized data void computeType() const; + bool checkCornerContainment(SkScalar x, SkScalar y) const; // to access fRadii directly friend class SkPath; diff --git a/gfx/skia/include/core/SkRasterizer.h b/gfx/skia/trunk/include/core/SkRasterizer.h similarity index 90% rename from gfx/skia/include/core/SkRasterizer.h rename to gfx/skia/trunk/include/core/SkRasterizer.h index 3e662ab2c1b0..d916b231b7ac 100644 --- a/gfx/skia/include/core/SkRasterizer.h +++ b/gfx/skia/trunk/include/core/SkRasterizer.h @@ -30,8 +30,10 @@ public: const SkIRect* clipBounds, SkMaskFilter* filter, SkMask* mask, SkMask::CreateMode mode) const; + SK_DEFINE_FLATTENABLE_TYPE(SkRasterizer) + protected: - SkRasterizer(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkRasterizer(SkReadBuffer& buffer) : INHERITED(buffer) {} virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix, const SkIRect* clipBounds, diff --git a/gfx/skia/trunk/include/core/SkReadBuffer.h b/gfx/skia/trunk/include/core/SkReadBuffer.h new file mode 100644 index 000000000000..75cc64b2be19 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkReadBuffer.h @@ -0,0 +1,205 @@ + +/* + * 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 SkReadBuffer_DEFINED +#define SkReadBuffer_DEFINED + +#include "SkBitmapHeap.h" +#include "SkColorFilter.h" +#include "SkData.h" +#include "SkDrawLooper.h" +#include "SkImageFilter.h" +#include "SkMaskFilter.h" +#include "SkPath.h" +#include "SkPathEffect.h" +#include "SkPicture.h" +#include "SkPixelRef.h" +#include "SkRasterizer.h" +#include "SkReadBuffer.h" +#include "SkReader32.h" +#include "SkRefCnt.h" +#include "SkShader.h" +#include "SkUnitMapper.h" +#include "SkWriteBuffer.h" +#include "SkXfermode.h" + +class SkBitmap; + +#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_MAC) + #define DEBUG_NON_DETERMINISTIC_ASSERT +#endif + +class SkReadBuffer { +public: + SkReadBuffer(); + SkReadBuffer(const void* data, size_t size); + SkReadBuffer(SkStream* stream); + virtual ~SkReadBuffer(); + + enum Flags { + kCrossProcess_Flag = 1 << 0, + kScalarIsFloat_Flag = 1 << 1, + kPtrIs64Bit_Flag = 1 << 2, + kValidation_Flag = 1 << 3, + }; + + void setFlags(uint32_t flags) { fFlags = flags; } + uint32_t getFlags() const { return fFlags; } + + bool isCrossProcess() const { + return this->isValidating() || SkToBool(fFlags & kCrossProcess_Flag); + } + bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); } + bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); } + bool isValidating() const { return SkToBool(fFlags & kValidation_Flag); } + + 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(); + virtual SkColor readColor(); + virtual SkFixed readFixed(); + virtual int32_t readInt(); + virtual SkScalar readScalar(); + virtual uint32_t readUInt(); + virtual int32_t read32(); + + void* readFunctionPtr() { + void* ptr; + this->readByteArray(&ptr, sizeof(ptr)); + return ptr; + } + + // strings -- the caller is responsible for freeing the string contents + virtual void readString(SkString* string); + virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding); + + // common data structures + virtual void readPoint(SkPoint* point); + SkPoint readPoint() { SkPoint p; this->readPoint(&p); return p; } + virtual void readMatrix(SkMatrix* matrix); + virtual void readIRect(SkIRect* rect); + virtual void readRect(SkRect* rect); + virtual void readRegion(SkRegion* region); + virtual void readPath(SkPath* path); + void readPaint(SkPaint* paint) { paint->unflatten(*this); } + + virtual SkFlattenable* readFlattenable(SkFlattenable::Type); + template T* readFlattenable() { + return (T*) this->readFlattenable(T::GetFlattenableType()); + } + SkColorFilter* readColorFilter() { return this->readFlattenable(); } + SkDrawLooper* readDrawLooper() { return this->readFlattenable(); } + SkImageFilter* readImageFilter() { return this->readFlattenable(); } + SkMaskFilter* readMaskFilter() { return this->readFlattenable(); } + SkPathEffect* readPathEffect() { return this->readFlattenable(); } + SkPixelRef* readPixelRef() { return this->readFlattenable(); } + SkRasterizer* readRasterizer() { return this->readFlattenable(); } + SkShader* readShader() { return this->readFlattenable(); } + SkUnitMapper* readUnitMapper() { return this->readFlattenable(); } + SkXfermode* readXfermode() { return this->readFlattenable(); } + + + // binary data and arrays + virtual bool readByteArray(void* value, size_t size); + virtual bool readColorArray(SkColor* colors, size_t size); + virtual bool readIntArray(int32_t* values, size_t size); + virtual bool readPointArray(SkPoint* points, size_t size); + virtual bool readScalarArray(SkScalar* values, size_t size); + + SkData* readByteArrayAsData() { + size_t len = this->getArrayCount(); + if (!this->validateAvailable(len)) { + return SkData::NewEmpty(); + } + void* buffer = sk_malloc_throw(len); + this->readByteArray(buffer, len); + return SkData::NewFromMalloc(buffer, len); + } + + // helpers to get info about arrays and binary data + virtual uint32_t getArrayCount(); + + virtual void readBitmap(SkBitmap* bitmap); + virtual SkTypeface* readTypeface(); + + 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 + * SkWriteBuffer::setNamedFactoryRecorder. + */ + void setFactoryArray(SkTDArray* 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; + } + + // Default impelementations don't check anything. + virtual bool validate(bool isValid) { return true; } + virtual bool isValid() const { return true; } + virtual bool validateAvailable(size_t size) { return true; } + +private: + bool readArray(void* value, size_t size, size_t elementSize); + + uint32_t fFlags; + + SkReader32 fReader; + void* fMemoryPtr; + + SkBitmapHeapReader* fBitmapStorage; + SkTypeface** fTFArray; + int fTFCount; + + SkTDArray* 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 +}; + +#endif // SkReadBuffer_DEFINED diff --git a/gfx/skia/include/core/SkReader32.h b/gfx/skia/trunk/include/core/SkReader32.h similarity index 82% rename from gfx/skia/include/core/SkReader32.h rename to gfx/skia/trunk/include/core/SkReader32.h index 7a8d22a80c16..40ae12ce2363 100644 --- a/gfx/skia/include/core/SkReader32.h +++ b/gfx/skia/trunk/include/core/SkReader32.h @@ -106,27 +106,20 @@ public: int32_t readS32() { return this->readInt(); } uint32_t readU32() { return this->readInt(); } - void readPath(SkPath* path) { - size_t size = path->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readPath(SkPath* path) { + return readObjectFromMemory(path); } - void readMatrix(SkMatrix* matrix) { - size_t size = matrix->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readMatrix(SkMatrix* matrix) { + return readObjectFromMemory(matrix); } - SkRRect* readRRect(SkRRect* rrect) { - rrect->readFromMemory(this->skip(SkRRect::kSizeInMemory)); - return rrect; + bool readRRect(SkRRect* rrect) { + return readObjectFromMemory(rrect); } - void readRegion(SkRegion* rgn) { - size_t size = rgn->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readRegion(SkRegion* rgn) { + return readObjectFromMemory(rgn); } /** @@ -143,6 +136,15 @@ public: size_t readIntoString(SkString* copy); private: + template bool readObjectFromMemory(T* obj) { + size_t size = obj->readFromMemory(this->peek(), this->available()); + // If readFromMemory() fails (which means that available() was too small), it returns 0 + bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size); + // In case of failure, we want to skip to the end + (void)this->skip(success ? size : this->available()); + return success; + } + // these are always 4-byte aligned const char* fCurr; // current position within buffer const char* fStop; // end of buffer diff --git a/gfx/skia/include/core/SkRect.h b/gfx/skia/trunk/include/core/SkRect.h similarity index 93% rename from gfx/skia/include/core/SkRect.h rename to gfx/skia/trunk/include/core/SkRect.h index b2f515129d05..397e4a03eea3 100644 --- a/gfx/skia/include/core/SkRect.h +++ b/gfx/skia/trunk/include/core/SkRect.h @@ -26,6 +26,12 @@ struct SK_API SkIRect { return r; } + static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() { + SkIRect r; + r.setLargest(); + return r; + } + static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) { SkIRect r; r.set(0, 0, w, h); @@ -94,6 +100,11 @@ struct SK_API SkIRect { */ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + bool isLargest() const { return SK_MinS32 == fLeft && + SK_MinS32 == fTop && + SK_MaxS32 == fRight && + SK_MaxS32 == fBottom; } + friend bool operator==(const SkIRect& a, const SkIRect& b) { return !memcmp(&a, &b, sizeof(a)); } @@ -360,6 +371,12 @@ struct SK_API SkRect { return r; } + static SkRect SK_WARN_UNUSED_RESULT MakeLargest() { + SkRect r; + r.setLargest(); + return r; + } + static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) { SkRect r; r.set(0, 0, w, h); @@ -384,7 +401,7 @@ struct SK_API SkRect { return r; } - // DEPRECATED: call Make(r) + SK_ATTR_DEPRECATED("use Make()") static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) { SkRect r; r.set(SkIntToScalar(irect.fLeft), @@ -408,13 +425,17 @@ struct SK_API SkRect { */ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + bool isLargest() const { return SK_ScalarMin == fLeft && + SK_ScalarMin == fTop && + SK_ScalarMax == fRight && + SK_ScalarMax == fBottom; } + /** * Returns true iff all values in the rect are finite. If any are * infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this * returns false. */ bool isFinite() const { -#ifdef SK_SCALAR_IS_FLOAT float accum = 0; accum *= fLeft; accum *= fTop; @@ -427,13 +448,6 @@ struct SK_API SkRect { // value==value will be true iff value is not NaN // TODO: is it faster to say !accum or accum==accum? return accum == accum; -#else - // use bit-or for speed, since we don't care about short-circuting the - // tests, and we expect the common case will be that we need to check all. - int isNaN = (SK_FixedNaN == fLeft) | (SK_FixedNaN == fTop) | - (SK_FixedNaN == fRight) | (SK_FixedNaN == fBottom); - return !isNaN; -#endif } SkScalar x() const { return fLeft; } @@ -455,8 +469,9 @@ struct SK_API SkRect { return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4); } - /** return the 4 points that enclose the rectangle - */ + /** return the 4 points that enclose the rectangle (top-left, top-right, bottom-right, + bottom-left). TODO: Consider adding param to control whether quad is CW or CCW. + */ void toQuad(SkPoint quad[4]) const; /** Set this rectangle to the empty rectangle (0,0,0,0) @@ -610,6 +625,7 @@ struct SK_API SkRect { If either rectangle is empty, do nothing and return false. */ bool intersect(const SkRect& r); + bool intersect2(const SkRect& r); /** If this rectangle intersects the rectangle specified by left, top, right, bottom, return true and set this rectangle to that intersection, otherwise return false @@ -679,32 +695,19 @@ struct SK_API SkRect { fBottom = SkMaxScalar(y, fBottom); } - /** - * Returns true if (p.fX,p.fY) is inside the rectangle, and the rectangle - * is not empty. - * - * Contains treats the left and top differently from the right and bottom. - * The left and top coordinates of the rectangle are themselves considered - * to be inside, while the right and bottom are not. Thus for the rectangle - * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not. - */ - bool contains(const SkPoint& p) const { - return !this->isEmpty() && - fLeft <= p.fX && p.fX < fRight && fTop <= p.fY && p.fY < fBottom; + /** Bulk version of growToInclude */ + void growToInclude(const SkPoint pts[], int count) { + this->growToInclude(pts, sizeof(SkPoint), count); } - /** - * Returns true if (x,y) is inside the rectangle, and the rectangle - * is not empty. - * - * Contains treats the left and top differently from the right and bottom. - * The left and top coordinates of the rectangle are themselves considered - * to be inside, while the right and bottom are not. Thus for the rectangle - * {0, 0, 5, 10}, (0,0) is contained, but (0,10), (5,0) and (5,10) are not. - */ - bool contains(SkScalar x, SkScalar y) const { - return !this->isEmpty() && - fLeft <= x && x < fRight && fTop <= y && y < fBottom; + /** Bulk version of growToInclude with stride. */ + void growToInclude(const SkPoint pts[], size_t stride, int count) { + SkASSERT(count >= 0); + SkASSERT(stride >= sizeof(SkPoint)); + const SkPoint* end = (const SkPoint*)((intptr_t)pts + count * stride); + for (; pts < end; pts = (const SkPoint*)((intptr_t)pts + stride)) { + this->growToInclude(pts->fX, pts->fY); + } } /** @@ -712,6 +715,7 @@ struct SK_API SkRect { * not empty. */ bool contains(const SkRect& r) const { + // todo: can we eliminate the this->isEmpty check? return !r.isEmpty() && !this->isEmpty() && fLeft <= r.fLeft && fTop <= r.fTop && fRight >= r.fRight && fBottom >= r.fBottom; @@ -719,7 +723,7 @@ struct SK_API SkRect { /** * Set the dst rectangle by rounding this rectangle's coordinates to their - * nearest integer values using SkScalarRound. + * nearest integer values using SkScalarRoundToInt. */ void round(SkIRect* dst) const { SkASSERT(dst); @@ -761,6 +765,15 @@ struct SK_API SkRect { SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)); } + /** + * Return a new SkIRect which is contains the rounded coordinates of this + * rect using SkScalarRoundToInt. + */ + SkIRect round() const { + SkIRect ir; + this->round(&ir); + return ir; + } /** * Swap top/bottom or left/right if there are flipped (i.e. if width() diff --git a/gfx/skia/include/core/SkRefCnt.h b/gfx/skia/trunk/include/core/SkRefCnt.h similarity index 76% rename from gfx/skia/include/core/SkRefCnt.h rename to gfx/skia/trunk/include/core/SkRefCnt.h index 66fc9dba68d1..e4524beff7ae 100644 --- a/gfx/skia/include/core/SkRefCnt.h +++ b/gfx/skia/trunk/include/core/SkRefCnt.h @@ -10,13 +10,14 @@ #ifndef SkRefCnt_DEFINED #define SkRefCnt_DEFINED +#include "SkDynamicAnnotations.h" #include "SkThread.h" #include "SkInstCnt.h" #include "SkTemplates.h" -/** \class SkRefCnt +/** \class SkRefCntBase - SkRefCnt is the base class for objects that may be shared by multiple + SkRefCntBase is the base class for objects that may be shared by multiple objects. When an existing owner wants to share a reference, it calls ref(). When an owner wants to release its reference, it calls unref(). When the shared object's reference count goes to zero as the result of an unref() @@ -24,27 +25,41 @@ destructor to be called explicitly (or via the object going out of scope on the stack or calling delete) if getRefCnt() > 1. */ -class SK_API SkRefCnt : SkNoncopyable { +class SK_API SkRefCntBase : public SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(SkRefCnt) + SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase) /** Default construct, initializing the reference count to 1. */ - SkRefCnt() : fRefCnt(1) {} + SkRefCntBase() : fRefCnt(1) {} /** Destruct, asserting that the reference count is 1. */ - virtual ~SkRefCnt() { + virtual ~SkRefCntBase() { #ifdef SK_DEBUG SkASSERT(fRefCnt == 1); fRefCnt = 0; // illegal value, to catch us if we reuse after delete #endif } - /** Return the reference count. - */ + /** Return the reference count. Use only for debugging. */ int32_t getRefCnt() const { return fRefCnt; } + /** May return true if the caller is the only owner. + * Ensures that all previous owner's actions are complete. + */ + bool unique() const { + // We believe we're reading fRefCnt in a safe way here, so we stifle the TSAN warning about + // an unproctected read. Generally, don't read fRefCnt, and don't stifle this warning. + bool const unique = (1 == SK_ANNOTATE_UNPROTECTED_READ(fRefCnt)); + if (unique) { + // Acquire barrier (L/SL), if not provided by load of fRefCnt. + // Prevents user's 'unique' code from happening before decrements. + //TODO: issue the barrier. + } + return unique; + } + /** Increment the reference count. Must be balanced by a call to unref(). */ void ref() const { @@ -60,26 +75,18 @@ public: SkASSERT(fRefCnt > 0); // Release barrier (SL/S), if not provided below. if (sk_atomic_dec(&fRefCnt) == 1) { - // Aquire barrier (L/SL), if not provided above. + // Acquire barrier (L/SL), if not provided above. // Prevents code in dispose from happening before the decrement. - sk_membar_aquire__after_atomic_dec(); + sk_membar_acquire__after_atomic_dec(); internal_dispose(); } } +#ifdef SK_DEBUG void validate() const { SkASSERT(fRefCnt > 0); } - - /** - * Alias for ref(), for compatibility with scoped_refptr. - */ - void AddRef() { this->ref(); } - - /** - * Alias for unref(), for compatibility with scoped_refptr. - */ - void Release() { this->unref(); } +#endif protected: /** @@ -104,15 +111,24 @@ private: SkDELETE(this); } + // The following friends are those which override internal_dispose() + // and conditionally call SkRefCnt::internal_dispose(). + friend class GrTexture; friend class SkWeakRefCnt; - friend class GrTexture; // to allow GrTexture's internal_dispose to - // call SkRefCnt's & directly set fRefCnt (to 1) mutable int32_t fRefCnt; typedef SkNoncopyable INHERITED; }; +#ifdef SK_REF_CNT_MIXIN_INCLUDE +// It is the responsibility of the following include to define the type SkRefCnt. +// This SkRefCnt should normally derive from SkRefCntBase. +#include SK_REF_CNT_MIXIN_INCLUDE +#else +class SK_API SkRefCnt : public SkRefCntBase { }; +#endif + /////////////////////////////////////////////////////////////////////////////// /** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for @@ -152,6 +168,13 @@ template static inline void SkSafeUnref(T* obj) { } } +template static inline void SkSafeSetNull(T*& obj) { + if (NULL != obj) { + obj->unref(); + obj = NULL; + } +} + /////////////////////////////////////////////////////////////////////////////// /** @@ -189,12 +212,13 @@ public: } /** - * BlockRef is a type which inherits from B, cannot be created, - * and makes ref and unref private. + * BlockRef is a type which inherits from B, cannot be created, + * cannot be deleted, and makes ref and unref private. */ template class BlockRef : public B { private: BlockRef(); + ~BlockRef(); void ref() const; void unref() const; }; @@ -216,11 +240,13 @@ public: private: T* fObj; }; +// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( class SkAutoUnref : public SkAutoTUnref { public: SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref(obj) {} }; +#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) class SkAutoRef : SkNoncopyable { public: @@ -229,6 +255,7 @@ public: private: SkRefCnt* fObj; }; +#define SkAutoRef(...) SK_REQUIRE_LOCAL_VAR(SkAutoRef) /** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to a SkRefCnt (or subclass) object. diff --git a/gfx/skia/include/core/SkRegion.h b/gfx/skia/trunk/include/core/SkRegion.h similarity index 94% rename from gfx/skia/include/core/SkRegion.h rename to gfx/skia/trunk/include/core/SkRegion.h index ab8f220a355e..c9aa8daf880b 100644 --- a/gfx/skia/include/core/SkRegion.h +++ b/gfx/skia/trunk/include/core/SkRegion.h @@ -85,6 +85,16 @@ public: */ const SkIRect& getBounds() const { return fBounds; } + /** + * Returns a value that grows approximately linearly with the number of + * intervals comprised in the region. Empty region will return 0, Rect + * will return 1, Complex will return a value > 1. + * + * Use this to compare two regions, where the larger count likely + * indicates a more complex region. + */ + int computeRegionComplexity() const; + /** * Returns true if the region is non-empty, and if so, appends the * boundary(s) of the region to the specified path. @@ -351,13 +361,16 @@ public: * Write the region to the buffer, and return the number of bytes written. * If buffer is NULL, it still returns the number of bytes. */ - uint32_t writeToMemory(void* buffer) const; - + size_t writeToMemory(void* buffer) const; /** - * Initialized the region from the buffer, returning the number - * of bytes actually read. + * Initializes the region from the buffer + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); /** * Returns a reference to a global empty region. Just a convenience for diff --git a/gfx/skia/trunk/include/core/SkScalar.h b/gfx/skia/trunk/include/core/SkScalar.h new file mode 100644 index 000000000000..b9256badb4c0 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkScalar.h @@ -0,0 +1,234 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkScalar_DEFINED +#define SkScalar_DEFINED + +#include "SkFixed.h" +#include "SkFloatingPoint.h" + +//#define SK_SUPPORT_DEPRECATED_SCALARROUND + +typedef float SkScalar; + +/** SK_Scalar1 is defined to be 1.0 represented as an SkScalar +*/ +#define SK_Scalar1 (1.0f) +/** SK_Scalar1 is defined to be 1/2 represented as an SkScalar +*/ +#define SK_ScalarHalf (0.5f) +/** SK_ScalarInfinity is defined to be infinity as an SkScalar +*/ +#define SK_ScalarInfinity SK_FloatInfinity +/** SK_ScalarNegativeInfinity is defined to be negative infinity as an SkScalar +*/ +#define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity +/** SK_ScalarMax is defined to be the largest value representable as an SkScalar +*/ +#define SK_ScalarMax (3.402823466e+38f) +/** SK_ScalarMin is defined to be the smallest value representable as an SkScalar +*/ +#define SK_ScalarMin (-SK_ScalarMax) +/** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar +*/ +#define SK_ScalarNaN SK_FloatNaN +/** SkScalarIsNaN(n) returns true if argument is not a number +*/ +static inline bool SkScalarIsNaN(float x) { return x != x; } + +/** Returns true if x is not NaN and not infinite */ +static inline bool SkScalarIsFinite(float x) { + // We rely on the following behavior of infinities and nans + // 0 * finite --> 0 + // 0 * infinity --> NaN + // 0 * NaN --> NaN + float prod = x * 0; + // At this point, prod will either be NaN or 0 + // Therefore we can return (prod == prod) or (0 == prod). + return prod == prod; +} + +/** SkIntToScalar(n) returns its integer argument as an SkScalar +*/ +#define SkIntToScalar(n) ((float)(n)) +/** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar +*/ +#define SkFixedToScalar(x) SkFixedToFloat(x) +/** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed +*/ +#define SkScalarToFixed(x) SkFloatToFixed(x) + +#define SkScalarToFloat(n) (n) +#ifndef SK_SCALAR_TO_FLOAT_EXCLUDED +#define SkFloatToScalar(n) (n) +#endif + +#define SkScalarToDouble(n) (double)(n) +#define SkDoubleToScalar(n) (float)(n) + +/** SkScalarFraction(x) returns the signed fractional part of the argument +*/ +#define SkScalarFraction(x) sk_float_mod(x, 1.0f) + +#define SkScalarFloorToScalar(x) sk_float_floor(x) +#define SkScalarCeilToScalar(x) sk_float_ceil(x) +#define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f) + +#define SkScalarFloorToInt(x) sk_float_floor2int(x) +#define SkScalarCeilToInt(x) sk_float_ceil2int(x) +#define SkScalarRoundToInt(x) sk_float_round2int(x) +#define SkScalarTruncToInt(x) static_cast(x) + +/** Returns the absolute value of the specified SkScalar +*/ +#define SkScalarAbs(x) sk_float_abs(x) +/** Return x with the sign of y + */ +#define SkScalarCopySign(x, y) sk_float_copysign(x, y) +/** Returns the value pinned between 0 and max inclusive +*/ +inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) { + return x < 0 ? 0 : x > max ? max : x; +} +/** Returns the value pinned between min and max inclusive +*/ +inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) { + return x < min ? min : x > max ? max : x; +} +/** Returns the specified SkScalar squared (x*x) +*/ +inline SkScalar SkScalarSquare(SkScalar x) { return x * x; } +/** Returns the product of two SkScalars +*/ +#define SkScalarMul(a, b) ((float)(a) * (b)) +/** Returns the product of two SkScalars plus a third SkScalar +*/ +#define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c)) +/** Returns the quotient of two SkScalars (a/b) +*/ +#define SkScalarDiv(a, b) ((float)(a) / (b)) +/** Returns the mod of two SkScalars (a mod b) +*/ +#define SkScalarMod(x,y) sk_float_mod(x,y) +/** Returns the product of the first two arguments, divided by the third argument +*/ +#define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c)) +/** Returns the multiplicative inverse of the SkScalar (1/x) +*/ +#define SkScalarInvert(x) (SK_Scalar1 / (x)) +#define SkScalarFastInvert(x) (SK_Scalar1 / (x)) +/** Returns the square root of the SkScalar +*/ +#define SkScalarSqrt(x) sk_float_sqrt(x) +/** Returns b to the e +*/ +#define SkScalarPow(b, e) sk_float_pow(b, e) +/** Returns the average of two SkScalars (a+b)/2 +*/ +#define SkScalarAve(a, b) (((a) + (b)) * 0.5f) +/** Returns one half of the specified SkScalar +*/ +#define SkScalarHalf(a) ((a) * 0.5f) + +#define SK_ScalarSqrt2 1.41421356f +#define SK_ScalarPI 3.14159265f +#define SK_ScalarTanPIOver8 0.414213562f +#define SK_ScalarRoot2Over2 0.707106781f + +#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180)) +#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI)) +float SkScalarSinCos(SkScalar radians, SkScalar* cosValue); +#define SkScalarSin(radians) (float)sk_float_sin(radians) +#define SkScalarCos(radians) (float)sk_float_cos(radians) +#define SkScalarTan(radians) (float)sk_float_tan(radians) +#define SkScalarASin(val) (float)sk_float_asin(val) +#define SkScalarACos(val) (float)sk_float_acos(val) +#define SkScalarATan2(y, x) (float)sk_float_atan2(y,x) +#define SkScalarExp(x) (float)sk_float_exp(x) +#define SkScalarLog(x) (float)sk_float_log(x) + +inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; } +inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; } + +static inline bool SkScalarIsInt(SkScalar x) { + return x == (float)(int)x; +} + +// DEPRECATED : use ToInt or ToScalar variant +#ifdef SK_SUPPORT_DEPRECATED_SCALARROUND +# define SkScalarFloor(x) SkScalarFloorToInt(x) +# define SkScalarCeil(x) SkScalarCeilToInt(x) +# define SkScalarRound(x) SkScalarRoundToInt(x) +#endif + +/** + * Returns -1 || 0 || 1 depending on the sign of value: + * -1 if x < 0 + * 0 if x == 0 + * 1 if x > 0 + */ +static inline int SkScalarSignAsInt(SkScalar x) { + return x < 0 ? -1 : (x > 0); +} + +// Scalar result version of above +static inline SkScalar SkScalarSignAsScalar(SkScalar x) { + return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0); +} + +#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12)) + +static inline bool SkScalarNearlyZero(SkScalar x, + SkScalar tolerance = SK_ScalarNearlyZero) { + SkASSERT(tolerance >= 0); + return SkScalarAbs(x) <= tolerance; +} + +static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y, + SkScalar tolerance = SK_ScalarNearlyZero) { + SkASSERT(tolerance >= 0); + return SkScalarAbs(x-y) <= tolerance; +} + +/** Linearly interpolate between A and B, based on t. + If t is 0, return A + If t is 1, return B + else interpolate. + t must be [0..SK_Scalar1] +*/ +static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) { + SkASSERT(t >= 0 && t <= SK_Scalar1); + return A + (B - A) * t; +} + +/** Interpolate along the function described by (keys[length], values[length]) + for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length] + clamp to the min or max value. This function was inspired by a desire + to change the multiplier for thickness in fakeBold; therefore it assumes + the number of pairs (length) will be small, and a linear search is used. + Repeated keys are allowed for discontinuous functions (so long as keys is + monotonically increasing), and if key is the value of a repeated scalar in + keys, the first one will be used. However, that may change if a binary + search is used. +*/ +SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[], + const SkScalar values[], int length); + +/* + * Helper to compare an array of scalars. + */ +static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) { + SkASSERT(n >= 0); + for (int i = 0; i < n; ++i) { + if (a[i] != b[i]) { + return false; + } + } + return true; +} + +#endif diff --git a/gfx/skia/include/core/SkScalarCompare.h b/gfx/skia/trunk/include/core/SkScalarCompare.h similarity index 100% rename from gfx/skia/include/core/SkScalarCompare.h rename to gfx/skia/trunk/include/core/SkScalarCompare.h diff --git a/gfx/skia/include/core/SkShader.h b/gfx/skia/trunk/include/core/SkShader.h similarity index 95% rename from gfx/skia/include/core/SkShader.h rename to gfx/skia/trunk/include/core/SkShader.h index 126602def953..da23a20a4b5e 100644 --- a/gfx/skia/include/core/SkShader.h +++ b/gfx/skia/trunk/include/core/SkShader.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -312,14 +311,17 @@ public: SkPoint fPoint[2]; //!< Type specific, see above. SkScalar fRadius[2]; //!< Type specific, see above. TileMode fTileMode; //!< The tile mode used. + uint32_t fGradientFlags; //!< see SkGradientShader::Flags }; virtual GradientType asAGradient(GradientInfo* info) const; /** - * If the shader subclass has a GrEffect implementation, this installs an effect on the stage. - * The GrContext may be used by the effect to create textures. The GPU device does not call - * setContext. Instead we pass the paint here in case the shader needs paint info. + * If the shader subclass has a GrEffect implementation, this resturns the effect to install. + * The incoming color to the effect has r=g=b=a all extracted from the SkPaint's alpha. + * The output color should be the computed SkShader premul color modulated by the incoming + * color. The GrContext may be used by the effect to create textures. The GPU device does not + * call setContext. Instead we pass the SkPaint here in case the shader needs paint info. */ virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const; @@ -332,6 +334,9 @@ public: * exceed implementation limits (currently at 64K - 1)) then SkEmptyShader * may be returned. * + * If the src is kA8_Config then that mask will be colorized using the color on + * the paint. + * * @param src The bitmap to use inside the shader * @param tmx The tiling mode to use when sampling the bitmap in the x-direction. * @param tmy The tiling mode to use when sampling the bitmap in the y-direction. @@ -342,6 +347,8 @@ public: SkDEVCODE(virtual void toString(SkString* str) const;) + SK_DEFINE_FLATTENABLE_TYPE(SkShader) + protected: enum MatrixClass { kLinear_MatrixClass, // no perspective @@ -352,17 +359,15 @@ protected: // These can be called by your subclass after setContext() has been called uint8_t getPaintAlpha() const { return fPaintAlpha; } - SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; } const SkMatrix& getTotalInverse() const { return fTotalInverse; } MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } - SkShader(SkFlattenableReadBuffer& ); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkShader(SkReadBuffer& ); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkMatrix fLocalMatrix; SkMatrix fTotalInverse; uint8_t fPaintAlpha; - uint8_t fDeviceConfig; uint8_t fTotalInverseClass; SkDEBUGCODE(SkBool8 fInSetContext;) diff --git a/gfx/skia/include/core/SkSize.h b/gfx/skia/trunk/include/core/SkSize.h similarity index 91% rename from gfx/skia/include/core/SkSize.h rename to gfx/skia/trunk/include/core/SkSize.h index 01c6e35083d2..7bc8c7165d7b 100644 --- a/gfx/skia/include/core/SkSize.h +++ b/gfx/skia/trunk/include/core/SkSize.h @@ -90,19 +90,19 @@ struct SkSize : public SkTSize { SkISize toRound() const { SkISize s; - s.set(SkScalarRound(fWidth), SkScalarRound(fHeight)); + s.set(SkScalarRoundToInt(fWidth), SkScalarRoundToInt(fHeight)); return s; } SkISize toCeil() const { SkISize s; - s.set(SkScalarCeil(fWidth), SkScalarCeil(fHeight)); + s.set(SkScalarCeilToInt(fWidth), SkScalarCeilToInt(fHeight)); return s; } SkISize toFloor() const { SkISize s; - s.set(SkScalarFloor(fWidth), SkScalarFloor(fHeight)); + s.set(SkScalarFloorToInt(fWidth), SkScalarFloorToInt(fHeight)); return s; } }; diff --git a/gfx/skia/trunk/include/core/SkStream.h b/gfx/skia/trunk/include/core/SkStream.h new file mode 100644 index 000000000000..50ed691e5ae4 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkStream.h @@ -0,0 +1,453 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkStream_DEFINED +#define SkStream_DEFINED + +#include "SkRefCnt.h" +#include "SkScalar.h" + +class SkData; + +class SkStream; +class SkStreamRewindable; +class SkStreamSeekable; +class SkStreamAsset; +class SkStreamMemory; + +/** + * SkStream -- abstraction for a source of bytes. Subclasses can be backed by + * memory, or a file, or something else. + * + * NOTE: + * + * Classic "streams" APIs are sort of async, in that on a request for N + * bytes, they may return fewer than N bytes on a given call, in which case + * the caller can "try again" to get more bytes, eventually (modulo an error) + * receiving their total N bytes. + * + * Skia streams behave differently. They are effectively synchronous, and will + * always return all N bytes of the request if possible. If they return fewer + * (the read() call returns the number of bytes read) then that means there is + * no more data (at EOF or hit an error). The caller should *not* call again + * in hopes of fulfilling more of the request. + */ +class SK_API SkStream : public SkRefCnt { //TODO: remove SkRefCnt +public: + /** + * Attempts to open the specified file, and return a stream to it (using + * mmap if available). On success, the caller must call unref() on the + * returned object. On failure, returns NULL. + */ + static SkStreamAsset* NewFromFile(const char path[]); + + SK_DECLARE_INST_COUNT(SkStream) + + /** Reads or skips size number of bytes. + * If buffer == NULL, skip size bytes, return how many were skipped. + * If buffer != NULL, copy size bytes into buffer, return how many were copied. + * @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer + * @param size the number of bytes to skip or copy + * @return the number of bytes actually read. + */ + virtual size_t read(void* buffer, size_t size) = 0; + + /** Skip size number of bytes. + * @return the actual number bytes that could be skipped. + */ + size_t skip(size_t size) { + return this->read(NULL, size); + } + + /** Returns true when all the bytes in the stream have been read. + * This may return true early (when there are no more bytes to be read) + * or late (after the first unsuccessful read). + */ + virtual bool isAtEnd() const = 0; + + int8_t readS8(); + int16_t readS16(); + int32_t readS32(); + + uint8_t readU8() { return (uint8_t)this->readS8(); } + uint16_t readU16() { return (uint16_t)this->readS16(); } + uint32_t readU32() { return (uint32_t)this->readS32(); } + + bool readBool() { return this->readU8() != 0; } + SkScalar readScalar(); + size_t readPackedUInt(); + + /** + * Reconstitute an SkData object that was written to the stream + * using SkWStream::writeData(). + */ + SkData* readData(); + +//SkStreamRewindable + /** Rewinds to the beginning of the stream. Returns true if the stream is known + * to be at the beginning after this call returns. + */ + virtual bool rewind() { return false; } + + /** Duplicates this stream. If this cannot be done, returns NULL. + * The returned stream will be positioned at the beginning of its data. + */ + virtual SkStreamRewindable* duplicate() const { return NULL; } + +//SkStreamSeekable + /** Returns true if this stream can report it's current position. */ + virtual bool hasPosition() const { return false; } + /** Returns the current position in the stream. If this cannot be done, returns 0. */ + virtual size_t getPosition() const { return 0; } + + /** Seeks to an absolute position in the stream. If this cannot be done, returns false. + * If an attempt is made to seek past the end of the stream, the position will be set + * to the end of the stream. + */ + virtual bool seek(size_t position) { return false; } + + /** Seeks to an relative offset in the stream. If this cannot be done, returns false. + * If an attempt is made to move to a position outside the stream, the position will be set + * to the closest point within the stream (beginning or end). + */ + virtual bool move(long offset) { return false; } + + /** Duplicates this stream. If this cannot be done, returns NULL. + * The returned stream will be positioned the same as this stream. + */ + virtual SkStreamSeekable* fork() const { return NULL; } + +//SkStreamAsset + /** Returns true if this stream can report it's total length. */ + virtual bool hasLength() const { return false; } + /** Returns the total length of the stream. If this cannot be done, returns 0. */ + virtual size_t getLength() const { return 0; } + +//SkStreamMemory + /** Returns the starting address for the data. If this cannot be done, returns NULL. */ + //TODO: replace with virtual const SkData* getData() + virtual const void* getMemoryBase() { return NULL; } + +private: + typedef SkRefCnt INHERITED; +}; + +/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */ +class SK_API SkStreamRewindable : public SkStream { +public: + virtual bool rewind() SK_OVERRIDE = 0; + virtual SkStreamRewindable* duplicate() const SK_OVERRIDE = 0; +}; + +/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */ +class SK_API SkStreamSeekable : public SkStreamRewindable { +public: + virtual SkStreamSeekable* duplicate() const SK_OVERRIDE = 0; + + virtual bool hasPosition() const SK_OVERRIDE { return true; } + virtual size_t getPosition() const SK_OVERRIDE = 0; + virtual bool seek(size_t position) SK_OVERRIDE = 0; + virtual bool move(long offset) SK_OVERRIDE = 0; + virtual SkStreamSeekable* fork() const SK_OVERRIDE = 0; +}; + +/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */ +class SK_API SkStreamAsset : public SkStreamSeekable { +public: + virtual SkStreamAsset* duplicate() const SK_OVERRIDE = 0; + virtual SkStreamAsset* fork() const SK_OVERRIDE = 0; + + virtual bool hasLength() const SK_OVERRIDE { return true; } + virtual size_t getLength() const SK_OVERRIDE = 0; +}; + +/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */ +class SK_API SkStreamMemory : public SkStreamAsset { +public: + virtual SkStreamMemory* duplicate() const SK_OVERRIDE = 0; + virtual SkStreamMemory* fork() const SK_OVERRIDE = 0; + + virtual const void* getMemoryBase() SK_OVERRIDE = 0; +}; + +class SK_API SkWStream : SkNoncopyable { +public: + SK_DECLARE_INST_COUNT_ROOT(SkWStream) + + virtual ~SkWStream(); + + /** Called to write bytes to a SkWStream. Returns true on success + @param buffer the address of at least size bytes to be written to the stream + @param size The number of bytes in buffer to write to the stream + @return true on success + */ + virtual bool write(const void* buffer, size_t size) = 0; + virtual void newline(); + virtual void flush(); + + // helpers + + bool write8(U8CPU); + bool write16(U16CPU); + bool write32(uint32_t); + + bool writeText(const char text[]); + bool writeDecAsText(int32_t); + bool writeBigDecAsText(int64_t, int minDigits = 0); + bool writeHexAsText(uint32_t, int minDigits = 0); + bool writeScalarAsText(SkScalar); + + bool writeBool(bool v) { return this->write8(v); } + bool writeScalar(SkScalar); + bool writePackedUInt(size_t); + + bool writeStream(SkStream* input, size_t length); + + /** + * Append an SkData object to the stream, such that it can be read + * out of the stream using SkStream::readData(). + * + * Note that the encoding method used to write the SkData object + * to the stream may change over time. This method DOES NOT + * just write the raw content of the SkData object to the stream. + */ + bool writeData(const SkData*); +}; + +//////////////////////////////////////////////////////////////////////////////////////// + +#include "SkString.h" +#include + +struct SkFILE; + +/** A stream that wraps a C FILE* file stream. */ +class SK_API SkFILEStream : public SkStreamAsset { +public: + SK_DECLARE_INST_COUNT(SkFILEStream) + + /** Initialize the stream by calling sk_fopen on the specified path. + * This internal stream will be closed in the destructor. + */ + explicit SkFILEStream(const char path[] = NULL); + + enum Ownership { + kCallerPasses_Ownership, + kCallerRetains_Ownership + }; + /** Initialize the stream with an existing C file stream. + * While this stream exists, it assumes exclusive access to the C file stream. + * The C file stream will be closed in the destructor unless the caller specifies + * kCallerRetains_Ownership. + */ + explicit SkFILEStream(FILE* file, Ownership ownership = kCallerPasses_Ownership); + + virtual ~SkFILEStream(); + + /** Returns true if the current path could be opened. */ + bool isValid() const { return fFILE != NULL; } + + /** Close the current file, and open a new file with the specified path. + * If path is NULL, just close the current file. + */ + void setPath(const char path[]); + + virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; + virtual bool isAtEnd() const SK_OVERRIDE; + + virtual bool rewind() SK_OVERRIDE; + virtual SkStreamAsset* duplicate() const SK_OVERRIDE; + + virtual size_t getPosition() const SK_OVERRIDE; + virtual bool seek(size_t position) SK_OVERRIDE; + virtual bool move(long offset) SK_OVERRIDE; + virtual SkStreamAsset* fork() const SK_OVERRIDE; + + virtual size_t getLength() const SK_OVERRIDE; + + virtual const void* getMemoryBase() SK_OVERRIDE; + +private: + SkFILE* fFILE; + SkString fName; + Ownership fOwnership; + // fData is lazilly initialized when needed. + mutable SkAutoTUnref fData; + + typedef SkStreamAsset INHERITED; +}; + +class SK_API SkMemoryStream : public SkStreamMemory { +public: + SK_DECLARE_INST_COUNT(SkMemoryStream) + + SkMemoryStream(); + + /** We allocate (and free) the memory. Write to it via getMemoryBase() */ + SkMemoryStream(size_t length); + + /** If copyData is true, the stream makes a private copy of the data. */ + SkMemoryStream(const void* data, size_t length, bool copyData = false); + + /** Use the specified data as the memory for this stream. + * The stream will call ref() on the data (assuming it is not NULL). + */ + SkMemoryStream(SkData*); + + virtual ~SkMemoryStream(); + + /** Resets the stream to the specified data and length, + just like the constructor. + if copyData is true, the stream makes a private copy of the data + */ + virtual void setMemory(const void* data, size_t length, + bool copyData = false); + /** Replace any memory buffer with the specified buffer. The caller + must have allocated data with sk_malloc or sk_realloc, since it + will be freed with sk_free. + */ + void setMemoryOwned(const void* data, size_t length); + + /** Return the stream's data in a SkData. + * The caller must call unref() when it is finished using the data. + */ + SkData* copyToData() const; + + /** + * Use the specified data as the memory for this stream. + * The stream will call ref() on the data (assuming it is not NULL). + * The function returns the data parameter as a convenience. + */ + SkData* setData(SkData*); + + void skipToAlign4(); + const void* getAtPos(); + size_t peek() const { return fOffset; } + + virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; + virtual bool isAtEnd() const SK_OVERRIDE; + + virtual bool rewind() SK_OVERRIDE; + virtual SkMemoryStream* duplicate() const SK_OVERRIDE; + + virtual size_t getPosition() const SK_OVERRIDE; + virtual bool seek(size_t position) SK_OVERRIDE; + virtual bool move(long offset) SK_OVERRIDE; + virtual SkMemoryStream* fork() const SK_OVERRIDE; + + virtual size_t getLength() const SK_OVERRIDE; + + virtual const void* getMemoryBase() SK_OVERRIDE; + +private: + SkData* fData; + size_t fOffset; + + typedef SkStreamMemory INHERITED; +}; + +///////////////////////////////////////////////////////////////////////////////////////////// + +class SK_API SkFILEWStream : public SkWStream { +public: + SK_DECLARE_INST_COUNT(SkFILEWStream) + + SkFILEWStream(const char path[]); + virtual ~SkFILEWStream(); + + /** Returns true if the current path could be opened. + */ + bool isValid() const { return fFILE != NULL; } + + virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; + virtual void flush() SK_OVERRIDE; + +private: + SkFILE* fFILE; + + typedef SkWStream INHERITED; +}; + +class SkMemoryWStream : public SkWStream { +public: + SK_DECLARE_INST_COUNT(SkMemoryWStream) + + SkMemoryWStream(void* buffer, size_t size); + virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; + size_t bytesWritten() const { return fBytesWritten; } + +private: + char* fBuffer; + size_t fMaxLength; + size_t fBytesWritten; + + typedef SkWStream INHERITED; +}; + +class SK_API SkDynamicMemoryWStream : public SkWStream { +public: + SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream) + + SkDynamicMemoryWStream(); + virtual ~SkDynamicMemoryWStream(); + + virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; + // random access write + // modifies stream and returns true if offset + size is less than or equal to getOffset() + bool write(const void* buffer, size_t offset, size_t size); + bool read(void* buffer, size_t offset, size_t size); + size_t getOffset() const { return fBytesWritten; } + size_t bytesWritten() const { return fBytesWritten; } + + // copy what has been written to the stream into dst + void copyTo(void* dst) const; + + /** + * Return a copy of the data written so far. This call is responsible for + * calling unref() when they are finished with the data. + */ + SkData* copyToData() const; + + /** Reset, returning a reader stream with the current content. */ + SkStreamAsset* detachAsStream(); + + /** Reset the stream to its original, empty, state. */ + void reset(); + void padToAlign4(); +private: + struct Block; + Block* fHead; + Block* fTail; + size_t fBytesWritten; + mutable SkData* fCopy; // is invalidated if we write after it is created + + void invalidateCopy(); + + // For access to the Block type. + friend class SkBlockMemoryStream; + friend class SkBlockMemoryRefCnt; + + typedef SkWStream INHERITED; +}; + + +class SK_API SkDebugWStream : public SkWStream { +public: + SK_DECLARE_INST_COUNT(SkDebugWStream) + + // overrides + virtual bool write(const void* buffer, size_t size) SK_OVERRIDE; + virtual void newline() SK_OVERRIDE; + +private: + typedef SkWStream INHERITED; +}; + +// for now +typedef SkFILEStream SkURLStream; + +#endif diff --git a/gfx/skia/include/core/SkString.h b/gfx/skia/trunk/include/core/SkString.h similarity index 89% rename from gfx/skia/include/core/SkString.h rename to gfx/skia/trunk/include/core/SkString.h index 743f07889d07..bc06cb0aba63 100644 --- a/gfx/skia/include/core/SkString.h +++ b/gfx/skia/trunk/include/core/SkString.h @@ -11,6 +11,7 @@ #define SkString_DEFINED #include "SkScalar.h" +#include "SkTArray.h" #include @@ -59,9 +60,14 @@ static inline char *SkStrDup(const char string[]) { -#define SkStrAppendS32_MaxSize 11 +#define SkStrAppendU32_MaxSize 10 +char* SkStrAppendU32(char buffer[], uint32_t); +#define SkStrAppendU64_MaxSize 20 +char* SkStrAppendU64(char buffer[], uint64_t, int minDigits); + +#define SkStrAppendS32_MaxSize (SkStrAppendU32_MaxSize + 1) char* SkStrAppendS32(char buffer[], int32_t); -#define SkStrAppendS64_MaxSize 20 +#define SkStrAppendS64_MaxSize (SkStrAppendU64_MaxSize + 1) char* SkStrAppendS64(char buffer[], int64_t, int minDigits); /** @@ -80,11 +86,7 @@ char* SkStrAppendS64(char buffer[], int64_t, int minDigits); * Thus if the caller wants to add a 0 at the end, buffer must be at least * SkStrAppendScalar_MaxSize + 1 bytes large. */ -#ifdef SK_SCALAR_IS_FLOAT - #define SkStrAppendScalar SkStrAppendFloat -#else - #define SkStrAppendScalar SkStrAppendFixed -#endif +#define SkStrAppendScalar SkStrAppendFloat char* SkStrAppendFloat(char buffer[], float); char* SkStrAppendFixed(char buffer[], SkFixed); @@ -164,6 +166,8 @@ public: void insertUnichar(size_t offset, SkUnichar); void insertS32(size_t offset, int32_t value); void insertS64(size_t offset, int64_t value, int minDigits = 0); + void insertU32(size_t offset, uint32_t value); + void insertU64(size_t offset, uint64_t value, int minDigits = 0); void insertHex(size_t offset, uint32_t value, int minDigits = 0); void insertScalar(size_t offset, SkScalar); @@ -173,6 +177,8 @@ public: void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); } void appendS32(int32_t value) { this->insertS32((size_t)-1, value); } void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); } + void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); } + void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); } void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); } void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } @@ -187,7 +193,7 @@ public: void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3); void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3); - void appendf(const char format[], va_list); + void appendVAList(const char format[], va_list); void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3); void remove(size_t offset, size_t length); @@ -205,7 +211,7 @@ public: private: struct Rec { public: - size_t fLength; + uint32_t fLength; // logically size_t, but we want it to stay 32bits int32_t fRefCnt; char fBeginningOfData; @@ -226,24 +232,6 @@ private: static Rec* RefRec(Rec*); }; -class SkAutoUCS2 { -public: - SkAutoUCS2(const char utf8[]); - ~SkAutoUCS2(); - - /** This returns the number of ucs2 characters - */ - int count() const { return fCount; } - - /** This returns a null terminated ucs2 string - */ - const uint16_t* getUCS2() const { return fUCS2; } - -private: - int fCount; - uint16_t* fUCS2; -}; - /// Creates a new string and writes into it using a printf()-style format. SkString SkStringPrintf(const char* format, ...); @@ -253,4 +241,7 @@ template <> inline void SkTSwap(SkString& a, SkString& b) { a.swap(b); } +// Split str on any characters in delimiters into out. (Think, strtok with a sane API.) +void SkStrSplit(const char* str, const char* delimiters, SkTArray* out); + #endif diff --git a/gfx/skia/include/core/SkStringUtils.h b/gfx/skia/trunk/include/core/SkStringUtils.h similarity index 100% rename from gfx/skia/include/core/SkStringUtils.h rename to gfx/skia/trunk/include/core/SkStringUtils.h diff --git a/gfx/skia/include/core/SkStrokeRec.h b/gfx/skia/trunk/include/core/SkStrokeRec.h similarity index 88% rename from gfx/skia/include/core/SkStrokeRec.h rename to gfx/skia/trunk/include/core/SkStrokeRec.h index c5b47c25dd90..1e0ec880f7fa 100644 --- a/gfx/skia/include/core/SkStrokeRec.h +++ b/gfx/skia/trunk/include/core/SkStrokeRec.h @@ -81,6 +81,14 @@ public: */ bool applyToPath(SkPath* dst, const SkPath& src) const; + bool operator==(const SkStrokeRec& other) const { + return fWidth == other.fWidth && + fMiterLimit == other.fMiterLimit && + fCap == other.fCap && + fJoin == other.fJoin && + fStrokeAndFill == other.fStrokeAndFill; + } + private: SkScalar fWidth; SkScalar fMiterLimit; diff --git a/gfx/skia/include/core/SkSurface.h b/gfx/skia/trunk/include/core/SkSurface.h similarity index 73% rename from gfx/skia/include/core/SkSurface.h rename to gfx/skia/trunk/include/core/SkSurface.h index 70012994db03..2f277b755df7 100644 --- a/gfx/skia/include/core/SkSurface.h +++ b/gfx/skia/trunk/include/core/SkSurface.h @@ -24,7 +24,7 @@ class GrRenderTarget; * To draw into a canvas, first create the appropriate type of Surface, and * then request the canvas from the surface. */ -class SkSurface : public SkRefCnt { +class SK_API SkSurface : public SkRefCnt { public: SK_DECLARE_INST_COUNT(SkSurface) @@ -35,7 +35,7 @@ public: * If the requested surface cannot be created, or the request is not a * supported configuration, NULL will be returned. */ - static SkSurface* NewRasterDirect(const SkImage::Info&, void* pixels, size_t rowBytes); + static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes); /** * Return a new surface, with the memory for the pixels automatically @@ -44,7 +44,19 @@ public: * If the requested surface cannot be created, or the request is not a * supported configuration, NULL will be returned. */ - static SkSurface* NewRaster(const SkImage::Info&); + static SkSurface* NewRaster(const SkImageInfo&); + + /** + * Helper version of NewRaster. It creates a SkImageInfo with the + * specified width and height, and populates the rest of info to match + * pixels in SkPMColor format. + */ + static SkSurface* NewRasterPMColor(int width, int height) { + SkImageInfo info = { + width, height, kPMColor_SkColorType, kPremul_SkAlphaType + }; + return NewRaster(info); + } /** * Return a new surface whose contents will be recorded into a picture. @@ -56,13 +68,13 @@ public: /** * Return a new surface using the specified render target. */ - static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*); + static SkSurface* NewRenderTargetDirect(GrRenderTarget*); /** * Return a new surface whose contents will be drawn to an offscreen * render target, allocated by the surface. */ - static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&, int sampleCount = 0); + static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount = 0); int width() const { return fWidth; } int height() const { return fHeight; } @@ -79,10 +91,26 @@ public: uint32_t generationID(); /** - * Call this if the contents have changed. This will (lazily) force a new + * Modes that can be passed to notifyContentWillChange + */ + enum ContentChangeMode { + /** + * Use this mode if it is known that the upcoming content changes will + * clear or overwrite prior contents, thus making them discardable. + */ + kDiscard_ContentChangeMode, + /** + * Use this mode if prior surface contents need to be preserved or + * if in doubt. + */ + kRetain_ContentChangeMode, + }; + + /** + * Call this if the contents are about to change. This will (lazily) force a new * value to be returned from generationID() when it is called next. */ - void notifyContentChanged(); + void notifyContentWillChange(ContentChangeMode mode); /** * Return a canvas that will draw into this surface. This will always @@ -105,14 +133,14 @@ public: * ... // draw using canvasB * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! */ - SkSurface* newSurface(const SkImage::Info&); + SkSurface* newSurface(const SkImageInfo&); /** * Returns an image of the current state of the surface pixels up to this * point. Subsequent changes to the surface (by drawing into its canvas) * will not be reflected in this image. */ - SkImage* newImageShapshot(); + SkImage* newImageSnapshot(); /** * Thought the caller could get a snapshot image explicitly, and draw that, @@ -125,6 +153,7 @@ public: protected: SkSurface(int width, int height); + SkSurface(const SkImageInfo&); // called by subclass if their contents have changed void dirtyGenerationID() { diff --git a/gfx/skia/include/core/SkTArray.h b/gfx/skia/trunk/include/core/SkTArray.h similarity index 79% rename from gfx/skia/include/core/SkTArray.h rename to gfx/skia/trunk/include/core/SkTArray.h index bb5e57eada90..f7bdc5a15824 100644 --- a/gfx/skia/include/core/SkTArray.h +++ b/gfx/skia/trunk/include/core/SkTArray.h @@ -28,19 +28,21 @@ inline void copyAndDelete(SkTArray* self, char* newMemArray) { template inline void copy(SkTArray* self, const T* array) { for (int i = 0; i < self->fCount; ++i) { - new (self->fItemArray + i) T(array[i]); + SkNEW_PLACEMENT_ARGS(self->fItemArray + i, T, (array[i])); } } template inline void copyAndDelete(SkTArray* self, char* newMemArray) { for (int i = 0; i < self->fCount; ++i) { - new (newMemArray + sizeof(T) * i) T(self->fItemArray[i]); + SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i])); self->fItemArray[i].~T(); } } } +template void* operator new(size_t, SkTArray*, int); + /** When MEM_COPY is true T will be bit copied when moved. When MEM_COPY is false, T will be copy constructed / destructed. In all cases T's constructor will be called on allocation, @@ -91,7 +93,7 @@ public: fItemArray[i].~T(); } fCount = 0; - checkRealloc((int)array.count()); + this->checkRealloc((int)array.count()); fCount = array.count(); SkTArrayExt::copy(this, static_cast(array.fMemArray)); return *this; @@ -111,6 +113,23 @@ public: */ void reset() { this->pop_back_n(fCount); } + /** + * Resets to count() = n newly constructed T objects. + */ + void reset(int n) { + SkASSERT(n >= 0); + for (int i = 0; i < fCount; ++i) { + fItemArray[i].~T(); + } + // set fCount to 0 before calling checkRealloc so that no copy cons. are called. + fCount = 0; + this->checkRealloc(n); + fCount = n; + for (int i = 0; i < fCount; ++i) { + SkNEW_PLACEMENT(fItemArray + i, T); + } + } + /** * Resets to a copy of a C array. */ @@ -142,20 +161,18 @@ public: * elements. */ T& push_back() { - checkRealloc(1); - new ((char*)fMemArray+sizeof(T)*fCount) T; - ++fCount; - return fItemArray[fCount-1]; + T* newT = reinterpret_cast(this->push_back_raw(1)); + SkNEW_PLACEMENT(newT, T); + return *newT; } /** * Version of above that uses a copy constructor to initialize the new item */ T& push_back(const T& t) { - checkRealloc(1); - new ((char*)fMemArray+sizeof(T)*fCount) T(t); - ++fCount; - return fItemArray[fCount-1]; + T* newT = reinterpret_cast(this->push_back_raw(1)); + SkNEW_PLACEMENT_ARGS(newT, T, (t)); + return *newT; } /** @@ -165,12 +182,11 @@ public: */ T* push_back_n(int n) { SkASSERT(n >= 0); - checkRealloc(n); + T* newTs = reinterpret_cast(this->push_back_raw(n)); for (int i = 0; i < n; ++i) { - new (fItemArray + fCount + i) T; + SkNEW_PLACEMENT(newTs + i, T); } - fCount += n; - return fItemArray + fCount - n; + return newTs; } /** @@ -179,12 +195,11 @@ public: */ T* push_back_n(int n, const T& t) { SkASSERT(n >= 0); - checkRealloc(n); + T* newTs = reinterpret_cast(this->push_back_raw(n)); for (int i = 0; i < n; ++i) { - new (fItemArray + fCount + i) T(t); + SkNEW_PLACEMENT_ARGS(newTs[i], T, (t)); } - fCount += n; - return fItemArray + fCount - n; + return newTs; } /** @@ -193,9 +208,9 @@ public: */ T* push_back_n(int n, const T t[]) { SkASSERT(n >= 0); - checkRealloc(n); + this->checkRealloc(n); for (int i = 0; i < n; ++i) { - new (fItemArray + fCount + i) T(t[i]); + SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t[i])); } fCount += n; return fItemArray + fCount - n; @@ -208,7 +223,7 @@ public: SkASSERT(fCount > 0); --fCount; fItemArray[fCount].~T(); - checkRealloc(0); + this->checkRealloc(0); } /** @@ -219,9 +234,9 @@ public: SkASSERT(fCount >= n); fCount -= n; for (int i = 0; i < n; ++i) { - fItemArray[i].~T(); + fItemArray[fCount + i].~T(); } - checkRealloc(0); + this->checkRealloc(0); } /** @@ -232,9 +247,9 @@ public: SkASSERT(newCount >= 0); if (newCount > fCount) { - push_back_n(newCount - fCount); + this->push_back_n(newCount - fCount); } else if (newCount < fCount) { - pop_back_n(fCount - newCount); + this->pop_back_n(fCount - newCount); } } @@ -367,6 +382,15 @@ private: static const int gMIN_ALLOC_COUNT = 8; + // Helper function that makes space for n objects, adjusts the count, but does not initialize + // the new objects. + void* push_back_raw(int n) { + this->checkRealloc(n); + void* ptr = fItemArray + fCount; + fCount += n; + return ptr; + } + inline void checkRealloc(int delta) { SkASSERT(fCount >= 0); SkASSERT(fAllocCount >= 0); @@ -401,6 +425,8 @@ private: } } + friend void* operator new(size_t, SkTArray*, int); + template friend void SkTArrayExt::copy(SkTArray* that, const X*); template friend void SkTArrayExt::copyAndDelete(SkTArray* that, char*); @@ -417,6 +443,29 @@ private: }; }; +// Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directly +template +void* operator new(size_t, SkTArray* array, int atIndex) { + // Currently, we only support adding to the end of the array. When the array class itself + // supports random insertion then this should be updated. + // SkASSERT(atIndex >= 0 && atIndex <= array->count()); + SkASSERT(atIndex == array->count()); + return array->push_back_raw(1); +} + +// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete +// to match the op new silences warnings about missing op delete when a constructor throws an +// exception. +template +void operator delete(void*, SkTArray* array, int atIndex) { + SK_CRASH(); +} + +// Constructs a new object as the last element of an SkTArray. +#define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \ + (new ((array_ptr), (array_ptr)->count()) type_name args) + + /** * Subclass of SkTArray that contains a preallocated memory block for the array. */ @@ -437,6 +486,10 @@ public: : INHERITED(array, &fStorage) { } + explicit SkSTArray(int reserveCount) + : INHERITED(reserveCount) { + } + SkSTArray(const T* array, int count) : INHERITED(array, count, &fStorage) { } diff --git a/gfx/skia/include/core/SkTDArray.h b/gfx/skia/trunk/include/core/SkTDArray.h similarity index 70% rename from gfx/skia/include/core/SkTDArray.h rename to gfx/skia/trunk/include/core/SkTDArray.h index d733c47bf8ed..804b84f669df 100644 --- a/gfx/skia/include/core/SkTDArray.h +++ b/gfx/skia/trunk/include/core/SkTDArray.h @@ -21,7 +21,7 @@ public: fData = NULL; #endif } - SkTDArray(const T src[], size_t count) { + SkTDArray(const T src[], int count) { SkASSERT(src || count == 0); fReserve = fCount = 0; @@ -69,6 +69,9 @@ public: (a.fCount == 0 || !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T))); } + friend bool operator!=(const SkTDArray& a, const SkTDArray& b) { + return !(a == b); + } void swap(SkTDArray& other) { SkTSwap(fArray, other.fArray); @@ -95,7 +98,14 @@ public: /** * Return the number of elements in the array */ - int count() const { return (int)fCount; } + int count() const { return fCount; } + + /** + * Return the total number of elements allocated. + * reserved() - count() gives you the number of elements you can add + * without causing an allocation. + */ + int reserved() const { return fReserve; } /** * return the number of bytes in the array: count * sizeof(T) @@ -108,11 +118,11 @@ public: const T* end() const { return fArray ? fArray + fCount : NULL; } T& operator[](int index) { - SkASSERT((unsigned)index < fCount); + SkASSERT(index < fCount); return fArray[index]; } const T& operator[](int index) const { - SkASSERT((unsigned)index < fCount); + SkASSERT(index < fCount); return fArray[index]; } @@ -141,25 +151,43 @@ public: fCount = 0; } - void setCount(size_t count) { + /** + * Sets the number of elements in the array. + * If the array does not have space for count elements, it will increase + * the storage allocated to some amount greater than that required. + * It will never shrink the shrink the storage. + */ + void setCount(int count) { + // TODO(mtklein): eliminate this method, setCountExact -> setCount + SkASSERT(count >= 0); if (count > fReserve) { - this->growBy(count - fCount); - } else { - fCount = count; + this->resizeStorageToAtLeast(count); } + fCount = count; } - void setReserve(size_t reserve) { + /** + * Sets the number of elements in the array. + * If the array does not have space for count elements, it will increase + * the storage allocated to exactly the amount required, with no remaining + * reserved space. + * It will never shrink the shrink the storage. + */ + void setCountExact(int count) { + if (count > fReserve) { + this->resizeStorageToExact(count); + } + fCount = count; + } + + void setReserve(int reserve) { if (reserve > fReserve) { - SkASSERT(reserve > fCount); - size_t count = fCount; - this->growBy(reserve - fCount); - fCount = count; + this->resizeStorageToAtLeast(reserve); } } T* prepend() { - this->growBy(1); + this->adjustCount(1); memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T)); return fArray; } @@ -167,13 +195,13 @@ public: T* append() { return this->append(1, NULL); } - T* append(size_t count, const T* src = NULL) { - size_t oldCount = fCount; + T* append(int count, const T* src = NULL) { + int oldCount = fCount; if (count) { SkASSERT(src == NULL || fArray == NULL || src + count <= fArray || fArray + oldCount <= src); - this->growBy(count); + this->adjustCount(count); if (src) { memcpy(fArray + oldCount, src, sizeof(T) * count); } @@ -187,14 +215,14 @@ public: return result; } - T* insert(size_t index) { + T* insert(int index) { return this->insert(index, 1, NULL); } - T* insert(size_t index, size_t count, const T* src = NULL) { + T* insert(int index, int count, const T* src = NULL) { SkASSERT(count); SkASSERT(index <= fCount); size_t oldCount = fCount; - this->growBy(count); + this->adjustCount(count); T* dst = fArray + index; memmove(dst + count, dst, sizeof(T) * (oldCount - index)); if (src) { @@ -203,15 +231,15 @@ public: return dst; } - void remove(size_t index, size_t count = 1) { + void remove(int index, int count = 1) { SkASSERT(index + count <= fCount); fCount = fCount - count; memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index)); } - void removeShuffle(size_t index) { + void removeShuffle(int index) { SkASSERT(index < fCount); - size_t newCount = fCount - 1; + int newCount = fCount - 1; fCount = newCount; if (index != newCount) { memcpy(fArray + index, fArray + newCount, sizeof(T)); @@ -236,7 +264,7 @@ public: while (iter > stop) { if (*--iter == elem) { - return iter - stop; + return SkToInt(iter - stop); } } return -1; @@ -253,7 +281,7 @@ public: * Copies up to max elements into dst. The number of items copied is * capped by count - index. The actual number copied is returned. */ - int copyRange(T* dst, size_t index, int max) const { + int copyRange(T* dst, int index, int max) const { SkASSERT(max >= 0); SkASSERT(!max || dst); if (index >= fCount) { @@ -265,7 +293,7 @@ public: } void copy(T* dst) const { - this->copyRange(0, fCount, dst); + this->copyRange(dst, 0, fCount); } // routines to treat the array like a stack @@ -343,22 +371,46 @@ private: ArrayT* fData; #endif T* fArray; - size_t fReserve, fCount; + int fReserve; + int fCount; - void growBy(size_t extra) { - SkASSERT(extra); + /** + * Adjusts the number of elements in the array. + * This is the same as calling setCount(count() + delta). + */ + void adjustCount(int delta) { + this->setCount(fCount + delta); + } - if (fCount + extra > fReserve) { - size_t size = fCount + extra + 4; - size += size >> 2; - - fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); + /** + * This resizes the storage to *exactly* count elements, growing or + * shrinking the allocation as needed. It does not ASSERT anything about + * the previous allocation size, or about fCount. + * + * note: does NOT modify fCount + */ + void resizeStorageToExact(int count) { + SkASSERT(count >= 0); + fArray = (T*)sk_realloc_throw(fArray, count * sizeof(T)); #ifdef SK_DEBUG - fData = (ArrayT*)fArray; + fData = (ArrayT*)fArray; #endif - fReserve = size; - } - fCount += extra; + fReserve = count; + } + + /** + * Increase the storage allocation such that it can hold (fCount + extra) + * elements. + * It never shrinks the allocation, and it may increase the allocation by + * more than is strictly required, based on a private growth heuristic. + * + * note: does NOT modify fCount + */ + void resizeStorageToAtLeast(int count) { + SkASSERT(count > fReserve); + int space = count + 4; + space += space>>2; + this->resizeStorageToExact(space); } }; diff --git a/gfx/skia/include/core/SkTDStack.h b/gfx/skia/trunk/include/core/SkTDStack.h similarity index 100% rename from gfx/skia/include/core/SkTDStack.h rename to gfx/skia/trunk/include/core/SkTDStack.h diff --git a/gfx/skia/include/core/SkTDict.h b/gfx/skia/trunk/include/core/SkTDict.h similarity index 100% rename from gfx/skia/include/core/SkTDict.h rename to gfx/skia/trunk/include/core/SkTDict.h diff --git a/gfx/skia/include/core/SkTInternalLList.h b/gfx/skia/trunk/include/core/SkTInternalLList.h similarity index 99% rename from gfx/skia/include/core/SkTInternalLList.h rename to gfx/skia/trunk/include/core/SkTInternalLList.h index a6b6f1535307..0b67d4a76695 100644 --- a/gfx/skia/include/core/SkTInternalLList.h +++ b/gfx/skia/trunk/include/core/SkTInternalLList.h @@ -227,7 +227,7 @@ public: void validate() const { SkASSERT(!fHead == !fTail); Iter iter; - for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != (item = iter.next()); ) { + for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; item = iter.next()) { SkASSERT(this->isInList(item)); if (NULL == item->fPrev) { SkASSERT(fHead == item); diff --git a/gfx/skia/include/core/SkTLazy.h b/gfx/skia/trunk/include/core/SkTLazy.h similarity index 100% rename from gfx/skia/include/core/SkTLazy.h rename to gfx/skia/trunk/include/core/SkTLazy.h diff --git a/gfx/skia/include/core/SkTRegistry.h b/gfx/skia/trunk/include/core/SkTRegistry.h similarity index 78% rename from gfx/skia/include/core/SkTRegistry.h rename to gfx/skia/trunk/include/core/SkTRegistry.h index 34fcffd5c513..0994c990dccb 100644 --- a/gfx/skia/include/core/SkTRegistry.h +++ b/gfx/skia/trunk/include/core/SkTRegistry.h @@ -16,11 +16,11 @@ and provides a function-pointer. This can be used to auto-register a set of services, e.g. a set of image codecs. */ -template class SkTRegistry : SkNoncopyable { +template class SkTRegistry : SkNoncopyable { public: - typedef T (*Factory)(P); + typedef T Factory; - SkTRegistry(Factory fact) { + explicit SkTRegistry(T fact) : fFact(fact) { #ifdef SK_BUILD_FOR_ANDROID // work-around for double-initialization bug { @@ -33,15 +33,14 @@ public: } } #endif - fFact = fact; fChain = gHead; - gHead = this; + gHead = this; } static const SkTRegistry* Head() { return gHead; } const SkTRegistry* next() const { return fChain; } - Factory factory() const { return fFact; } + const Factory& factory() const { return fFact; } private: Factory fFact; @@ -51,6 +50,6 @@ private: }; // The caller still needs to declare an instance of this somewhere -template SkTRegistry* SkTRegistry::gHead; +template SkTRegistry* SkTRegistry::gHead; #endif diff --git a/gfx/skia/trunk/include/core/SkTSearch.h b/gfx/skia/trunk/include/core/SkTSearch.h new file mode 100644 index 000000000000..a4e4994ef378 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkTSearch.h @@ -0,0 +1,146 @@ + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkTSearch_DEFINED +#define SkTSearch_DEFINED + +#include "SkTypes.h" + +/** + * All of the SkTSearch variants want to return the index (0...N-1) of the + * found element, or the bit-not of where to insert the element. + * + * At a simple level, if the return value is negative, it was not found. + * + * For clients that want to insert the new element if it was not found, use + * the following logic: + * + * int index = SkTSearch(...); + * if (index >= 0) { + * // found at index + * } else { + * index = ~index; // now we are positive + * // insert at index + * } + */ + + +// The most general form of SkTSearch takes an array of T and a key of type K. A functor, less, is +// used to perform comparisons. It has two function operators: +// bool operator() (const T& t, const K& k) +// bool operator() (const K& t, const T& k) +template +int SkTSearch(const T base[], int count, const K& key, size_t elemSize, LESS& less) +{ + SkASSERT(count >= 0); + if (count <= 0) { + return ~0; + } + + SkASSERT(base != NULL); // base may be NULL if count is zero + + int lo = 0; + int hi = count - 1; + + while (lo < hi) { + int mid = (hi + lo) >> 1; + const T* elem = (const T*)((const char*)base + mid * elemSize); + + if (less(*elem, key)) + lo = mid + 1; + else + hi = mid; + } + + const T* elem = (const T*)((const char*)base + hi * elemSize); + if (less(*elem, key)) { + hi += 1; + hi = ~hi; + } else if (less(key, *elem)) { + hi = ~hi; + } + return hi; +} + +// Adapts a less-than function to a functor. +template struct SkTLessFunctionToFunctorAdaptor { + bool operator()(const T& a, const T& b) { return LESS(a, b); } +}; + +// Specialization for case when T==K and the caller wants to use a function rather than functor. +template +int SkTSearch(const T base[], int count, const T& target, size_t elemSize) { + static SkTLessFunctionToFunctorAdaptor functor; + return SkTSearch(base, count, target, elemSize, functor); +} + +// Adapts operator < to a functor. +template struct SkTLessFunctor { + bool operator()(const T& a, const T& b) { return a < b; } +}; + +// Specialization for T==K, compare using op <. +template +int SkTSearch(const T base[], int count, const T& target, size_t elemSize) { + static SkTLessFunctor functor; + return SkTSearch(base, count, target, elemSize, functor); +} + +// Similar to SkLessFunctionToFunctorAdaptor but makes the functor interface take T* rather than T. +template struct SkTLessFunctionToPtrFunctorAdaptor { + bool operator() (const T* t, const T* k) { return LESS(*t, *k); } +}; + +// Specialization for case where domain is an array of T* and the key value is a T*, and you want +// to compare the T objects, not the pointers. +template +int SkTSearch(T* base[], int count, T* target, size_t elemSize) { + static SkTLessFunctionToPtrFunctorAdaptor functor; + return SkTSearch(base, count, target, elemSize, functor); +} + +int SkStrSearch(const char*const* base, int count, const char target[], + size_t target_len, size_t elemSize); +int SkStrSearch(const char*const* base, int count, const char target[], + size_t elemSize); + +/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that + base points to a table of lower-case strings. +*/ +int SkStrLCSearch(const char*const* base, int count, const char target[], + size_t target_len, size_t elemSize); +int SkStrLCSearch(const char*const* base, int count, const char target[], + size_t elemSize); + +/** Helper class to convert a string to lower-case, but only modifying the ascii + characters. This makes the routine very fast and never changes the string + length, but it is not suitable for linguistic purposes. Normally this is + used for buiding and searching string tables. +*/ +class SkAutoAsciiToLC { +public: + SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1); + ~SkAutoAsciiToLC(); + + const char* lc() const { return fLC; } + size_t length() const { return fLength; } + +private: + char* fLC; // points to either the heap or fStorage + size_t fLength; + enum { + STORAGE = 64 + }; + char fStorage[STORAGE+1]; +}; + +// Helper when calling qsort with a compare proc that has typed its arguments +#define SkCastForQSort(compare) reinterpret_cast(compare) + +#endif diff --git a/gfx/skia/include/core/SkTemplates.h b/gfx/skia/trunk/include/core/SkTemplates.h similarity index 61% rename from gfx/skia/include/core/SkTemplates.h rename to gfx/skia/trunk/include/core/SkTemplates.h index c4ba0e676a12..a3a846600a9e 100644 --- a/gfx/skia/include/core/SkTemplates.h +++ b/gfx/skia/trunk/include/core/SkTemplates.h @@ -46,6 +46,24 @@ template struct SkTConstType { }; ///@} +/** + * Returns a pointer to a D which comes immediately after S[count]. + */ +template static D* SkTAfter(S* ptr, size_t count = 1) { + return reinterpret_cast(ptr + count); +} + +/** + * Returns a pointer to a D which comes byteOffset bytes after S. + */ +template static D* SkTAddOffset(S* ptr, size_t byteOffset) { + // The intermediate char* has the same const-ness as D as this produces better error messages. + // This relies on the fact that reinterpret_cast can add constness, but cannot remove it. + return reinterpret_cast( + reinterpret_cast::value>::type*>(ptr) + byteOffset + ); +} + /** \class SkAutoTCallVProc Call a function when this goes out of scope. The template uses two @@ -80,21 +98,37 @@ private: T* fObj; }; -// See also SkTScopedPtr. +/** \class SkAutoTDelete + An SkAutoTDelete is like a T*, except that the destructor of SkAutoTDelete + automatically deletes the pointer it holds (if any). That is, SkAutoTDelete + owns the T object that it points to. Like a T*, an SkAutoTDelete may hold + either NULL or a pointer to a T object. Also like T*, SkAutoTDelete is + thread-compatible, and once you dereference it, you get the threadsafety + guarantees of T. + + The size of a SkAutoTDelete is small: sizeof(SkAutoTDelete) == sizeof(T*) +*/ template class SkAutoTDelete : SkNoncopyable { public: - SkAutoTDelete(T* obj) : fObj(obj) {} - ~SkAutoTDelete() { delete fObj; } + SkAutoTDelete(T* obj = NULL) : fObj(obj) {} + ~SkAutoTDelete() { SkDELETE(fObj); } T* get() const { return fObj; } T& operator*() const { SkASSERT(fObj); return *fObj; } T* operator->() const { SkASSERT(fObj); return fObj; } + void reset(T* obj) { + if (fObj != obj) { + SkDELETE(fObj); + fObj = obj; + } + } + /** * Delete the owned object, setting the internal pointer to NULL. */ void free() { - delete fObj; + SkDELETE(fObj); fObj = NULL; } @@ -109,6 +143,28 @@ public: return obj; } + void swap(SkAutoTDelete* that) { + SkTSwap(fObj, that->fObj); + } + +private: + T* fObj; +}; + +// Calls ~T() in the destructor. +template class SkAutoTDestroy : SkNoncopyable { +public: + SkAutoTDestroy(T* obj = NULL) : fObj(obj) {} + ~SkAutoTDestroy() { + if (NULL != fObj) { + fObj->~T(); + } + } + + T* get() const { return fObj; } + T& operator*() const { SkASSERT(fObj); return *fObj; } + T* operator->() const { SkASSERT(fObj); return fObj; } + private: T* fObj; }; @@ -122,6 +178,13 @@ public: void free() { SkDELETE_ARRAY(fArray); fArray = NULL; } T* detach() { T* array = fArray; fArray = NULL; return array; } + void reset(T array[]) { + if (fArray != array) { + SkDELETE_ARRAY(fArray); + fArray = array; + } + } + private: T* fArray; }; @@ -140,7 +203,7 @@ public: SkASSERT(count >= 0); fArray = NULL; if (count) { - fArray = new T[count]; + fArray = SkNEW_ARRAY(T, count); } SkDEBUGCODE(fCount = count;) } @@ -148,17 +211,17 @@ public: /** Reallocates given a new count. Reallocation occurs even if new count equals old count. */ void reset(int count) { - delete[] fArray; + SkDELETE_ARRAY(fArray); SkASSERT(count >= 0); fArray = NULL; if (count) { - fArray = new T[count]; + fArray = SkNEW_ARRAY(T, count); } SkDEBUGCODE(fCount = count;) } ~SkAutoTArray() { - delete[] fArray; + SkDELETE_ARRAY(fArray); } /** Return the array of T elements. Will be NULL if count == 0 @@ -179,36 +242,62 @@ private: /** Wraps SkAutoTArray, with room for up to N elements preallocated */ -template class SkAutoSTArray : SkNoncopyable { +template class SkAutoSTArray : SkNoncopyable { public: + /** Initialize with no objects */ + SkAutoSTArray() { + fArray = NULL; + fCount = 0; + } + /** Allocate count number of T elements */ - SkAutoSTArray(size_t count) { - if (count > N) { - fArray = new T[count]; - } else if (count) { - fArray = new (fStorage) T[count]; - } else { - fArray = NULL; - } - fCount = count; + SkAutoSTArray(int count) { + fArray = NULL; + fCount = 0; + this->reset(count); } ~SkAutoSTArray() { - if (fCount > N) { - delete[] fArray; - } else { - T* start = fArray; - T* iter = start + fCount; - while (iter > start) { - (--iter)->~T(); + this->reset(0); + } + + /** Destroys previous objects in the array and default constructs count number of objects */ + void reset(int count) { + T* start = fArray; + T* iter = start + fCount; + while (iter > start) { + (--iter)->~T(); + } + + if (fCount != count) { + if (fCount > N) { + // 'fArray' was allocated last time so free it now + SkASSERT((T*) fStorage != fArray); + sk_free(fArray); } + + if (count > N) { + fArray = (T*) sk_malloc_throw(count * sizeof(T)); + } else if (count > 0) { + fArray = (T*) fStorage; + } else { + fArray = NULL; + } + + fCount = count; + } + + iter = fArray; + T* stop = fArray + count; + while (iter < stop) { + SkNEW_PLACEMENT(iter++, T); } } /** Return the number of T elements in the array */ - size_t count() const { return fCount; } + int count() const { return fCount; } /** Return the array of T elements. Will be NULL if count == 0 */ @@ -217,23 +306,29 @@ public: /** Return the nth element in the array */ T& operator[](int index) const { - SkASSERT((unsigned)index < fCount); + SkASSERT(index < fCount); return fArray[index]; } private: - size_t fCount; + int fCount; T* fArray; // since we come right after fArray, fStorage should be properly aligned char fStorage[N * sizeof(T)]; }; -/** Allocate a temp array on the stack/heap. - Does NOT call any constructors/destructors on T (i.e. T must be POD) -*/ +/** Manages an array of T elements, freeing the array in the destructor. + * Does NOT call any constructors/destructors on T (T must be POD). + */ template class SkAutoTMalloc : SkNoncopyable { public: - SkAutoTMalloc(size_t count) { + /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */ + explicit SkAutoTMalloc(T* ptr = NULL) { + fPtr = ptr; + } + + /** Allocates space for 'count' Ts. */ + explicit SkAutoTMalloc(size_t count) { fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); } @@ -241,10 +336,15 @@ public: sk_free(fPtr); } - // doesn't preserve contents - void reset (size_t count) { + /** Resize the memory area pointed to by the current ptr preserving contents. */ + void realloc(size_t count) { + fPtr = reinterpret_cast(sk_realloc_throw(fPtr, count * sizeof(T))); + } + + /** Resize the memory area pointed to by the current ptr without preserving contents. */ + void reset(size_t count) { sk_free(fPtr); - fPtr = fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); } T* get() const { return fPtr; } @@ -265,17 +365,34 @@ public: return fPtr[index]; } + /** + * Transfer ownership of the ptr to the caller, setting the internal + * pointer to NULL. Note that this differs from get(), which also returns + * the pointer, but it does not transfer ownership. + */ + T* detach() { + T* ptr = fPtr; + fPtr = NULL; + return ptr; + } + private: - T* fPtr; + T* fPtr; }; -template class SK_API SkAutoSTMalloc : SkNoncopyable { +template class SkAutoSTMalloc : SkNoncopyable { public: + SkAutoSTMalloc() { + fPtr = NULL; + } + SkAutoSTMalloc(size_t count) { - if (count <= N) { + if (count > N) { + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } else if (count) { fPtr = fTStorage; } else { - fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + fPtr = NULL; } } @@ -286,15 +403,18 @@ public: } // doesn't preserve contents - void reset(size_t count) { + T* reset(size_t count) { if (fPtr != fTStorage) { sk_free(fPtr); } - if (count <= N) { + if (count > N) { + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } else if (count) { fPtr = fTStorage; } else { - fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + fPtr = NULL; } + return fPtr; } T* get() const { return fPtr; } diff --git a/gfx/skia/trunk/include/core/SkThread.h b/gfx/skia/trunk/include/core/SkThread.h new file mode 100644 index 000000000000..7e2c90ed5192 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkThread.h @@ -0,0 +1,108 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkThread_DEFINED +#define SkThread_DEFINED + +#include "SkTypes.h" + +// SK_ATOMICS_PLATFORM_H must provide inline implementations for the following declarations. + +/** Atomically adds one to the int referenced by addr and returns the previous value. + * No additional memory barrier is required; this must act as a compiler barrier. + */ +static int32_t sk_atomic_inc(int32_t* addr); + +/** Atomically adds inc to the int referenced by addr and returns the previous value. + * No additional memory barrier is required; this must act as a compiler barrier. + */ +static int32_t sk_atomic_add(int32_t* addr, int32_t inc); + +/** Atomically subtracts one from the int referenced by addr and returns the previous value. + * This must act as a release (SL/S) memory barrier and as a compiler barrier. + */ +static int32_t sk_atomic_dec(int32_t* addr); + +/** Atomically adds one to the int referenced by addr iff the referenced int was not 0 + * and returns the previous value. + * No additional memory barrier is required; this must act as a compiler barrier. + */ +static int32_t sk_atomic_conditional_inc(int32_t* addr); + +/** Atomic compare and set. + * If *addr == before, set *addr to after and return true, otherwise return false. + * This must act as a release (SL/S) memory barrier and as a compiler barrier. + */ +static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after); + +/** If sk_atomic_dec does not act as an acquire (L/SL) barrier, + * this must act as an acquire (L/SL) memory barrier and as a compiler barrier. + */ +static void sk_membar_acquire__after_atomic_dec(); + +/** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier, + * this must act as an acquire (L/SL) memory barrier and as a compiler barrier. + */ +static void sk_membar_acquire__after_atomic_conditional_inc(); + +#include SK_ATOMICS_PLATFORM_H + +/** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations. + +class SkBaseMutex { +public: + void acquire(); + void release(); +}; + +class SkMutex : SkBaseMutex { +public: + SkMutex(); + ~SkMutex(); +}; + +#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = ... +#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = ... +*/ + +#include SK_MUTEX_PLATFORM_H + + +class SkAutoMutexAcquire : SkNoncopyable { +public: + explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) { + SkASSERT(fMutex != NULL); + mutex.acquire(); + } + + explicit SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) { + if (mutex) { + mutex->acquire(); + } + } + + /** If the mutex has not been released, release it now. */ + ~SkAutoMutexAcquire() { + if (fMutex) { + fMutex->release(); + } + } + + /** If the mutex has not been released, release it now. */ + void release() { + if (fMutex) { + fMutex->release(); + fMutex = NULL; + } + } + +private: + SkBaseMutex* fMutex; +}; +#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire) + +#endif diff --git a/gfx/skia/include/core/SkThread_platform.h b/gfx/skia/trunk/include/core/SkThread_platform.h similarity index 97% rename from gfx/skia/include/core/SkThread_platform.h rename to gfx/skia/trunk/include/core/SkThread_platform.h index faad40208602..7df778cb5e57 100644 --- a/gfx/skia/include/core/SkThread_platform.h +++ b/gfx/skia/trunk/include/core/SkThread_platform.h @@ -154,8 +154,6 @@ struct SkBaseMutex { // Special case used when the static mutex must be available globally. #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER } -#define SK_DECLARE_MUTEX_ARRAY(name, count) SkBaseMutex name[count] = { { PTHREAD_MUTEX_INITIALIZER } } - // A normal mutex that requires to be initialized through normal C++ construction, // i.e. when it's a member of another class, or allocated on the heap. class SK_API SkMutex : public SkBaseMutex, SkNoncopyable { @@ -189,7 +187,6 @@ typedef SkMutex SkBaseMutex; #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name -#define SK_DECLARE_MUTEX_ARRAY(name, count) SkBaseMutex name[count] #endif // !SK_USE_POSIX_THREADS diff --git a/gfx/skia/include/core/SkTileGridPicture.h b/gfx/skia/trunk/include/core/SkTileGridPicture.h similarity index 100% rename from gfx/skia/include/core/SkTileGridPicture.h rename to gfx/skia/trunk/include/core/SkTileGridPicture.h diff --git a/gfx/skia/include/core/SkTime.h b/gfx/skia/trunk/include/core/SkTime.h similarity index 96% rename from gfx/skia/include/core/SkTime.h rename to gfx/skia/trunk/include/core/SkTime.h index 7f3c27053eab..51616d41c741 100644 --- a/gfx/skia/include/core/SkTime.h +++ b/gfx/skia/trunk/include/core/SkTime.h @@ -60,5 +60,6 @@ private: SkMSec fNow; SkMSec fMinToDump; }; +#define SkAutoTime(...) SK_REQUIRE_LOCAL_VAR(SkAutoTime) #endif diff --git a/gfx/skia/include/core/SkTrace.h b/gfx/skia/trunk/include/core/SkTrace.h similarity index 100% rename from gfx/skia/include/core/SkTrace.h rename to gfx/skia/trunk/include/core/SkTrace.h diff --git a/gfx/skia/include/core/SkTypeface.h b/gfx/skia/trunk/include/core/SkTypeface.h similarity index 61% rename from gfx/skia/include/core/SkTypeface.h rename to gfx/skia/trunk/include/core/SkTypeface.h index c91fa428faa1..0be97eb4f7c3 100644 --- a/gfx/skia/include/core/SkTypeface.h +++ b/gfx/skia/trunk/include/core/SkTypeface.h @@ -22,6 +22,7 @@ class SkAdvancedTypefaceMetrics; class SkWStream; typedef uint32_t SkFontID; +/** Machine endian. */ typedef uint32_t SkFontTableTag; /** \class SkTypeface @@ -85,7 +86,7 @@ public: * Returns a ref() to the default typeface. The caller must call unref() * when they are done referencing the object. Never returns NULL. */ - static SkTypeface* RefDefault(); + static SkTypeface* RefDefault(Style style = SkTypeface::kNormal); /** Return a new reference to the typeface that most closely matches the requested familyName and style. Pass null as the familyName to return @@ -133,20 +134,35 @@ public: */ static SkTypeface* Deserialize(SkStream*); - /** Retrieve detailed typeface metrics. Used by the PDF backend. - @param perGlyphInfo Indicate what glyph specific information (advances, - names, etc.) should be populated. - @param glyphIDs For per-glyph info, specify subset of the font by - giving glyph ids. Each integer represents a glyph - id. Passing NULL means all glyphs in the font. - @param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if - glyphIDs is NULL. - @return The returned object has already been referenced. + enum Encoding { + kUTF8_Encoding, + kUTF16_Encoding, + kUTF32_Encoding + }; + + /** + * Given an array of character codes, of the specified encoding, + * optionally return their corresponding glyph IDs (if glyphs is not NULL). + * + * @param chars pointer to the array of character codes + * @param encoding how the characters are encoded + * @param glyphs (optional) returns the corresponding glyph IDs for each + * character code, up to glyphCount values. If a character code is + * not found in the typeface, the corresponding glyph ID will be 0. + * @param glyphCount number of code points in 'chars' to process. If glyphs + * is not NULL, then it must point sufficient memory to write + * glyphCount values into it. + * @return the number of number of continuous non-zero glyph IDs computed + * from the beginning of chars. This value is valid, even if the + * glyphs parameter is NULL. */ - SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics( - SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, - const uint32_t* glyphIDs = NULL, - uint32_t glyphIDsCount = 0) const; + int charsToGlyphs(const void* chars, Encoding encoding, uint16_t glyphs[], + int glyphCount) const; + + /** + * Return the number of glyphs in the typeface. + */ + int countGlyphs() const; // Table getters -- may fail if the underlying font format is not organized // as 4-byte tables. @@ -194,6 +210,53 @@ public: */ int getUnitsPerEm() const; + /** + * Given a run of glyphs, return the associated horizontal adjustments. + * Adjustments are in "design units", which are integers relative to the + * typeface's units per em (see getUnitsPerEm). + * + * Some typefaces are known to never support kerning. Calling this method + * with all zeros (e.g. getKerningPairAdustments(NULL, 0, NULL)) returns + * a boolean indicating if the typeface might support kerning. If it + * returns false, then it will always return false (no kerning) for all + * possible glyph runs. If it returns true, then it *may* return true for + * somne glyph runs. + * + * If count is non-zero, then the glyphs parameter must point to at least + * [count] valid glyph IDs, and the adjustments parameter must be + * sized to at least [count - 1] entries. If the method returns true, then + * [count-1] entries in the adjustments array will be set. If the method + * returns false, then no kerning should be applied, and the adjustments + * array will be in an undefined state (possibly some values may have been + * written, but none of them should be interpreted as valid values). + */ + bool getKerningPairAdjustments(const uint16_t glyphs[], int count, + int32_t adjustments[]) const; + + struct LocalizedString { + SkString fString; + SkString fLanguage; + }; + class LocalizedStrings : ::SkNoncopyable { + public: + virtual ~LocalizedStrings() { } + virtual bool next(LocalizedString* localizedString) = 0; + void unref() { SkDELETE(this); } + }; + /** + * Returns an iterator which will attempt to enumerate all of the + * family names specified by the font. + * It is the caller's responsibility to unref() the returned pointer. + */ + LocalizedStrings* createFamilyNameIterator() const; + + /** + * Return the family name for this typeface. It will always be returned + * encoded as UTF8, but the language of the name is whatever the host + * platform chooses. + */ + void getFamilyName(SkString* name) const; + /** * Return a stream for the contents of the font data, or NULL on failure. * If ttcIndex is not null, it is set to the TrueTypeCollection index @@ -201,7 +264,23 @@ public: * collection. */ SkStream* openStream(int* ttcIndex) const; - SkScalerContext* createScalerContext(const SkDescriptor*) const; + + /** + * Return a scalercontext for the given descriptor. If this fails, then + * if allowFailure is true, this returns NULL, else it returns a + * dummy scalercontext that will not crash, but will draw nothing. + */ + SkScalerContext* createScalerContext(const SkDescriptor*, + bool allowFailure = false) const; + + // PRIVATE / EXPERIMENTAL -- do not call + void filterRec(SkScalerContextRec* rec) const { + this->onFilterRec(rec); + } + // PRIVATE / EXPERIMENTAL -- do not call + void getFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { + this->onGetFontDescriptor(desc, isLocal); + } protected: /** uniqueID must be unique and non-zero @@ -213,7 +292,7 @@ protected: void setIsFixedPitch(bool isFixedPitch) { fIsFixedPitch = isFixedPitch; } friend class SkScalerContext; - static SkTypeface* GetDefaultTypeface(); + static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal); virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const = 0; virtual void onFilterRec(SkScalerContextRec*) const = 0; @@ -221,16 +300,47 @@ protected: SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, const uint32_t* glyphIDs, uint32_t glyphIDsCount) const = 0; + virtual SkStream* onOpenStream(int* ttcIndex) const = 0; virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0; - virtual int onGetUPEM() const; + virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], + int glyphCount) const = 0; + virtual int onCountGlyphs() const = 0; - virtual int onGetTableTags(SkFontTableTag tags[]) const; + virtual int onGetUPEM() const = 0; + virtual bool onGetKerningPairAdjustments(const uint16_t glyphs[], int count, + int32_t adjustments[]) const; + + virtual LocalizedStrings* onCreateFamilyNameIterator() const = 0; + + virtual int onGetTableTags(SkFontTableTag tags[]) const = 0; virtual size_t onGetTableData(SkFontTableTag, size_t offset, - size_t length, void* data) const; + size_t length, void* data) const = 0; private: + friend class SkGTypeface; + friend class SkPDFFont; + friend class SkPDFCIDFont; + + /** Retrieve detailed typeface metrics. Used by the PDF backend. + @param perGlyphInfo Indicate what glyph specific information (advances, + names, etc.) should be populated. + @param glyphIDs For per-glyph info, specify subset of the font by + giving glyph ids. Each integer represents a glyph + id. Passing NULL means all glyphs in the font. + @param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if + glyphIDs is NULL. + @return The returned object has already been referenced. + */ + SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics( + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, + const uint32_t* glyphIDs = NULL, + uint32_t glyphIDsCount = 0) const; + +private: + static void create_default_typeface(Style style); + SkFontID fUniqueID; Style fStyle; bool fIsFixedPitch; diff --git a/gfx/skia/include/core/SkTypes.h b/gfx/skia/trunk/include/core/SkTypes.h similarity index 82% rename from gfx/skia/include/core/SkTypes.h rename to gfx/skia/trunk/include/core/SkTypes.h index 9da836add3e8..969aac77b66e 100644 --- a/gfx/skia/include/core/SkTypes.h +++ b/gfx/skia/trunk/include/core/SkTypes.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,19 +5,13 @@ * found in the LICENSE file. */ - #ifndef SkTypes_DEFINED #define SkTypes_DEFINED #include "SkPreConfig.h" #include "SkUserConfig.h" #include "SkPostConfig.h" - -#ifndef SK_IGNORE_STDINT_DOT_H - #include -#endif - -#include +#include /** \file SkTypes.h */ @@ -49,7 +42,7 @@ enum { }; /** Return a block of memory (at least 4-byte aligned) of at least the specified size. If the requested memory cannot be returned, either - return null (if SK_MALLOC_TEMP bit is clear) or call sk_throw() + return null (if SK_MALLOC_TEMP bit is clear) or throw an exception (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free(). */ SK_API extern void* sk_malloc_flags(size_t size, unsigned flags); @@ -64,6 +57,14 @@ SK_API extern void* sk_realloc_throw(void* buffer, size_t size); */ SK_API extern void sk_free(void*); +/** Much like calloc: returns a pointer to at least size zero bytes, or NULL on failure. + */ +SK_API extern void* sk_calloc(size_t size); + +/** Same as sk_calloc, but throws an exception instead of returning NULL on failure. + */ +SK_API extern void* sk_calloc_throw(size_t size); + // bzero is safer than memset, but we can't rely on it, so... sk_bzero() static inline void sk_bzero(void* buffer, size_t size) { memset(buffer, 0, size); @@ -126,19 +127,8 @@ template struct SkCompileAssert { }; -/* - * The SK_COMPILE_ASSERT definition creates an otherwise-unused typedef. This - * triggers compiler warnings with some versions of gcc, so mark the typedef - * as permissibly-unused to disable the warnings. - */ -# if defined(__GNUC__) -# define SK_COMPILE_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) -# else -# define SK_COMPILE_ASSERT_UNUSED_ATTRIBUTE /* nothing */ -# endif - #define SK_COMPILE_ASSERT(expr, msg) \ - typedef SkCompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] SK_COMPILE_ASSERT_UNUSED_ATTRIBUTE + typedef SkCompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] SK_UNUSED /* * Usage: SK_MACRO_CONCAT(a, b) to construct the symbol ab @@ -157,6 +147,32 @@ struct SkCompileAssert { */ #define SK_MACRO_APPEND_LINE(name) SK_MACRO_CONCAT(name, __LINE__) +/** + * For some classes, it's almost always an error to instantiate one without a name, e.g. + * { + * SkAutoMutexAcquire(&mutex); + * + * } + * In this case, the writer meant to hold mutex while the rest of the code in the block runs, + * but instead the mutex is acquired and then immediately released. The correct usage is + * { + * SkAutoMutexAcquire lock(&mutex); + * + * } + * + * To prevent callers from instantiating your class without a name, use SK_REQUIRE_LOCAL_VAR + * like this: + * class classname { + * + * }; + * #define classname(...) SK_REQUIRE_LOCAL_VAR(classname) + * + * This won't work with templates, and you must inline the class' constructors and destructors. + * Take a look at SkAutoFree and SkAutoMalloc in this file for examples. + */ +#define SK_REQUIRE_LOCAL_VAR(classname) \ + SK_COMPILE_ASSERT(false, missing_name_for_##classname) + /////////////////////////////////////////////////////////////////////// /** @@ -195,12 +211,14 @@ typedef int SkBool; typedef uint8_t SkBool8; #ifdef SK_DEBUG - SK_API int8_t SkToS8(long); - SK_API uint8_t SkToU8(size_t); - SK_API int16_t SkToS16(long); - SK_API uint16_t SkToU16(size_t); - SK_API int32_t SkToS32(long); - SK_API uint32_t SkToU32(size_t); + SK_API int8_t SkToS8(intmax_t); + SK_API uint8_t SkToU8(uintmax_t); + SK_API int16_t SkToS16(intmax_t); + SK_API uint16_t SkToU16(uintmax_t); + SK_API int32_t SkToS32(intmax_t); + SK_API uint32_t SkToU32(uintmax_t); + SK_API int SkToInt(intmax_t); + SK_API unsigned SkToUInt(uintmax_t); #else #define SkToS8(x) ((int8_t)(x)) #define SkToU8(x) ((uint8_t)(x)) @@ -208,6 +226,8 @@ typedef uint8_t SkBool8; #define SkToU16(x) ((uint16_t)(x)) #define SkToS32(x) ((int32_t)(x)) #define SkToU32(x) ((uint32_t)(x)) + #define SkToInt(x) ((int)(x)) + #define SkToUInt(x) ((unsigned)(x)) #endif /** Returns 0 or 1 based on the condition @@ -296,14 +316,10 @@ template inline void SkTSwap(T& a, T& b) { } static inline int32_t SkAbs32(int32_t value) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (value < 0) + if (value < 0) { value = -value; + } return value; -#else - int32_t mask = value >> 31; - return (value ^ mask) - mask; -#endif } template inline T SkTAbs(T value) { @@ -325,37 +341,34 @@ static inline int32_t SkMin32(int32_t a, int32_t b) { return a; } +template const T& SkTMin(const T& a, const T& b) { + return (a < b) ? a : b; +} + +template const T& SkTMax(const T& a, const T& b) { + return (b < a) ? a : b; +} + static inline int32_t SkSign32(int32_t a) { return (a >> 31) | ((unsigned) -a >> 31); } static inline int32_t SkFastMin32(int32_t value, int32_t max) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (value > max) + if (value > max) { value = max; + } return value; -#else - int diff = max - value; - // clear diff if it is negative (clear if value > max) - diff &= (diff >> 31); - return value + diff; -#endif } /** Returns signed 32 bit value pinned between min and max, inclusively */ static inline int32_t SkPin32(int32_t value, int32_t min, int32_t max) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (value < min) + if (value < min) { value = min; - if (value > max) + } + if (value > max) { value = max; -#else - if (value < min) - value = min; - else if (value > max) - value = max; -#endif + } return value; } @@ -447,6 +460,7 @@ private: SkAutoFree(const SkAutoFree&); SkAutoFree& operator=(const SkAutoFree&); }; +#define SkAutoFree(...) SK_REQUIRE_LOCAL_VAR(SkAutoFree) /** * Manage an allocated block of heap memory. This object is the sole manager of @@ -487,14 +501,20 @@ public: /** * Reallocates the block to a new size. The ptr may or may not change. */ - void* reset(size_t size, OnShrink shrink = kAlloc_OnShrink) { + void* reset(size_t size, OnShrink shrink = kAlloc_OnShrink, bool* didChangeAlloc = NULL) { if (size == fSize || (kReuse_OnShrink == shrink && size < fSize)) { + if (NULL != didChangeAlloc) { + *didChangeAlloc = false; + } return fPtr; } sk_free(fPtr); fPtr = size ? sk_malloc_throw(size) : NULL; fSize = size; + if (NULL != didChangeAlloc) { + *didChangeAlloc = true; + } return fPtr; } @@ -527,6 +547,7 @@ private: void* fPtr; size_t fSize; // can be larger than the requested size (see kReuse) }; +#define SkAutoMalloc(...) SK_REQUIRE_LOCAL_VAR(SkAutoMalloc) /** * Manage an allocated block of memory. If the requested size is <= kSize, then @@ -543,7 +564,7 @@ public: */ SkAutoSMalloc() { fPtr = fStorage; - fSize = 0; + fSize = kSize; } /** @@ -553,7 +574,7 @@ public: */ explicit SkAutoSMalloc(size_t size) { fPtr = fStorage; - fSize = 0; + fSize = kSize; this->reset(size); } @@ -582,21 +603,29 @@ public: * heap. */ void* reset(size_t size, - SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink) { - if (size == fSize || (SkAutoMalloc::kReuse_OnShrink == shrink && - size < fSize)) { - return fPtr; + SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink, + bool* didChangeAlloc = NULL) { + size = (size < kSize) ? kSize : size; + bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink || size > fSize); + if (NULL != didChangeAlloc) { + *didChangeAlloc = alloc; } + if (alloc) { + if (fPtr != (void*)fStorage) { + sk_free(fPtr); + } - if (fPtr != (void*)fStorage) { - sk_free(fPtr); - } + if (size == kSize) { + SkASSERT(fPtr != fStorage); // otherwise we lied when setting didChangeAlloc. + fPtr = fStorage; + } else { + fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); + } - if (size <= kSize) { - fPtr = fStorage; - } else { - fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); + fSize = size; } + SkASSERT(fSize >= size && fSize >= kSize); + SkASSERT((fPtr == fStorage) || fSize > kSize); return fPtr; } @@ -605,6 +634,7 @@ private: size_t fSize; // can be larger than the requested size (see kReuse) uint32_t fStorage[(kSize + 3) >> 2]; }; +// Can't guard the constructor because it's a template class. #endif /* C++ */ diff --git a/gfx/skia/include/core/SkUnPreMultiply.h b/gfx/skia/trunk/include/core/SkUnPreMultiply.h similarity index 94% rename from gfx/skia/include/core/SkUnPreMultiply.h rename to gfx/skia/trunk/include/core/SkUnPreMultiply.h index 4fa5d579e95a..16181ce4e6fb 100644 --- a/gfx/skia/include/core/SkUnPreMultiply.h +++ b/gfx/skia/trunk/include/core/SkUnPreMultiply.h @@ -49,6 +49,8 @@ public: static SkColor PMColorToColor(SkPMColor c); + static uint32_t UnPreMultiplyPreservingByteOrder(SkPMColor c); + private: static const uint32_t gTable[256]; }; diff --git a/gfx/skia/include/core/SkUnitMapper.h b/gfx/skia/trunk/include/core/SkUnitMapper.h similarity index 85% rename from gfx/skia/include/core/SkUnitMapper.h rename to gfx/skia/trunk/include/core/SkUnitMapper.h index 754be2684135..46f6eddd709e 100644 --- a/gfx/skia/include/core/SkUnitMapper.h +++ b/gfx/skia/trunk/include/core/SkUnitMapper.h @@ -25,8 +25,10 @@ public: */ virtual uint16_t mapUnit16(uint16_t x) = 0; + SK_DEFINE_FLATTENABLE_TYPE(SkUnitMapper) + protected: - SkUnitMapper(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {} + SkUnitMapper(SkReadBuffer& rb) : SkFlattenable(rb) {} private: typedef SkFlattenable INHERITED; diff --git a/gfx/skia/include/core/SkUtils.h b/gfx/skia/trunk/include/core/SkUtils.h similarity index 95% rename from gfx/skia/include/core/SkUtils.h rename to gfx/skia/trunk/include/core/SkUtils.h index e29367dc226c..d6bf8dd3ee65 100644 --- a/gfx/skia/include/core/SkUtils.h +++ b/gfx/skia/trunk/include/core/SkUtils.h @@ -71,8 +71,7 @@ size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[] = NULL); #define SkUTF16_IsLowSurrogate(c) (((c) & 0xFC00) == 0xDC00) int SkUTF16_CountUnichars(const uint16_t utf16[]); -int SkUTF16_CountUnichars(const uint16_t utf16[], - int numberOf16BitValues); +int SkUTF16_CountUnichars(const uint16_t utf16[], int numberOf16BitValues); // returns the current unichar and then moves past it (*p++) SkUnichar SkUTF16_NextUnichar(const uint16_t**); // this guy backs up to the previus unichar value, and returns it (*--p) @@ -80,7 +79,7 @@ SkUnichar SkUTF16_PrevUnichar(const uint16_t**); size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = NULL); size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, - char utf8[] = NULL); + char utf8[] = NULL); inline bool SkUnichar_IsVariationSelector(SkUnichar uni) { /* The 'true' ranges are: @@ -113,5 +112,6 @@ public: private: const char* fLabel; }; +#define SkAutoTrace(...) SK_REQUIRE_LOCAL_VAR(SkAutoTrace) #endif diff --git a/gfx/skia/include/core/SkWeakRefCnt.h b/gfx/skia/trunk/include/core/SkWeakRefCnt.h similarity index 93% rename from gfx/skia/include/core/SkWeakRefCnt.h rename to gfx/skia/trunk/include/core/SkWeakRefCnt.h index e6871fe4d226..210dcc9f1c7b 100644 --- a/gfx/skia/include/core/SkWeakRefCnt.h +++ b/gfx/skia/trunk/include/core/SkWeakRefCnt.h @@ -23,7 +23,7 @@ getRefCnt() > 1. In addition to strong ownership, an owner may instead obtain a weak - reference by calling weak_ref(). A call to weak_ref() must be balanced my a + reference by calling weak_ref(). A call to weak_ref() must be balanced by a call to weak_unref(). To obtain a strong reference from a weak reference, call try_ref(). If try_ref() returns true, the owner's pointer is now also a strong reference on which unref() must be called. Note that this does not @@ -73,10 +73,12 @@ public: */ int32_t getWeakCnt() const { return fWeakCnt; } +#ifdef SK_DEBUG void validate() const { - SkRefCnt::validate(); + this->INHERITED::validate(); SkASSERT(fWeakCnt > 0); } +#endif /** Creates a strong reference from a weak reference, if possible. The caller must already be an owner. If try_ref() returns true the owner @@ -87,9 +89,9 @@ public: */ bool SK_WARN_UNUSED_RESULT try_ref() const { if (sk_atomic_conditional_inc(&fRefCnt) != 0) { - // Aquire barrier (L/SL), if not provided above. + // Acquire barrier (L/SL), if not provided above. // Prevents subsequent code from happening before the increment. - sk_membar_aquire__after_atomic_conditional_inc(); + sk_membar_acquire__after_atomic_conditional_inc(); return true; } return false; @@ -113,14 +115,14 @@ public: SkASSERT(fWeakCnt > 0); // Release barrier (SL/S), if not provided below. if (sk_atomic_dec(&fWeakCnt) == 1) { - // Aquire barrier (L/SL), if not provided above. + // Acquire barrier (L/SL), if not provided above. // Prevents code in destructor from happening before the decrement. - sk_membar_aquire__after_atomic_dec(); + sk_membar_acquire__after_atomic_dec(); #ifdef SK_DEBUG // so our destructor won't complain fWeakCnt = 1; #endif - SkRefCnt::internal_dispose(); + this->INHERITED::internal_dispose(); } } diff --git a/gfx/skia/trunk/include/core/SkWriteBuffer.h b/gfx/skia/trunk/include/core/SkWriteBuffer.h new file mode 100644 index 000000000000..332dfaea40e5 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkWriteBuffer.h @@ -0,0 +1,120 @@ + +/* + * 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 SkWriteBuffer_DEFINED +#define SkWriteBuffer_DEFINED + +#include "SkBitmapHeap.h" +#include "SkData.h" +#include "SkPath.h" +#include "SkPicture.h" +#include "SkRefCnt.h" +#include "SkWriter32.h" + +class SkBitmap; +class SkFactorySet; +class SkFlattenable; +class SkNamedFactorySet; +class SkRefCntSet; + +class SkWriteBuffer { +public: + enum Flags { + kCrossProcess_Flag = 1 << 0, + kValidation_Flag = 1 << 1, + }; + + SkWriteBuffer(uint32_t flags = 0); + SkWriteBuffer(void* initialStorage, size_t storageSize, uint32_t flags = 0); + ~SkWriteBuffer(); + + bool isCrossProcess() const { + return this->isValidating() || SkToBool(fFlags & kCrossProcess_Flag); + } + + SkWriter32* getWriter32() { return &fWriter; } + void reset(void* storage = NULL, size_t storageSize = 0) { + fWriter.reset(storage, storageSize); + } + + uint32_t* reserve(size_t size) { return fWriter.reserve(size); } + + size_t bytesWritten() const { return fWriter.bytesWritten(); } + + void writeByteArray(const void* data, size_t size); + void writeDataAsByteArray(SkData* data) { this->writeByteArray(data->data(), data->size()); } + void writeBool(bool value); + void writeFixed(SkFixed value); + void writeScalar(SkScalar value); + void writeScalarArray(const SkScalar* value, uint32_t count); + void writeInt(int32_t value); + void writeIntArray(const int32_t* value, uint32_t count); + void writeUInt(uint32_t value); + void write32(int32_t value); + void writeString(const char* value); + void writeEncodedString(const void* value, size_t byteLength, SkPaint::TextEncoding encoding); + void writeFunctionPtr(void* ptr) { this->writeByteArray(&ptr, sizeof(ptr)); } + + void writeFlattenable(const SkFlattenable* flattenable); + void writeColor(const SkColor& color); + void writeColorArray(const SkColor* color, uint32_t count); + void writePoint(const SkPoint& point); + void writePointArray(const SkPoint* point, uint32_t count); + void writeMatrix(const SkMatrix& matrix); + void writeIRect(const SkIRect& rect); + void writeRect(const SkRect& rect); + void writeRegion(const SkRegion& region); + void writePath(const SkPath& path); + size_t writeStream(SkStream* stream, size_t length); + void writeBitmap(const SkBitmap& bitmap); + void writeTypeface(SkTypeface* typeface); + void writePaint(const SkPaint& paint) { paint.flatten(*this); } + + bool writeToStream(SkWStream*); + void writeToMemory(void* dst) { fWriter.flatten(dst); } + + 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: + bool isValidating() const { return SkToBool(fFlags & kValidation_Flag); } + + const uint32_t fFlags; + SkFactorySet* fFactorySet; + SkNamedFactorySet* fNamedFactorySet; + SkWriter32 fWriter; + + SkBitmapHeap* fBitmapHeap; + SkRefCntSet* fTFSet; + + SkPicture::EncodeBitmap fBitmapEncoder; +}; + +#endif // SkWriteBuffer_DEFINED diff --git a/gfx/skia/trunk/include/core/SkWriter32.h b/gfx/skia/trunk/include/core/SkWriter32.h new file mode 100644 index 000000000000..586fe9fb08e5 --- /dev/null +++ b/gfx/skia/trunk/include/core/SkWriter32.h @@ -0,0 +1,270 @@ + +/* + * Copyright 2008 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkWriter32_DEFINED +#define SkWriter32_DEFINED + +#include "SkMatrix.h" +#include "SkPath.h" +#include "SkPoint.h" +#include "SkRRect.h" +#include "SkRect.h" +#include "SkRegion.h" +#include "SkScalar.h" +#include "SkStream.h" +#include "SkTDArray.h" +#include "SkTypes.h" + +class SkWriter32 : SkNoncopyable { +public: + /** + * The caller can specify an initial block of storage, which the caller manages. + * + * SkWriter32 will try to back reserve and write calls with this external storage until the + * first time an allocation doesn't fit. From then it will use dynamically allocated storage. + * This used to be optional behavior, but pipe now relies on it. + */ + SkWriter32(void* external = NULL, size_t externalBytes = 0) + : fData(0) + , fCapacity(0) + , fUsed(0) + , fExternal(0) + { + this->reset(external, externalBytes); + } + + // return the current offset (will always be a multiple of 4) + size_t bytesWritten() const { return fUsed; } + + SK_ATTR_DEPRECATED("use bytesWritten") + size_t size() const { return this->bytesWritten(); } + + void reset(void* external = NULL, size_t externalBytes = 0) { + SkASSERT(SkIsAlign4((uintptr_t)external)); + SkASSERT(SkIsAlign4(externalBytes)); + + fData = (uint8_t*)external; + fCapacity = externalBytes; + fUsed = 0; + fExternal = external; + } + + // Returns the current buffer. + // The pointer may be invalidated by any future write calls. + const uint32_t* contiguousArray() const { + return (uint32_t*)fData; + } + + // size MUST be multiple of 4 + uint32_t* reserve(size_t size) { + SkASSERT(SkAlign4(size) == size); + size_t offset = fUsed; + size_t totalRequired = fUsed + size; + if (totalRequired > fCapacity) { + this->growToAtLeast(totalRequired); + } + fUsed = totalRequired; + return (uint32_t*)(fData + offset); + } + + /** + * Read a T record at offset, which must be a multiple of 4. Only legal if the record + * was writtern atomically using the write methods below. + */ + template + const T& readTAt(size_t offset) const { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset < fUsed); + return *(T*)(fData + offset); + } + + /** + * Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record + * was writtern atomically using the write methods below. + */ + template + void overwriteTAt(size_t offset, const T& value) { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset < fUsed); + *(T*)(fData + offset) = value; + } + + bool writeBool(bool value) { + this->write32(value); + return value; + } + + void writeInt(int32_t value) { + this->write32(value); + } + + void write8(int32_t value) { + *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; + } + + void write16(int32_t value) { + *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; + } + + void write32(int32_t value) { + *(int32_t*)this->reserve(sizeof(value)) = value; + } + + void writePtr(void* value) { + *(void**)this->reserve(sizeof(value)) = value; + } + + void writeScalar(SkScalar value) { + *(SkScalar*)this->reserve(sizeof(value)) = value; + } + + void writePoint(const SkPoint& pt) { + *(SkPoint*)this->reserve(sizeof(pt)) = pt; + } + + void writeRect(const SkRect& rect) { + *(SkRect*)this->reserve(sizeof(rect)) = rect; + } + + void writeIRect(const SkIRect& rect) { + *(SkIRect*)this->reserve(sizeof(rect)) = rect; + } + + void writeRRect(const SkRRect& rrect) { + rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); + } + + void writePath(const SkPath& path) { + size_t size = path.writeToMemory(NULL); + SkASSERT(SkAlign4(size) == size); + path.writeToMemory(this->reserve(size)); + } + + void writeMatrix(const SkMatrix& matrix) { + size_t size = matrix.writeToMemory(NULL); + SkASSERT(SkAlign4(size) == size); + matrix.writeToMemory(this->reserve(size)); + } + + void writeRegion(const SkRegion& rgn) { + size_t size = rgn.writeToMemory(NULL); + SkASSERT(SkAlign4(size) == size); + rgn.writeToMemory(this->reserve(size)); + } + + // write count bytes (must be a multiple of 4) + void writeMul4(const void* values, size_t size) { + this->write(values, size); + } + + /** + * Write size bytes from values. size must be a multiple of 4, though + * values need not be 4-byte aligned. + */ + void write(const void* values, size_t size) { + SkASSERT(SkAlign4(size) == size); + memcpy(this->reserve(size), values, size); + } + + /** + * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be + * filled in with zeroes. + */ + uint32_t* reservePad(size_t size) { + size_t alignedSize = SkAlign4(size); + uint32_t* p = this->reserve(alignedSize); + if (alignedSize != size) { + SkASSERT(alignedSize >= 4); + p[alignedSize / 4 - 1] = 0; + } + return p; + } + + /** + * Write size bytes from src, and pad to 4 byte alignment with zeroes. + */ + void writePad(const void* src, size_t size) { + memcpy(this->reservePad(size), src, size); + } + + /** + * Writes a string to the writer, which can be retrieved with + * SkReader32::readString(). + * The length can be specified, or if -1 is passed, it will be computed by + * calling strlen(). The length must be < max size_t. + * + * If you write NULL, it will be read as "". + */ + void writeString(const char* str, size_t len = (size_t)-1); + + /** + * Computes the size (aligned to multiple of 4) need to write the string + * in a call to writeString(). If the length is not specified, it will be + * computed by calling strlen(). + */ + static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); + + /** + * Move the cursor back to offset bytes from the beginning. + * offset must be a multiple of 4 no greater than size(). + */ + void rewindToOffset(size_t offset) { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset <= bytesWritten()); + fUsed = offset; + } + + // copy into a single buffer (allocated by caller). Must be at least size() + void flatten(void* dst) const { + memcpy(dst, fData, fUsed); + } + + bool writeToStream(SkWStream* stream) const { + return stream->write(fData, fUsed); + } + + // read from the stream, and write up to length bytes. Return the actual + // number of bytes written. + size_t readFromStream(SkStream* stream, size_t length) { + return stream->read(this->reservePad(length), length); + } + +private: + void growToAtLeast(size_t size); + + uint8_t* fData; // Points to either fInternal or fExternal. + size_t fCapacity; // Number of bytes we can write to fData. + size_t fUsed; // Number of bytes written. + void* fExternal; // Unmanaged memory block. + SkTDArray fInternal; // Managed memory block. +}; + +/** + * Helper class to allocated SIZE bytes as part of the writer, and to provide + * that storage to the constructor as its initial storage buffer. + * + * This wrapper ensures proper alignment rules are met for the storage. + */ +template class SkSWriter32 : public SkWriter32 { +public: + SkSWriter32() { this->reset(); } + + void reset() {this->INHERITED::reset(fData.fStorage, SIZE); } + +private: + union { + void* fPtrAlignment; + double fDoubleAlignment; + char fStorage[SIZE]; + } fData; + + typedef SkWriter32 INHERITED; +}; + +#endif diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/trunk/include/core/SkXfermode.h similarity index 77% rename from gfx/skia/include/core/SkXfermode.h rename to gfx/skia/trunk/include/core/SkXfermode.h index 3a395225fd90..31b8081f85b0 100644 --- a/gfx/skia/include/core/SkXfermode.h +++ b/gfx/skia/trunk/include/core/SkXfermode.h @@ -13,18 +13,21 @@ #include "SkFlattenable.h" #include "SkColor.h" -class GrContext; class GrEffectRef; +class GrTexture; class SkString; /** \class SkXfermode - - SkXfermode is the base class for objects that are called to implement custom - "transfer-modes" in the drawing pipeline. The static function Create(Modes) - can be called to return an instance of any of the predefined subclasses as - specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, - then objects drawn with that paint have the xfermode applied. -*/ + * + * SkXfermode is the base class for objects that are called to implement custom + * "transfer-modes" in the drawing pipeline. The static function Create(Modes) + * can be called to return an instance of any of the predefined subclasses as + * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, + * then objects drawn with that paint have the xfermode applied. + * + * All subclasses are required to be reentrant-safe : it must be legal to share + * the same instance between several threads. + */ class SK_API SkXfermode : public SkFlattenable { public: SK_DECLARE_INST_COUNT(SkXfermode) @@ -35,8 +38,6 @@ public: const SkAlpha aa[]) const; virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[]) const; - virtual void xfer4444(uint16_t dst[], const SkPMColor src[], int count, - const SkAlpha aa[]) const; virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[]) const; @@ -87,6 +88,9 @@ public: [a, c] - Resulting (alpha, color) values For these equations, the colors are in premultiplied state. If no xfermode is specified, kSrcOver is assumed. + The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those + that aren't Coeffs but have separable r,g,b computations, and finally + those that are not separable. */ enum Mode { kClear_Mode, //!< [0, 0] @@ -104,12 +108,11 @@ public: kPlus_Mode, //!< [Sa + Da, Sc + Dc] kModulate_Mode, // multiplies all components (= alpha and color) - // all above modes can be expressed as pair of src/dst Coeffs - kCoeffModesCnt, - // Following blend modes are defined in the CSS Compositing standard: // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending - kScreen_Mode = kCoeffModesCnt, + kScreen_Mode, + kLastCoeffMode = kScreen_Mode, + kOverlay_Mode, kDarken_Mode, kLighten_Mode, @@ -120,12 +123,12 @@ public: kDifference_Mode, kExclusion_Mode, kMultiply_Mode, + kLastSeparableMode = kMultiply_Mode, kHue_Mode, kSaturation_Mode, kColor_Mode, kLuminosity_Mode, - kLastMode = kLuminosity_Mode }; @@ -183,39 +186,39 @@ public: */ static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst); - // DEPRECATED: call AsMode(...) + SK_ATTR_DEPRECATED("use AsMode(...)") static bool IsMode(const SkXfermode* xfer, Mode* mode) { return AsMode(xfer, mode); } /** A subclass may implement this factory function to work with the GPU backend. It is legal - to call this with all but the context param NULL to simply test the return value. effect, - src, and dst must all be NULL or all non-NULL. If effect is non-NULL then the xfermode may - optionally allocate an effect to return and the caller as *effect. The caller will install - it and own a ref to it. Since the xfermode may or may not assign *effect, the caller should - set *effect to NULL beforehand. If the function returns true and *effect is NULL then the - src and dst coeffs will be applied to the draw. When *effect is non-NULL the coeffs are - ignored. + to call this with all params NULL to simply test the return value. If effect is non-NULL + then the xfermode may optionally allocate an effect to return and the caller as *effect. + The caller will install it and own a ref to it. Since the xfermode may or may not assign + *effect, the caller should set *effect to NULL beforehand. background specifies the + texture to use as the background for compositing, and should be accessed in the effect's + fragment shader. If NULL, the effect should request access to destination color + (setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()). */ - virtual bool asNewEffectOrCoeff(GrContext*, - GrEffectRef** effect, - Coeff* src, - Coeff* dst) const; + virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background = NULL) const; - /** - * The same as calling xfermode->asNewEffect(...), except that this also checks if the xfermode - * is NULL, and if so, treats it as kSrcOver_Mode. + /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect + (effect). This helper calls the asCoeff() and asNewEffect() virtuals. If the xfermode is + NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to + simply test the return value. effect, src, and dst must all be NULL or all non-NULL. */ static bool AsNewEffectOrCoeff(SkXfermode*, - GrContext*, GrEffectRef** effect, Coeff* src, - Coeff* dst); + Coeff* dst, + GrTexture* background = NULL); SkDEVCODE(virtual void toString(SkString* str) const = 0;) SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkXfermode) + protected: - SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {} + SkXfermode(SkReadBuffer& rb) : SkFlattenable(rb) {} /** The default implementation of xfer32/xfer16/xferA8 in turn call this method, 1 color at a time (upscaled to a SkPMColor). The default @@ -231,6 +234,10 @@ private: enum { kModeCount = kLastMode + 1 }; + + friend class SkGraphics; + static void Term(); + typedef SkFlattenable INHERITED; }; @@ -250,8 +257,6 @@ public: 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 xfer4444(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; @@ -259,14 +264,18 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode) protected: - SkProcXfermode(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkProcXfermode(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // allow subclasses to update this after we unflatten void setProc(SkXfermodeProc proc) { fProc = proc; } + SkXfermodeProc getProc() const { + return fProc; + } + private: SkXfermodeProc fProc; diff --git a/gfx/skia/include/device/xps/SkConstexprMath.h b/gfx/skia/trunk/include/device/xps/SkConstexprMath.h similarity index 87% rename from gfx/skia/include/device/xps/SkConstexprMath.h rename to gfx/skia/trunk/include/device/xps/SkConstexprMath.h index 65b70b6eeab2..9625d5112b13 100644 --- a/gfx/skia/include/device/xps/SkConstexprMath.h +++ b/gfx/skia/trunk/include/device/xps/SkConstexprMath.h @@ -46,7 +46,9 @@ struct SK_2N1<1> { */ #define SK_DIGITS_IN(t) SK_BASE_N_DIGITS_IN(10, (t)) -//! a > b ? a : b -#define SK_MAX(a,b) (((a) > (b)) ? (a) : (b)) +// Compile-time constant maximum value of two unsigned values. +template struct SkTUMax { + static const uintmax_t value = (b < a) ? a : b; +}; #endif diff --git a/gfx/skia/include/device/xps/SkXPSDevice.h b/gfx/skia/trunk/include/device/xps/SkXPSDevice.h similarity index 92% rename from gfx/skia/include/device/xps/SkXPSDevice.h rename to gfx/skia/trunk/include/device/xps/SkXPSDevice.h index 228e90539b57..13ae83492f60 100644 --- a/gfx/skia/include/device/xps/SkXPSDevice.h +++ b/gfx/skia/trunk/include/device/xps/SkXPSDevice.h @@ -13,10 +13,10 @@ #include #include "SkAutoCoInitialize.h" +#include "SkBitmapDevice.h" #include "SkBitSet.h" #include "SkCanvas.h" #include "SkColor.h" -#include "SkDevice.h" #include "SkPaint.h" #include "SkPath.h" #include "SkPoint.h" @@ -30,7 +30,7 @@ The drawing context for the XPS backend. */ -class SkXPSDevice : public SkDevice { +class SkXPSDevice : public SkBitmapDevice { public: SK_API SkXPSDevice(); SK_API virtual ~SkXPSDevice(); @@ -85,6 +85,11 @@ protected: const SkRect& r, const SkPaint& paint) SK_OVERRIDE; + virtual void drawRRect( + const SkDraw&, + const SkRRect&, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawPath( const SkDraw&, const SkPath& platonicPath, @@ -95,7 +100,6 @@ protected: virtual void drawBitmap( const SkDraw&, const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE; @@ -135,7 +139,7 @@ protected: virtual void drawDevice( const SkDraw&, - SkDevice* device, + SkBaseDevice* device, int x, int y, const SkPaint& paint) SK_OVERRIDE; @@ -144,12 +148,13 @@ protected: int y, SkCanvas::Config8888) SK_OVERRIDE; - virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE; + virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE; private: class TypefaceUse : ::SkNoncopyable { public: SkFontID typefaceId; + int ttcIndex; SkStream* fontData; IXpsOMFontResource* xpsFont; SkBitSet* glyphsUsed; @@ -247,7 +252,7 @@ private: const SkDraw& d, IXpsOMObjectFactory* xpsFactory, IXpsOMCanvas* canvas, - IXpsOMFontResource* font, + TypefaceUse* font, LPCWSTR text, XPS_GLYPH_INDEX* xpsGlyphs, UINT32 xpsGlyphsLen, @@ -307,18 +312,17 @@ private: const SkVector& ppuScale, IXpsOMPath* shadedPath); - // override from SkDevice - virtual SkDevice* onCreateCompatibleDevice( - SkBitmap::Config config, - int width, int height, - bool isOpaque, - Usage usage) SK_OVERRIDE; + // override from SkBaseDevice + virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) SK_OVERRIDE; // Disable the default copy and assign implementation. SkXPSDevice(const SkXPSDevice&); void operator=(const SkXPSDevice&); - typedef SkDevice INHERITED; + typedef SkBitmapDevice INHERITED; }; #endif diff --git a/gfx/skia/include/effects/Sk1DPathEffect.h b/gfx/skia/trunk/include/effects/Sk1DPathEffect.h similarity index 95% rename from gfx/skia/include/effects/Sk1DPathEffect.h rename to gfx/skia/trunk/include/effects/Sk1DPathEffect.h index 4599276e7bba..4ac8f73b266b 100644 --- a/gfx/skia/include/effects/Sk1DPathEffect.h +++ b/gfx/skia/trunk/include/effects/Sk1DPathEffect.h @@ -60,8 +60,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath1DPathEffect) protected: - SkPath1DPathEffect(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkPath1DPathEffect(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // overrides from Sk1DPathEffect virtual SkScalar begin(SkScalar contourLength) const SK_OVERRIDE; diff --git a/gfx/skia/include/effects/Sk2DPathEffect.h b/gfx/skia/trunk/include/effects/Sk2DPathEffect.h similarity index 88% rename from gfx/skia/include/effects/Sk2DPathEffect.h rename to gfx/skia/trunk/include/effects/Sk2DPathEffect.h index ed7f674f89ca..859b5cd95292 100644 --- a/gfx/skia/include/effects/Sk2DPathEffect.h +++ b/gfx/skia/trunk/include/effects/Sk2DPathEffect.h @@ -41,8 +41,8 @@ protected: const SkMatrix& getMatrix() const { return fMatrix; } // protected so that subclasses can call this during unflattening - Sk2DPathEffect(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + Sk2DPathEffect(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkMatrix fMatrix, fInverse; @@ -69,9 +69,9 @@ public: protected: virtual void nextSpan(int u, int v, int ucount, SkPath*) const SK_OVERRIDE; - SkLine2DPathEffect(SkFlattenableReadBuffer&); + SkLine2DPathEffect(SkReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkScalar fWidth; @@ -90,8 +90,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPath2DPathEffect) protected: - SkPath2DPathEffect(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkPath2DPathEffect(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual void next(const SkPoint&, int u, int v, SkPath*) const SK_OVERRIDE; diff --git a/gfx/skia/trunk/include/effects/SkAlphaThresholdFilter.h b/gfx/skia/trunk/include/effects/SkAlphaThresholdFilter.h new file mode 100644 index 000000000000..23af56fc549a --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkAlphaThresholdFilter.h @@ -0,0 +1,26 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkAlphaThresholdFilter_DEFINED +#define SkAlphaThresholdFilter_DEFINED + +#include "SkRegion.h" +#include "SkImageFilter.h" + +class SK_API SkAlphaThresholdFilter { +public: + /** + * Creates an image filter that samples a region. If the sample is inside the + * region the alpha of the image is boosted up to a threshold value. If it is + * outside the region then the alpha is decreased to the threshold value. + * The 0,0 point of the region corresponds to the upper left corner of the + * source image. + */ + static SkImageFilter* Create(const SkRegion& region, SkScalar innerThreshold, SkScalar outerThreshold); +}; + +#endif diff --git a/gfx/skia/include/effects/SkArithmeticMode.h b/gfx/skia/trunk/include/effects/SkArithmeticMode.h similarity index 79% rename from gfx/skia/include/effects/SkArithmeticMode.h rename to gfx/skia/trunk/include/effects/SkArithmeticMode.h index dc5493f77402..46b7121bb4c5 100644 --- a/gfx/skia/include/effects/SkArithmeticMode.h +++ b/gfx/skia/trunk/include/effects/SkArithmeticMode.h @@ -8,9 +8,12 @@ #ifndef SkArithmeticMode_DEFINED #define SkArithmeticMode_DEFINED -#include "SkXfermode.h" +#include "SkFlattenable.h" +#include "SkScalar.h" -class SK_API SkArithmeticMode : public SkXfermode { +class SkXfermode; + +class SK_API SkArithmeticMode { public: /** * result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4] @@ -25,8 +28,10 @@ public: static SkXfermode* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4); + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP(); + private: - typedef SkXfermode INHERITED; + SkArithmeticMode(); // can't be instantiated }; #endif diff --git a/gfx/skia/include/effects/SkAvoidXfermode.h b/gfx/skia/trunk/include/effects/SkAvoidXfermode.h similarity index 89% rename from gfx/skia/include/effects/SkAvoidXfermode.h rename to gfx/skia/trunk/include/effects/SkAvoidXfermode.h index e35439160eb7..afc3fc9d7009 100644 --- a/gfx/skia/include/effects/SkAvoidXfermode.h +++ b/gfx/skia/trunk/include/effects/SkAvoidXfermode.h @@ -44,8 +44,6 @@ public: 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 xfer4444(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; @@ -53,8 +51,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAvoidXfermode) protected: - SkAvoidXfermode(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkAvoidXfermode(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkColor fOpColor; diff --git a/gfx/skia/include/effects/SkBicubicImageFilter.h b/gfx/skia/trunk/include/effects/SkBicubicImageFilter.h similarity index 83% rename from gfx/skia/include/effects/SkBicubicImageFilter.h rename to gfx/skia/trunk/include/effects/SkBicubicImageFilter.h index 119c07958eca..48105b1c5b7e 100644 --- a/gfx/skia/include/effects/SkBicubicImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkBicubicImageFilter.h @@ -27,22 +27,24 @@ public: passed to filterImage() is used instead. */ - SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16], SkImageFilter* input = NULL); + SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16], + SkImageFilter* input = NULL); static SkBicubicImageFilter* CreateMitchell(const SkSize& scale, SkImageFilter* input = NULL); virtual ~SkBicubicImageFilter(); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBicubicImageFilter) protected: - SkBicubicImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkBicubicImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; #if SK_SUPPORT_GPU virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; } - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; #endif private: diff --git a/gfx/skia/trunk/include/effects/SkBitmapAlphaThresholdShader.h b/gfx/skia/trunk/include/effects/SkBitmapAlphaThresholdShader.h new file mode 100644 index 000000000000..61596daff3e0 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkBitmapAlphaThresholdShader.h @@ -0,0 +1,24 @@ +/* + * 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 "SkShader.h" +#include "SkBitmap.h" +#include "SkRegion.h" +#include "SkString.h" + +class SK_API SkBitmapAlphaThresholdShader : public SkShader { +public: + /** + * Creates a shader that samples a bitmap and a region. If the sample is inside the region + * the alpha of the bitmap color is boosted up to a threshold value. If it is + * outside the region then the bitmap alpha is decreased to the threshold value. + * The 0,0 point of the region corresponds to the upper left corner of the bitmap + * Currently, this only has a GPU implementation, doesn't respect the paint's bitmap + * filter setting, and always uses clamp mode. + */ + static SkShader* Create(const SkBitmap& bitmap, const SkRegion& region, U8CPU threshold); +}; diff --git a/gfx/skia/include/effects/SkBitmapSource.h b/gfx/skia/trunk/include/effects/SkBitmapSource.h similarity index 60% rename from gfx/skia/include/effects/SkBitmapSource.h rename to gfx/skia/trunk/include/effects/SkBitmapSource.h index 138987e701bb..fcc1db97bc75 100644 --- a/gfx/skia/include/effects/SkBitmapSource.h +++ b/gfx/skia/trunk/include/effects/SkBitmapSource.h @@ -14,17 +14,21 @@ class SK_API SkBitmapSource : public SkImageFilter { public: explicit SkBitmapSource(const SkBitmap& bitmap); + SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect); + virtual void computeFastBounds(const SkRect& src, SkRect* dst) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapSource) protected: - explicit SkBitmapSource(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + explicit SkBitmapSource(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const SK_OVERRIDE; private: SkBitmap fBitmap; + SkRect fSrcRect, fDstRect; typedef SkImageFilter INHERITED; }; diff --git a/gfx/skia/include/effects/SkBlurDrawLooper.h b/gfx/skia/trunk/include/effects/SkBlurDrawLooper.h similarity index 82% rename from gfx/skia/include/effects/SkBlurDrawLooper.h rename to gfx/skia/trunk/include/effects/SkBlurDrawLooper.h index e9688578891f..46b154debcae 100644 --- a/gfx/skia/include/effects/SkBlurDrawLooper.h +++ b/gfx/skia/trunk/include/effects/SkBlurDrawLooper.h @@ -35,6 +35,10 @@ public: kAll_BlurFlag = 0x07 }; + SkBlurDrawLooper(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy, + uint32_t flags = kNone_BlurFlag); + +// SK_ATTR_DEPRECATED("use sigma version") SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags = kNone_BlurFlag); virtual ~SkBlurDrawLooper(); @@ -47,8 +51,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurDrawLooper) protected: - SkBlurDrawLooper(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkBlurDrawLooper(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkMaskFilter* fBlur; @@ -64,6 +68,8 @@ private: }; State fState; + void init(SkScalar sigma, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags); + typedef SkDrawLooper INHERITED; }; diff --git a/gfx/skia/include/effects/SkBlurImageFilter.h b/gfx/skia/trunk/include/effects/SkBlurImageFilter.h similarity index 54% rename from gfx/skia/include/effects/SkBlurImageFilter.h rename to gfx/skia/trunk/include/effects/SkBlurImageFilter.h index 80ea9e5c92cf..60dab729b407 100644 --- a/gfx/skia/include/effects/SkBlurImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkBlurImageFilter.h @@ -13,19 +13,26 @@ class SK_API SkBlurImageFilter : public SkImageFilter { public: - SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input = NULL); + SkBlurImageFilter(SkScalar sigmaX, + SkScalar sigmaY, + SkImageFilter* input = NULL, + const CropRect* cropRect = NULL); + virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter) protected: - explicit SkBlurImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + explicit SkBlurImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&, + SkIRect* dst) const SK_OVERRIDE; bool canFilterImageGPU() const SK_OVERRIDE { return true; } - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; private: SkSize fSigma; diff --git a/gfx/skia/include/effects/SkBlurMaskFilter.h b/gfx/skia/trunk/include/effects/SkBlurMaskFilter.h similarity index 68% rename from gfx/skia/include/effects/SkBlurMaskFilter.h rename to gfx/skia/trunk/include/effects/SkBlurMaskFilter.h index 2ab321aa7ad2..9b352dc1e45b 100644 --- a/gfx/skia/include/effects/SkBlurMaskFilter.h +++ b/gfx/skia/trunk/include/effects/SkBlurMaskFilter.h @@ -33,27 +33,37 @@ public: kAll_BlurFlag = 0x03 }; - /** Create a blur maskfilter. - @param radius The radius to extend the blur from the original mask. Must be > 0. - @param style The BlurStyle to use - @param flags Flags to use - defaults to none - @return The new blur maskfilter - */ + SK_ATTR_DEPRECATED("use sigma version") static SkMaskFilter* Create(SkScalar radius, BlurStyle style, uint32_t flags = kNone_BlurFlag); + /** Create a blur maskfilter. + @param style The BlurStyle to use + @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0. + @param flags Flags to use - defaults to none + @return The new blur maskfilter + */ + static SkMaskFilter* Create(BlurStyle style, SkScalar sigma, + uint32_t flags = kNone_BlurFlag); + /** Create an emboss maskfilter + @param blurSigma standard deviation of the Gaussian blur to apply + before applying lighting (e.g. 3) @param direction array of 3 scalars [x, y, z] specifying the direction of the light source @param ambient 0...1 amount of ambient light @param specular coefficient for specular highlights (e.g. 8) - @param blurRadius amount to blur before applying lighting (e.g. 3) @return the emboss maskfilter */ - static SkMaskFilter* CreateEmboss( const SkScalar direction[3], - SkScalar ambient, SkScalar specular, - SkScalar blurRadius); + static SkMaskFilter* CreateEmboss(SkScalar blurSigma, const SkScalar direction[3], + SkScalar ambient, SkScalar specular); + + SK_ATTR_DEPRECATED("use sigma version") + static SkMaskFilter* CreateEmboss(const SkScalar direction[3], + SkScalar ambient, SkScalar specular, + SkScalar blurRadius); SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + private: SkBlurMaskFilter(); // can't be instantiated }; diff --git a/gfx/skia/include/effects/SkColorFilterImageFilter.h b/gfx/skia/trunk/include/effects/SkColorFilterImageFilter.h similarity index 61% rename from gfx/skia/include/effects/SkColorFilterImageFilter.h rename to gfx/skia/trunk/include/effects/SkColorFilterImageFilter.h index 2e5e59c3c096..d127f36db3c3 100755 --- a/gfx/skia/include/effects/SkColorFilterImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkColorFilterImageFilter.h @@ -14,22 +14,26 @@ class SkColorFilter; class SK_API SkColorFilterImageFilter : public SkImageFilter { public: - static SkColorFilterImageFilter* Create(SkColorFilter* cf, SkImageFilter* input = NULL); + static SkColorFilterImageFilter* Create(SkColorFilter* cf, + SkImageFilter* input = NULL, + const CropRect* cropRect = NULL); virtual ~SkColorFilterImageFilter(); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter) protected: - SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkColorFilterImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; virtual bool asColorFilter(SkColorFilter**) const SK_OVERRIDE; private: - SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input); + SkColorFilterImageFilter(SkColorFilter* cf, + SkImageFilter* input, + const CropRect* cropRect = NULL); SkColorFilter* fColorFilter; typedef SkImageFilter INHERITED; diff --git a/gfx/skia/include/effects/SkColorMatrix.h b/gfx/skia/trunk/include/effects/SkColorMatrix.h similarity index 81% rename from gfx/skia/include/effects/SkColorMatrix.h rename to gfx/skia/trunk/include/effects/SkColorMatrix.h index 84a3b7c4970e..c598a1210e5a 100644 --- a/gfx/skia/include/effects/SkColorMatrix.h +++ b/gfx/skia/trunk/include/effects/SkColorMatrix.h @@ -14,6 +14,18 @@ class SK_API SkColorMatrix { public: SkScalar fMat[20]; + enum Elem { + kR_Scale = 0, + kG_Scale = 6, + kB_Scale = 12, + kA_Scale = 18, + + kR_Trans = 4, + kG_Trans = 9, + kB_Trans = 14, + kA_Trans = 19, + }; + void setIdentity(); void setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale, SkScalar aScale = SK_Scalar1); @@ -21,6 +33,8 @@ public: SkScalar aScale = SK_Scalar1); void postScale(SkScalar rScale, SkScalar gScale, SkScalar bScale, SkScalar aScale = SK_Scalar1); + void postTranslate(SkScalar rTrans, SkScalar gTrans, SkScalar bTrans, + SkScalar aTrans = 0); enum Axis { kR_Axis = 0, diff --git a/gfx/skia/include/effects/SkColorMatrixFilter.h b/gfx/skia/trunk/include/effects/SkColorMatrixFilter.h similarity index 88% rename from gfx/skia/include/effects/SkColorMatrixFilter.h rename to gfx/skia/trunk/include/effects/SkColorMatrixFilter.h index e44a7cd75045..a4144e17175d 100644 --- a/gfx/skia/include/effects/SkColorMatrixFilter.h +++ b/gfx/skia/trunk/include/effects/SkColorMatrixFilter.h @@ -30,11 +30,13 @@ public: int fShift; }; + SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorMatrixFilter) protected: - SkColorMatrixFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkColorMatrixFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkColorMatrix fMatrix; diff --git a/gfx/skia/trunk/include/effects/SkComposeImageFilter.h b/gfx/skia/trunk/include/effects/SkComposeImageFilter.h new file mode 100644 index 000000000000..9e024ef84e19 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkComposeImageFilter.h @@ -0,0 +1,31 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkComposeImageFilter_DEFINED +#define SkComposeImageFilter_DEFINED + +#include "SkImageFilter.h" + +class SK_API SkComposeImageFilter : public SkImageFilter { +public: + SkComposeImageFilter(SkImageFilter* outer, SkImageFilter* inner) : INHERITED(outer, inner) {} + virtual ~SkComposeImageFilter(); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeImageFilter) + +protected: + explicit SkComposeImageFilter(SkReadBuffer& buffer); + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const SK_OVERRIDE; + +private: + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkCornerPathEffect.h b/gfx/skia/trunk/include/effects/SkCornerPathEffect.h similarity index 89% rename from gfx/skia/include/effects/SkCornerPathEffect.h rename to gfx/skia/trunk/include/effects/SkCornerPathEffect.h index 704b7fb8f024..dcb7c9f736c3 100644 --- a/gfx/skia/include/effects/SkCornerPathEffect.h +++ b/gfx/skia/trunk/include/effects/SkCornerPathEffect.h @@ -29,8 +29,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCornerPathEffect) protected: - SkCornerPathEffect(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkCornerPathEffect(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkScalar fRadius; diff --git a/gfx/skia/include/effects/SkDashPathEffect.h b/gfx/skia/trunk/include/effects/SkDashPathEffect.h similarity index 89% rename from gfx/skia/include/effects/SkDashPathEffect.h rename to gfx/skia/trunk/include/effects/SkDashPathEffect.h index 9c0775dfbaa1..818e0739246f 100644 --- a/gfx/skia/include/effects/SkDashPathEffect.h +++ b/gfx/skia/trunk/include/effects/SkDashPathEffect.h @@ -47,13 +47,13 @@ public: const SkStrokeRec&, const SkMatrix&, const SkRect*) const SK_OVERRIDE; - virtual Factory getFactory() SK_OVERRIDE; + virtual Factory getFactory() const SK_OVERRIDE; - static SkFlattenable* CreateProc(SkFlattenableReadBuffer&); + static SkFlattenable* CreateProc(SkReadBuffer&); protected: - SkDashPathEffect(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkDashPathEffect(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkScalar* fIntervals; diff --git a/gfx/skia/include/effects/SkDiscretePathEffect.h b/gfx/skia/trunk/include/effects/SkDiscretePathEffect.h similarity index 89% rename from gfx/skia/include/effects/SkDiscretePathEffect.h rename to gfx/skia/trunk/include/effects/SkDiscretePathEffect.h index 999ea04810bf..60eb85274c17 100644 --- a/gfx/skia/include/effects/SkDiscretePathEffect.h +++ b/gfx/skia/trunk/include/effects/SkDiscretePathEffect.h @@ -28,8 +28,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscretePathEffect) protected: - SkDiscretePathEffect(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkDiscretePathEffect(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: SkScalar fSegLength, fPerterb; diff --git a/gfx/skia/include/effects/SkDisplacementMapEffect.h b/gfx/skia/trunk/include/effects/SkDisplacementMapEffect.h similarity index 58% rename from gfx/skia/include/effects/SkDisplacementMapEffect.h rename to gfx/skia/trunk/include/effects/SkDisplacementMapEffect.h index 18f9df866e43..5de4814951a6 100644 --- a/gfx/skia/include/effects/SkDisplacementMapEffect.h +++ b/gfx/skia/trunk/include/effects/SkDisplacementMapEffect.h @@ -22,7 +22,11 @@ public: kKeyBits = 3 // Max value is 4, so 3 bits are required at most }; - SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, SkScalar scale, SkImageFilter* displacement, SkImageFilter* color = NULL); + SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, + ChannelSelectorType yChannelSelector, + SkScalar scale, SkImageFilter* displacement, + SkImageFilter* color = NULL, + const CropRect* cropRect = NULL); ~SkDisplacementMapEffect(); @@ -32,23 +36,29 @@ public: const SkBitmap& src, const SkMatrix& ctm, SkBitmap* dst, - SkIPoint* offset) SK_OVERRIDE; + SkIPoint* offset) const SK_OVERRIDE; + virtual void computeFastBounds(const SkRect& src, SkRect* dst) const SK_OVERRIDE; + + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&, + SkIRect* dst) const SK_OVERRIDE; + #if SK_SUPPORT_GPU virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; } - virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE; + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; #endif protected: - explicit SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + explicit SkDisplacementMapEffect(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: ChannelSelectorType fXChannelSelector; ChannelSelectorType fYChannelSelector; SkScalar fScale; typedef SkImageFilter INHERITED; - SkImageFilter* getDisplacementInput() { return getInput(0); } - SkImageFilter* getColorInput() { return getInput(1); } + const SkImageFilter* getDisplacementInput() const { return getInput(0); } + const SkImageFilter* getColorInput() const { return getInput(1); } }; #endif diff --git a/gfx/skia/include/effects/SkDrawExtraPathEffect.h b/gfx/skia/trunk/include/effects/SkDrawExtraPathEffect.h similarity index 100% rename from gfx/skia/include/effects/SkDrawExtraPathEffect.h rename to gfx/skia/trunk/include/effects/SkDrawExtraPathEffect.h diff --git a/gfx/skia/trunk/include/effects/SkDropShadowImageFilter.h b/gfx/skia/trunk/include/effects/SkDropShadowImageFilter.h new file mode 100644 index 000000000000..aba2017eef6d --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkDropShadowImageFilter.h @@ -0,0 +1,32 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkColor.h" +#include "SkImageFilter.h" +#include "SkScalar.h" + +class SK_API SkDropShadowImageFilter : public SkImageFilter { +public: + SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor, SkImageFilter* input = NULL); + SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor, SkImageFilter* input = NULL, const CropRect* cropRect = NULL); + virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDropShadowImageFilter) + +protected: + explicit SkDropShadowImageFilter(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual bool onFilterImage(Proxy*, const SkBitmap& source, const SkMatrix&, SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&, + SkIRect* dst) const SK_OVERRIDE; + + + +private: + SkScalar fDx, fDy, fSigmaX, fSigmaY; + SkColor fColor; + typedef SkImageFilter INHERITED; +}; diff --git a/gfx/skia/include/effects/SkEmbossMaskFilter.h b/gfx/skia/trunk/include/effects/SkEmbossMaskFilter.h similarity index 84% rename from gfx/skia/include/effects/SkEmbossMaskFilter.h rename to gfx/skia/trunk/include/effects/SkEmbossMaskFilter.h index c6679200b3e9..263c5e054509 100644 --- a/gfx/skia/include/effects/SkEmbossMaskFilter.h +++ b/gfx/skia/trunk/include/effects/SkEmbossMaskFilter.h @@ -23,6 +23,9 @@ public: uint8_t fSpecular; // exponent, 4.4 right now }; + SkEmbossMaskFilter(SkScalar blurSigma, const Light& light); + + SK_ATTR_DEPRECATED("use sigma version") SkEmbossMaskFilter(const Light& light, SkScalar blurRadius); // overrides from SkMaskFilter @@ -36,12 +39,12 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmbossMaskFilter) protected: - SkEmbossMaskFilter(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkEmbossMaskFilter(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: Light fLight; - SkScalar fBlurRadius; + SkScalar fBlurSigma; typedef SkMaskFilter INHERITED; }; diff --git a/gfx/skia/include/effects/SkGradientShader.h b/gfx/skia/trunk/include/effects/SkGradientShader.h similarity index 80% rename from gfx/skia/include/effects/SkGradientShader.h rename to gfx/skia/trunk/include/effects/SkGradientShader.h index dbeb2fb06981..ed0f1bf75b54 100644 --- a/gfx/skia/include/effects/SkGradientShader.h +++ b/gfx/skia/trunk/include/effects/SkGradientShader.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkGradientShader_DEFINED #define SkGradientShader_DEFINED @@ -21,6 +19,15 @@ class SkUnitMapper; */ class SK_API SkGradientShader { public: + enum Flags { + /** By default gradients will interpolate their colors in unpremul space + * and then premultiply each of the results. By setting this flag, the + * gradients will premultiply their colors first, and then interpolate + * between them. + */ + kInterpolateColorsInPremul_Flag = 1 << 0, + }; + /** Returns a shader that generates a linear gradient between the two specified points.

@@ -38,10 +45,11 @@ public: @param mode The tiling mode @param mapper May be NULL. Callback to modify the spread of the colors. */ - static SkShader* CreateLinear( const SkPoint pts[2], - const SkColor colors[], const SkScalar pos[], int count, - SkShader::TileMode mode, - SkUnitMapper* mapper = NULL); + static SkShader* CreateLinear(const SkPoint pts[2], + const SkColor colors[], const SkScalar pos[], int count, + SkShader::TileMode mode, + SkUnitMapper* mapper = NULL, + uint32_t flags = 0); /** Returns a shader that generates a radial gradient given the center and radius.

@@ -60,10 +68,11 @@ public: @param mode The tiling mode @param mapper May be NULL. Callback to modify the spread of the colors. */ - static SkShader* CreateRadial( const SkPoint& center, SkScalar radius, - const SkColor colors[], const SkScalar pos[], int count, - SkShader::TileMode mode, - SkUnitMapper* mapper = NULL); + static SkShader* CreateRadial(const SkPoint& center, SkScalar radius, + const SkColor colors[], const SkScalar pos[], int count, + SkShader::TileMode mode, + SkUnitMapper* mapper = NULL, + uint32_t flags = 0); /** Returns a shader that generates a radial gradient given the start position, start radius, end position and end radius.

@@ -92,7 +101,8 @@ public: const SkColor colors[], const SkScalar pos[], int count, SkShader::TileMode mode, - SkUnitMapper* mapper = NULL); + SkUnitMapper* mapper = NULL, + uint32_t flags = 0); /** * Returns a shader that generates a conical gradient given two circles, or @@ -101,13 +111,14 @@ public: * http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient */ static SkShader* CreateTwoPointConical(const SkPoint& start, - SkScalar startRadius, - const SkPoint& end, - SkScalar endRadius, - const SkColor colors[], - const SkScalar pos[], int count, - SkShader::TileMode mode, - SkUnitMapper* mapper = NULL); + SkScalar startRadius, + const SkPoint& end, + SkScalar endRadius, + const SkColor colors[], + const SkScalar pos[], int count, + SkShader::TileMode mode, + SkUnitMapper* mapper = NULL, + uint32_t flags = 0); /** Returns a shader that generates a sweep gradient given a center.

@@ -127,7 +138,8 @@ public: */ static SkShader* CreateSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], - int count, SkUnitMapper* mapper = NULL); + int count, SkUnitMapper* mapper = NULL, + uint32_t flags = 0); SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() }; diff --git a/gfx/skia/include/effects/SkKernel33MaskFilter.h b/gfx/skia/trunk/include/effects/SkKernel33MaskFilter.h similarity index 86% rename from gfx/skia/include/effects/SkKernel33MaskFilter.h rename to gfx/skia/trunk/include/effects/SkKernel33MaskFilter.h index 3404b73b1773..bcd9b26b8481 100644 --- a/gfx/skia/include/effects/SkKernel33MaskFilter.h +++ b/gfx/skia/trunk/include/effects/SkKernel33MaskFilter.h @@ -24,8 +24,8 @@ public: SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) protected: - SkKernel33ProcMaskFilter(SkFlattenableReadBuffer& rb); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkKernel33ProcMaskFilter(SkReadBuffer& rb); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: int fPercent256; @@ -53,8 +53,8 @@ private: int fKernel[3][3]; int fShift; - SkKernel33MaskFilter(SkFlattenableReadBuffer& rb); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkKernel33MaskFilter(SkReadBuffer& rb); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; typedef SkKernel33ProcMaskFilter INHERITED; }; diff --git a/gfx/skia/include/effects/SkLayerDrawLooper.h b/gfx/skia/trunk/include/effects/SkLayerDrawLooper.h similarity index 94% rename from gfx/skia/include/effects/SkLayerDrawLooper.h rename to gfx/skia/trunk/include/effects/SkLayerDrawLooper.h index cec78b7466cb..6955192b53f2 100644 --- a/gfx/skia/include/effects/SkLayerDrawLooper.h +++ b/gfx/skia/trunk/include/effects/SkLayerDrawLooper.h @@ -9,10 +9,10 @@ #define SkLayerDrawLooper_DEFINED #include "SkDrawLooper.h" +#include "SkPaint.h" +#include "SkPoint.h" #include "SkXfermode.h" -struct SkPoint; - class SK_API SkLayerDrawLooper : public SkDrawLooper { public: SK_DECLARE_INST_COUNT(SkLayerDrawLooper) @@ -99,6 +99,9 @@ public: */ void addLayer() { this->addLayer(0, 0); } + /// Similar to addLayer, but adds a layer to the top. + SkPaint* addLayerOnTop(const LayerInfo&); + // overrides from SkDrawLooper virtual void init(SkCanvas*); virtual bool next(SkCanvas*, SkPaint* paint); @@ -107,18 +110,17 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerDrawLooper) protected: - SkLayerDrawLooper(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkLayerDrawLooper(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: struct Rec { Rec* fNext; SkPaint fPaint; LayerInfo fInfo; - - static Rec* Reverse(Rec*); }; Rec* fRecs; + Rec* fTopRec; int fCount; // state-machine during the init/next cycle diff --git a/gfx/skia/include/effects/SkLayerRasterizer.h b/gfx/skia/trunk/include/effects/SkLayerRasterizer.h similarity index 91% rename from gfx/skia/include/effects/SkLayerRasterizer.h rename to gfx/skia/trunk/include/effects/SkLayerRasterizer.h index 65d1be0bc166..be81a2ba3def 100644 --- a/gfx/skia/include/effects/SkLayerRasterizer.h +++ b/gfx/skia/trunk/include/effects/SkLayerRasterizer.h @@ -35,8 +35,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLayerRasterizer) protected: - SkLayerRasterizer(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkLayerRasterizer(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // override from SkRasterizer virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix, diff --git a/gfx/skia/trunk/include/effects/SkLerpXfermode.h b/gfx/skia/trunk/include/effects/SkLerpXfermode.h new file mode 100644 index 000000000000..b6cc93fe0767 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkLerpXfermode.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkLerpXfermode_DEFINED +#define SkLerpXfermode_DEFINED + +#include "SkXfermode.h" + +class SK_API SkLerpXfermode : public SkXfermode { +public: + /** + * result = scale * src + (1 - scale) * dst + * + * When scale == 1, this is the same as kSrc_Mode + * When scale == 0, this is the same as kDst_Mode + */ + static SkXfermode* Create(SkScalar scale); + + // overrides from SkXfermode + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + + SK_DEVELOPER_TO_STRING() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLerpXfermode) + +protected: + SkLerpXfermode(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + +private: + SkLerpXfermode(unsigned scale256); + + unsigned fScale256; // 0..256 + + typedef SkXfermode INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkLightingImageFilter.h b/gfx/skia/trunk/include/effects/SkLightingImageFilter.h similarity index 68% rename from gfx/skia/include/effects/SkLightingImageFilter.h rename to gfx/skia/trunk/include/effects/SkLightingImageFilter.h index 5e9028d92ab4..4a76a9cd7e87 100644 --- a/gfx/skia/include/effects/SkLightingImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkLightingImageFilter.h @@ -5,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkLightingImageFilter_DEFINED #define SkLightingImageFilter_DEFINED @@ -18,23 +17,20 @@ public: SkPoint3(SkScalar x, SkScalar y, SkScalar z) : fX(x), fY(y), fZ(z) {} SkScalar dot(const SkPoint3& other) const { - return SkScalarMul(fX, other.fX) - + SkScalarMul(fY, other.fY) - + SkScalarMul(fZ, other.fZ); + return fX * other.fX + fY * other.fY + fZ * other.fZ; } SkScalar maxComponent() const { return fX > fY ? (fX > fZ ? fX : fZ) : (fY > fZ ? fY : fZ); } void normalize() { - SkScalar scale = SkScalarInvert(SkScalarSqrt(dot(*this))); - fX = SkScalarMul(fX, scale); - fY = SkScalarMul(fY, scale); - fZ = SkScalarMul(fZ, scale); + // Small epsilon is added to prevent division by 0. + SkScalar scale = SkScalarInvert(SkScalarSqrt(dot(*this)) + SK_ScalarNearlyZero); + fX = fX * scale; + fY = fY * scale; + fZ = fZ * scale; } SkPoint3 operator*(SkScalar scalar) const { - return SkPoint3(SkScalarMul(fX, scalar), - SkScalarMul(fY, scalar), - SkScalarMul(fZ, scalar)); + return SkPoint3(fX * scalar, fY * scalar, fZ * scalar); } SkPoint3 operator-(const SkPoint3& other) const { return SkPoint3(fX - other.fX, fY - other.fY, fZ - other.fZ); @@ -51,32 +47,35 @@ class SK_API SkLightingImageFilter : public SkImageFilter { public: static SkImageFilter* CreateDistantLitDiffuse(const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, - SkImageFilter* input = NULL); + SkImageFilter* input = NULL, const CropRect* cropRect = NULL); static SkImageFilter* CreatePointLitDiffuse(const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, - SkImageFilter* input = NULL); + SkImageFilter* input = NULL, const CropRect* cropRect = NULL); static SkImageFilter* CreateSpotLitDiffuse(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, - SkImageFilter* input = NULL); + SkImageFilter* input = NULL, const CropRect* cropRect = NULL); static SkImageFilter* CreateDistantLitSpecular(const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, - SkScalar shininess, SkImageFilter* input = NULL); + SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL); static SkImageFilter* CreatePointLitSpecular(const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, - SkScalar shininess, SkImageFilter* input = NULL); + SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL); static SkImageFilter* CreateSpotLitSpecular(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, - SkScalar shininess, SkImageFilter* input = NULL); + SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL); ~SkLightingImageFilter(); SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() protected: - SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input); - explicit SkLightingImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkLightingImageFilter(SkLight* light, + SkScalar surfaceScale, + SkImageFilter* input, + const CropRect* cropRect = NULL); + explicit SkLightingImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; const SkLight* light() const { return fLight; } SkScalar surfaceScale() const { return fSurfaceScale; } diff --git a/gfx/skia/trunk/include/effects/SkLumaColorFilter.h b/gfx/skia/trunk/include/effects/SkLumaColorFilter.h new file mode 100644 index 000000000000..6c57f7cc7513 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkLumaColorFilter.h @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkLumaColorFilter_DEFINED +#define SkLumaColorFilter_DEFINED + +#include "SkColorFilter.h" + +/** + * Luminance-to-alpha color filter, as defined in + * http://www.w3.org/TR/SVG/masking.html#Masking + * http://www.w3.org/TR/css-masking/#MaskValues + * + * The resulting color is black with transparency equal to the + * luminance value modulated by alpha: + * + * C' = [ Lum * a, 0, 0, 0 ] + * + */ +class SK_API SkLumaColorFilter : public SkColorFilter { +public: + static SkColorFilter* Create(); + + virtual void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const SK_OVERRIDE; + +#if SK_SUPPORT_GPU + virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE; +#endif + + SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;) + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLumaColorFilter) + +protected: + SkLumaColorFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + +private: + SkLumaColorFilter(); + + typedef SkColorFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkMagnifierImageFilter.h b/gfx/skia/trunk/include/effects/SkMagnifierImageFilter.h similarity index 77% rename from gfx/skia/include/effects/SkMagnifierImageFilter.h rename to gfx/skia/trunk/include/effects/SkMagnifierImageFilter.h index e01342695797..44f0d0d6898e 100644 --- a/gfx/skia/include/effects/SkMagnifierImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkMagnifierImageFilter.h @@ -16,16 +16,17 @@ class SK_API SkMagnifierImageFilter : public SkImageFilter { public: SkMagnifierImageFilter(SkRect srcRect, SkScalar inset); - virtual bool asNewEffect(GrEffectRef** effect, GrTexture* texture) const SK_OVERRIDE; - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMagnifierImageFilter) protected: - explicit SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + explicit SkMagnifierImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; + 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: SkRect fSrcRect; diff --git a/gfx/skia/include/effects/SkMatrixConvolutionImageFilter.h b/gfx/skia/trunk/include/effects/SkMatrixConvolutionImageFilter.h similarity index 62% rename from gfx/skia/include/effects/SkMatrixConvolutionImageFilter.h rename to gfx/skia/trunk/include/effects/SkMatrixConvolutionImageFilter.h index cd2a16fdfe3f..59af83e02527 100644 --- a/gfx/skia/include/effects/SkMatrixConvolutionImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkMatrixConvolutionImageFilter.h @@ -47,22 +47,34 @@ public: alpha is copied from the source image. @param input The input image filter. If NULL, the src bitmap passed to filterImage() is used instead. + @param cropRect The rectangle to which the output processing will be limited. */ - SkMatrixConvolutionImageFilter(const SkISize& kernelSize, const SkScalar* kernel, SkScalar gain, SkScalar bias, const SkIPoint& target, TileMode tileMode, bool convolveAlpha, SkImageFilter* input = NULL); + SkMatrixConvolutionImageFilter(const SkISize& kernelSize, + const SkScalar* kernel, + SkScalar gain, + SkScalar bias, + const SkIPoint& target, + TileMode tileMode, + bool convolveAlpha, + SkImageFilter* input = NULL, + const CropRect* cropRect = NULL); virtual ~SkMatrixConvolutionImageFilter(); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter) protected: - SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkMatrixConvolutionImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; #if SK_SUPPORT_GPU - virtual bool asNewEffect(GrEffectRef**, GrTexture*) const SK_OVERRIDE; + virtual bool asNewEffect(GrEffectRef** effect, + GrTexture*, + const SkMatrix& matrix, + const SkIRect& bounds) const SK_OVERRIDE; #endif private: @@ -76,11 +88,23 @@ private: typedef SkImageFilter INHERITED; template - void filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect); + void filterPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) const; template - void filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect); - void filterInteriorPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect); - void filterBorderPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect); + void filterPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) const; + void filterInteriorPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) const; + void filterBorderPixels(const SkBitmap& src, + SkBitmap* result, + const SkIRect& rect, + const SkIRect& bounds) const; }; #endif diff --git a/gfx/skia/include/effects/SkMergeImageFilter.h b/gfx/skia/trunk/include/effects/SkMergeImageFilter.h similarity index 79% rename from gfx/skia/include/effects/SkMergeImageFilter.h rename to gfx/skia/trunk/include/effects/SkMergeImageFilter.h index 8c4313dd13a8..36eaaf3df177 100755 --- a/gfx/skia/include/effects/SkMergeImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkMergeImageFilter.h @@ -15,21 +15,21 @@ class SK_API SkMergeImageFilter : public SkImageFilter { public: SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second, - SkXfermode::Mode = SkXfermode::kSrcOver_Mode); + SkXfermode::Mode = SkXfermode::kSrcOver_Mode, + const CropRect* cropRect = NULL); SkMergeImageFilter(SkImageFilter* filters[], int count, - const SkXfermode::Mode modes[] = NULL); + const SkXfermode::Mode modes[] = NULL, + const CropRect* cropRect = NULL); virtual ~SkMergeImageFilter(); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMergeImageFilter) protected: - SkMergeImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkMergeImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE; - + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; private: uint8_t* fModes; // SkXfermode::Mode diff --git a/gfx/skia/trunk/include/effects/SkMorphologyImageFilter.h b/gfx/skia/trunk/include/effects/SkMorphologyImageFilter.h new file mode 100644 index 000000000000..4d60180aeb67 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkMorphologyImageFilter.h @@ -0,0 +1,98 @@ +/* + * Copyright 2012 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkMorphologyImageFilter_DEFINED +#define SkMorphologyImageFilter_DEFINED + +#include "SkColor.h" +#include "SkImageFilter.h" +#include "SkSize.h" + +class SK_API SkMorphologyImageFilter : public SkImageFilter { +public: + SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect); + virtual void computeFastBounds(const SkRect& src, SkRect* dst) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst) const SK_OVERRIDE; + + /** + * 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 (*Proc)(const SkPMColor* src, SkPMColor* dst, int radius, + int width, int height, int srcStride, int dstStride); + +protected: + bool filterImageGeneric(Proc procX, Proc procY, + Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) const; + SkMorphologyImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; +#if SK_SUPPORT_GPU + virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; } + bool filterImageGPUGeneric(bool dilate, Proxy* proxy, const SkBitmap& src, + const SkMatrix& ctm, SkBitmap* result, + SkIPoint* offset) const; +#endif + + SkISize radius() const { return fRadius; } + +private: + SkISize fRadius; + typedef SkImageFilter INHERITED; +}; + +class SK_API SkDilateImageFilter : public SkMorphologyImageFilter { +public: + SkDilateImageFilter(int radiusX, int radiusY, + SkImageFilter* input = NULL, + const CropRect* cropRect = NULL) + : INHERITED(radiusX, radiusY, input, cropRect) {} + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; +#if SK_SUPPORT_GPU + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; +#endif + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter) + +protected: + SkDilateImageFilter(SkReadBuffer& buffer) : INHERITED(buffer) {} + +private: + typedef SkMorphologyImageFilter INHERITED; +}; + +class SK_API SkErodeImageFilter : public SkMorphologyImageFilter { +public: + SkErodeImageFilter(int radiusX, int radiusY, + SkImageFilter* input = NULL, + const CropRect* cropRect = NULL) + : INHERITED(radiusX, radiusY, input, cropRect) {} + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; +#if SK_SUPPORT_GPU + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; +#endif + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter) + +protected: + SkErodeImageFilter(SkReadBuffer& buffer) : INHERITED(buffer) {} + +private: + typedef SkMorphologyImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkOffsetImageFilter.h b/gfx/skia/trunk/include/effects/SkOffsetImageFilter.h similarity index 71% rename from gfx/skia/include/effects/SkOffsetImageFilter.h rename to gfx/skia/trunk/include/effects/SkOffsetImageFilter.h index 62b5fa6511f9..31eead3ded37 100644 --- a/gfx/skia/include/effects/SkOffsetImageFilter.h +++ b/gfx/skia/trunk/include/effects/SkOffsetImageFilter.h @@ -12,22 +12,24 @@ #include "SkPoint.h" class SK_API SkOffsetImageFilter : public SkImageFilter { + typedef SkImageFilter INHERITED; + public: - SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input = NULL); + SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input = NULL, + const CropRect* cropRect = NULL); + virtual void computeFastBounds(const SkRect& src, SkRect* dst) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOffsetImageFilter) protected: - SkOffsetImageFilter(SkFlattenableReadBuffer& buffer); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkOffsetImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, - SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE; + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const SK_OVERRIDE; private: SkVector fOffset; - - typedef SkImageFilter INHERITED; }; #endif diff --git a/gfx/skia/include/effects/SkPaintFlagsDrawFilter.h b/gfx/skia/trunk/include/effects/SkPaintFlagsDrawFilter.h similarity index 100% rename from gfx/skia/include/effects/SkPaintFlagsDrawFilter.h rename to gfx/skia/trunk/include/effects/SkPaintFlagsDrawFilter.h diff --git a/gfx/skia/trunk/include/effects/SkPerlinNoiseShader.h b/gfx/skia/trunk/include/effects/SkPerlinNoiseShader.h new file mode 100644 index 000000000000..dd89c7092595 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkPerlinNoiseShader.h @@ -0,0 +1,111 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPerlinNoiseShader_DEFINED +#define SkPerlinNoiseShader_DEFINED + +#include "SkShader.h" + +/** \class SkPerlinNoiseShader + + SkPerlinNoiseShader creates an image using the Perlin turbulence function. + + It can produce tileable noise if asked to stitch tiles and provided a tile size. + In order to fill a large area with repeating noise, set the stitchTiles flag to + true, and render exactly a single tile of noise. Without this flag, the result + will contain visible seams between tiles. + + The algorithm used is described here : + http://www.w3.org/TR/SVG/filters.html#feTurbulenceElement +*/ +class SK_API SkPerlinNoiseShader : public SkShader { + struct PaintingData; +public: + struct StitchData; + + /** + * About the noise types : the difference between the 2 is just minor tweaks to the algorithm, + * they're not 2 entirely different noises. The output looks different, but once the noise is + * generated in the [1, -1] range, the output is brought back in the [0, 1] range by doing : + * kFractalNoise_Type : noise * 0.5 + 0.5 + * kTurbulence_Type : abs(noise) + * Very little differences between the 2 types, although you can tell the difference visually. + */ + enum Type { + kFractalNoise_Type, + kTurbulence_Type, + kFirstType = kFractalNoise_Type, + kLastType = kTurbulence_Type + }; + /** + * This will construct Perlin noise of the given type (Fractal Noise or Turbulence). + * + * Both base frequencies (X and Y) have a usual range of (0..1). + * + * The number of octaves provided should be fairly small, although no limit is enforced. + * Each octave doubles the frequency, so 10 octaves would produce noise from + * baseFrequency * 1, * 2, * 4, ..., * 512, which quickly yields insignificantly small + * periods and resembles regular unstructured noise rather than Perlin noise. + * + * If tileSize isn't NULL or an empty size, the tileSize parameter will be used to modify + * the frequencies so that the noise will be tileable for the given tile size. If tileSize + * is NULL or an empty size, the frequencies will be used as is without modification. + */ + static SkShader* CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, + int numOctaves, SkScalar seed, + const SkISize* tileSize = NULL); + static SkShader* CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, + int numOctaves, SkScalar seed, + const SkISize* tileSize = NULL); + + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix); + virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; + + virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; + + SK_DEVELOPER_TO_STRING() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPerlinNoiseShader) + +protected: + SkPerlinNoiseShader(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + +private: + SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, SkScalar baseFrequencyX, + SkScalar baseFrequencyY, int numOctaves, SkScalar seed, + const SkISize* tileSize = NULL); + virtual ~SkPerlinNoiseShader(); + + void setTileSize(const SkISize&); + + void initPaint(PaintingData& paintingData); + + SkScalar noise2D(int channel, const PaintingData& paintingData, + const StitchData& stitchData, const SkPoint& noiseVector); + + SkScalar calculateTurbulenceValueForPoint(int channel, const PaintingData& paintingData, + StitchData& stitchData, const SkPoint& point); + + SkPMColor shade(const SkPoint& point, StitchData& stitchData); + + SkPerlinNoiseShader::Type fType; + SkScalar fBaseFrequencyX; + SkScalar fBaseFrequencyY; + int fNumOctaves; + SkScalar fSeed; + SkISize fTileSize; + bool fStitchTiles; + SkMatrix fMatrix; + + PaintingData* fPaintingData; + + typedef SkShader INHERITED; +}; + +#endif diff --git a/gfx/skia/trunk/include/effects/SkPictureImageFilter.h b/gfx/skia/trunk/include/effects/SkPictureImageFilter.h new file mode 100644 index 000000000000..a10d23eebb24 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkPictureImageFilter.h @@ -0,0 +1,48 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPictureImageFilter_DEFINED +#define SkPictureImageFilter_DEFINED + +#include "SkImageFilter.h" +#include "SkPicture.h" + +class SK_API SkPictureImageFilter : public SkImageFilter { +public: + /** + * Refs the passed-in picture. + */ + explicit SkPictureImageFilter(SkPicture* picture); + + /** + * Refs the passed-in picture. rect can be used to crop or expand the destination rect when + * the picture is drawn. (No scaling is implied by the dest rect; only the CTM is applied.) + */ + SkPictureImageFilter(SkPicture* picture, const SkRect& rect); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureImageFilter) + +protected: + virtual ~SkPictureImageFilter(); + /* Constructs an SkPictureImageFilter object from an SkReadBuffer. + * Note: If the SkPictureImageFilter object construction requires bitmap + * decoding, the decoder must be set on the SkReadBuffer parameter by calling + * SkReadBuffer::setBitmapDecoder() before calling this constructor. + * @param SkReadBuffer Serialized picture data. + */ + explicit SkPictureImageFilter(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; + +private: + SkPicture* fPicture; + SkRect fRect; + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkPixelXorXfermode.h b/gfx/skia/trunk/include/effects/SkPixelXorXfermode.h similarity index 88% rename from gfx/skia/include/effects/SkPixelXorXfermode.h rename to gfx/skia/trunk/include/effects/SkPixelXorXfermode.h index 5411b12d0514..9472d9426e3b 100644 --- a/gfx/skia/include/effects/SkPixelXorXfermode.h +++ b/gfx/skia/trunk/include/effects/SkPixelXorXfermode.h @@ -23,8 +23,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPixelXorXfermode) protected: - SkPixelXorXfermode(SkFlattenableReadBuffer& rb); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkPixelXorXfermode(SkReadBuffer& rb); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; // override from SkXfermode virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const; diff --git a/gfx/skia/include/effects/SkPorterDuff.h b/gfx/skia/trunk/include/effects/SkPorterDuff.h similarity index 98% rename from gfx/skia/include/effects/SkPorterDuff.h rename to gfx/skia/trunk/include/effects/SkPorterDuff.h index c5f549211d4c..e984e8e9b427 100644 --- a/gfx/skia/include/effects/SkPorterDuff.h +++ b/gfx/skia/trunk/include/effects/SkPorterDuff.h @@ -13,8 +13,6 @@ class SkXfermode; -/** DEPRECATED - use SkXfermode::Mode instead - */ class SK_API SkPorterDuff { public: /** List of predefined xfermodes. In general, the algebra for the modes @@ -76,6 +74,6 @@ public: /** Return the corersponding SkXfermode::Mode */ static SkXfermode::Mode ToXfermodeMode(Mode); -}; +} SK_ATTR_DEPRECATED("use SkXfermode::Mode"); #endif diff --git a/gfx/skia/trunk/include/effects/SkRectShaderImageFilter.h b/gfx/skia/trunk/include/effects/SkRectShaderImageFilter.h new file mode 100644 index 000000000000..23c538e6883b --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkRectShaderImageFilter.h @@ -0,0 +1,50 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkRectShaderImageFilter_DEFINED +#define SkRectShaderImageFilter_DEFINED + +#include "SkImageFilter.h" +#include "SkRect.h" + +class SkShader; + +class SK_API SkRectShaderImageFilter : public SkImageFilter { +public: + /** Create a new image filter which fills the given rectangle with pixels + * produced by the given SkShader. If no rectangle is specified, an output + * is produced with the same bounds as the input primitive (even though + * the input primitive's pixels are not used for processing). + * @param s Shader to call for processing. Cannot be NULL. Will be + * ref'ed by the new image filter. + * @param rect Rectangle of output pixels in which to apply the shader. + * If NULL or a given crop edge is not specified, the source + * primitive's bounds are used instead. + */ + SK_ATTR_DEPRECATED("use Create(SkShader*, const CropRect*)") + static SkRectShaderImageFilter* Create(SkShader* s, const SkRect& rect); + + static SkRectShaderImageFilter* Create(SkShader* s, const CropRect* rect = NULL); + virtual ~SkRectShaderImageFilter(); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter) + +protected: + SkRectShaderImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + +private: + SkRectShaderImageFilter(SkShader* s, const CropRect* rect); + SkShader* fShader; + + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/trunk/include/effects/SkResizeImageFilter.h b/gfx/skia/trunk/include/effects/SkResizeImageFilter.h new file mode 100644 index 000000000000..cc02a01d03e2 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkResizeImageFilter.h @@ -0,0 +1,51 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkResizeImageFilter_DEFINED +#define SkResizeImageFilter_DEFINED + +#include "SkImageFilter.h" +#include "SkScalar.h" +#include "SkRect.h" +#include "SkPoint.h" +#include "SkPaint.h" + +/*! \class SkResizeImageFilter + Resampling image filter. This filter draws its source image resampled using the given scale + values. + */ + +class SK_API SkResizeImageFilter : public SkImageFilter { +public: + /** Construct a (scaling-only) resampling image filter. + * @param sx The x scale parameter to apply when resizing. + * @param sy The y scale parameter to apply when resizing. + * @param filterLevel The quality of filtering to apply when scaling. + * @param input The input image filter. If NULL, the src bitmap + * passed to filterImage() is used instead. + */ + + SkResizeImageFilter(SkScalar sx, SkScalar sy, SkPaint::FilterLevel filterLevel, + SkImageFilter* input = NULL); + virtual ~SkResizeImageFilter(); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkResizeImageFilter) + +protected: + SkResizeImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + +private: + SkScalar fSx, fSy; + SkPaint::FilterLevel fFilterLevel; + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/effects/SkStippleMaskFilter.h b/gfx/skia/trunk/include/effects/SkStippleMaskFilter.h similarity index 94% rename from gfx/skia/include/effects/SkStippleMaskFilter.h rename to gfx/skia/trunk/include/effects/SkStippleMaskFilter.h index 8f6d20d9ca87..ee32ae1fe35e 100644 --- a/gfx/skia/include/effects/SkStippleMaskFilter.h +++ b/gfx/skia/trunk/include/effects/SkStippleMaskFilter.h @@ -31,7 +31,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkStippleMaskFilter); protected: - SkStippleMaskFilter(SkFlattenableReadBuffer& buffer) + SkStippleMaskFilter(SkReadBuffer& buffer) : SkMaskFilter(buffer) { } diff --git a/gfx/skia/include/effects/SkTableColorFilter.h b/gfx/skia/trunk/include/effects/SkTableColorFilter.h similarity index 100% rename from gfx/skia/include/effects/SkTableColorFilter.h rename to gfx/skia/trunk/include/effects/SkTableColorFilter.h diff --git a/gfx/skia/include/effects/SkTableMaskFilter.h b/gfx/skia/trunk/include/effects/SkTableMaskFilter.h similarity index 93% rename from gfx/skia/include/effects/SkTableMaskFilter.h rename to gfx/skia/trunk/include/effects/SkTableMaskFilter.h index ac33266f80c0..1c2bbd7a1b6c 100644 --- a/gfx/skia/include/effects/SkTableMaskFilter.h +++ b/gfx/skia/trunk/include/effects/SkTableMaskFilter.h @@ -51,8 +51,8 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTableMaskFilter) protected: - SkTableMaskFilter(SkFlattenableReadBuffer& rb); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkTableMaskFilter(SkReadBuffer& rb); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: uint8_t fTable[256]; diff --git a/gfx/skia/trunk/include/effects/SkTestImageFilters.h b/gfx/skia/trunk/include/effects/SkTestImageFilters.h new file mode 100755 index 000000000000..abbaa92593e1 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkTestImageFilters.h @@ -0,0 +1,27 @@ +#ifndef _SkTestImageFilters_h +#define _SkTestImageFilters_h + +#include "SkImageFilter.h" +#include "SkPoint.h" + +// Fun mode that scales down (only) and then scales back up to look pixelated +class SK_API SkDownSampleImageFilter : public SkImageFilter { +public: + SkDownSampleImageFilter(SkScalar scale) : INHERITED(0), fScale(scale) {} + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDownSampleImageFilter) + +protected: + SkDownSampleImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + +private: + SkScalar fScale; + + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/trunk/include/effects/SkTileImageFilter.h b/gfx/skia/trunk/include/effects/SkTileImageFilter.h new file mode 100644 index 000000000000..390e00c9a47a --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkTileImageFilter.h @@ -0,0 +1,40 @@ +/* + * 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 SkTileImageFilter_DEFINED +#define SkTileImageFilter_DEFINED + +#include "SkImageFilter.h" + +class SK_API SkTileImageFilter : public SkImageFilter { + typedef SkImageFilter INHERITED; + +public: + /** Tile image filter constructor + @param srcRect Defines the pixels to tile + @param dstRect Defines the pixels where tiles are drawn + @param input Input from which the subregion defined by srcRect will be tiled + */ + SkTileImageFilter(const SkRect& srcRect, const SkRect& dstRect, SkImageFilter* input) + : INHERITED(input), fSrcRect(srcRect), fDstRect(dstRect) {} + + virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE; + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTileImageFilter) + +protected: + explicit SkTileImageFilter(SkReadBuffer& buffer); + + virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + +private: + SkRect fSrcRect; + SkRect fDstRect; +}; + +#endif diff --git a/gfx/skia/include/effects/SkTransparentShader.h b/gfx/skia/trunk/include/effects/SkTransparentShader.h similarity index 92% rename from gfx/skia/include/effects/SkTransparentShader.h rename to gfx/skia/trunk/include/effects/SkTransparentShader.h index bee9a02d2d9f..2b3f99814aa2 100644 --- a/gfx/skia/include/effects/SkTransparentShader.h +++ b/gfx/skia/trunk/include/effects/SkTransparentShader.h @@ -29,7 +29,7 @@ private: const SkBitmap* fDevice; uint8_t fAlpha; - SkTransparentShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkTransparentShader(SkReadBuffer& buffer) : INHERITED(buffer) {} typedef SkShader INHERITED; }; diff --git a/gfx/skia/trunk/include/effects/SkXfermodeImageFilter.h b/gfx/skia/trunk/include/effects/SkXfermodeImageFilter.h new file mode 100644 index 000000000000..602dc4840493 --- /dev/null +++ b/gfx/skia/trunk/include/effects/SkXfermodeImageFilter.h @@ -0,0 +1,51 @@ +/* + * Copyright 2013 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkXfermodeImageFilter_DEFINED +#define SkXfermodeImageFilter_DEFINED + +#include "SkImageFilter.h" + +class SkBitmap; +class SkXfermode; + +class SK_API SkXfermodeImageFilter : public SkImageFilter { + /** + * This filter takes an xfermode, and uses it to composite the foreground + * over the background. If foreground or background is NULL, the input + * bitmap (src) is used instead. + */ + +public: + SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background, + SkImageFilter* foreground = NULL, const CropRect* cropRect = NULL); + + virtual ~SkXfermodeImageFilter(); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter) + + virtual bool onFilterImage(Proxy* proxy, + const SkBitmap& src, + const SkMatrix& ctm, + SkBitmap* dst, + SkIPoint* offset) const SK_OVERRIDE; +#if SK_SUPPORT_GPU + virtual bool canFilterImageGPU() const SK_OVERRIDE { return !cropRectIsSet(); } + virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; +#endif + +protected: + explicit SkXfermodeImageFilter(SkReadBuffer& buffer); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + +private: + SkXfermode* fMode; + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/gfx/skia/include/gpu/GrBackendEffectFactory.h b/gfx/skia/trunk/include/gpu/GrBackendEffectFactory.h similarity index 76% rename from gfx/skia/include/gpu/GrBackendEffectFactory.h rename to gfx/skia/trunk/include/gpu/GrBackendEffectFactory.h index 28114436de9b..d115a546474d 100644 --- a/gfx/skia/include/gpu/GrBackendEffectFactory.h +++ b/gfx/skia/trunk/include/gpu/GrBackendEffectFactory.h @@ -10,8 +10,8 @@ #include "GrTypes.h" #include "SkTemplates.h" -#include "SkThread_platform.h" -#include "GrNoncopyable.h" +#include "SkThread.h" +#include "SkTypes.h" /** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific effect object. Also tracks equivalence of shaders generated via a key. Each factory instance @@ -28,20 +28,20 @@ class GrGLEffect; class GrGLCaps; class GrDrawEffect; -class GrBackendEffectFactory : public GrNoncopyable { +class GrBackendEffectFactory : public SkNoncopyable { public: typedef uint32_t EffectKey; enum { kNoEffectKey = 0, - kEffectKeyBits = 15, + kEffectKeyBits = 10, /** - * Some aspects of the generated code may be determined by the particular textures that are - * associated with the effect. These manipulations are performed by GrGLShaderBuilder beyond - * GrGLEffects' control. So there is a dedicated part of the key which is combined - * automatically with the bits produced by GrGLEffect::GenKey(). + * The framework automatically includes coord transforms and texture accesses in their + * effect's EffectKey, so effects don't need to account for them in GenKey(). */ - kTextureKeyBits = 6, - kAttribKeyBits = 6 + kTextureKeyBits = 4, + kTransformKeyBits = 6, + kAttribKeyBits = 6, + kClassIDBits = 6 }; virtual EffectKey glEffectKey(const GrDrawEffect&, const GrGLCaps&) const = 0; @@ -56,6 +56,10 @@ public: virtual const char* name() const = 0; + static EffectKey GetTransformKey(EffectKey key) { + return key >> (kEffectKeyBits + kTextureKeyBits) & ((1U << kTransformKeyBits) - 1); + } + protected: enum { kIllegalEffectClassID = 0, @@ -67,13 +71,13 @@ protected: virtual ~GrBackendEffectFactory() {} static EffectKey GenID() { - GR_DEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) - + SkDEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) - kTextureKeyBits - kEffectKeyBits - kAttribKeyBits); // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The // atomic inc returns the old value not the incremented value. So we add // 1 to the returned value. int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1; - GrAssert(id < (1 << kClassIDBits)); + SkASSERT(id < (1 << kClassIDBits)); return static_cast(id); } diff --git a/gfx/skia/trunk/include/gpu/GrBitmapTextContext.h b/gfx/skia/trunk/include/gpu/GrBitmapTextContext.h new file mode 100755 index 000000000000..e0900ecd7d62 --- /dev/null +++ b/gfx/skia/trunk/include/gpu/GrBitmapTextContext.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrBitmapTextContext_DEFINED +#define GrBitmapTextContext_DEFINED + +#include "GrTextContext.h" + +class GrTextStrike; + +/* + * This class implements GrTextContext using standard bitmap fonts + */ +class GrBitmapTextContext : public GrTextContext { +public: + GrBitmapTextContext(GrContext*, const GrPaint&, SkColor); + virtual ~GrBitmapTextContext(); + + virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, + GrFontScaler*) SK_OVERRIDE; + +private: + GrContext::AutoMatrix fAutoMatrix; + GrTextStrike* fStrike; + + void flushGlyphs(); // automatically called by destructor + + enum { + kMinRequestedGlyphs = 1, + kDefaultRequestedGlyphs = 64, + kMinRequestedVerts = kMinRequestedGlyphs * 4, + kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, + }; + + SkColor fSkPaintColor; + SkPoint* fVertices; + int32_t fMaxVertices; + GrTexture* fCurrTexture; + int fCurrVertex; +}; + +#endif diff --git a/gfx/skia/include/gpu/GrClipData.h b/gfx/skia/trunk/include/gpu/GrClipData.h similarity index 94% rename from gfx/skia/include/gpu/GrClipData.h rename to gfx/skia/trunk/include/gpu/GrClipData.h index 078b61ec35cf..bced74183b30 100644 --- a/gfx/skia/include/gpu/GrClipData.h +++ b/gfx/skia/trunk/include/gpu/GrClipData.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,15 +5,13 @@ * found in the LICENSE file. */ - - #ifndef GrClip_DEFINED #define GrClip_DEFINED -#include "GrRect.h" #include "SkClipStack.h" class GrSurface; +struct SkIRect; /** * GrClipData encapsulates the information required to construct the clip @@ -50,7 +47,7 @@ public: } void getConservativeBounds(const GrSurface* surface, - GrIRect* devResult, + SkIRect* devResult, bool* isIntersectionOfRects = NULL) const; }; diff --git a/gfx/skia/include/gpu/GrColor.h b/gfx/skia/trunk/include/gpu/GrColor.h similarity index 84% rename from gfx/skia/include/gpu/GrColor.h rename to gfx/skia/trunk/include/gpu/GrColor.h index 43d932be0d81..cf7e7df8431b 100644 --- a/gfx/skia/include/gpu/GrColor.h +++ b/gfx/skia/trunk/include/gpu/GrColor.h @@ -35,10 +35,10 @@ typedef uint32_t GrColor; */ static inline GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a) { - GrAssert((uint8_t)r == r); - GrAssert((uint8_t)g == g); - GrAssert((uint8_t)b == b); - GrAssert((uint8_t)a == a); + SkASSERT((uint8_t)r == r); + SkASSERT((uint8_t)g == g); + SkASSERT((uint8_t)b == b); + SkASSERT((uint8_t)a == a); return (r << GrColor_SHIFT_R) | (g << GrColor_SHIFT_G) | (b << GrColor_SHIFT_B) | @@ -84,8 +84,25 @@ enum GrColorComponentFlags { kB_GrColorComponentFlag | kA_GrColorComponentFlag) }; +static inline char GrColorComponentFlagToChar(GrColorComponentFlags component) { + SkASSERT(GrIsPow2(component)); + switch (component) { + case kR_GrColorComponentFlag: + return 'r'; + case kG_GrColorComponentFlag: + return 'g'; + case kB_GrColorComponentFlag: + return 'b'; + case kA_GrColorComponentFlag: + return 'a'; + default: + GrCrash("Invalid color component flag."); + return '\0'; + } +} + static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) { - GrAssert(config >= 0 && config < kGrPixelConfigCnt); + SkASSERT(config >= 0 && config < kGrPixelConfigCnt); static const uint32_t kFlags[] = { 0, // kUnknown_GrPixelConfig kA_GrColorComponentFlag, // kAlpha_8_GrPixelConfig diff --git a/gfx/skia/include/gpu/GrConfig.h b/gfx/skia/trunk/include/gpu/GrConfig.h similarity index 59% rename from gfx/skia/include/gpu/GrConfig.h rename to gfx/skia/trunk/include/gpu/GrConfig.h index 856757b5474f..fc464c5038ba 100644 --- a/gfx/skia/include/gpu/GrConfig.h +++ b/gfx/skia/trunk/include/gpu/GrConfig.h @@ -32,85 +32,14 @@ * Gr defines are set to 0 or 1, rather than being undefined or defined */ -#if !defined(GR_ANDROID_BUILD) - #define GR_ANDROID_BUILD 0 -#endif -#if !defined(GR_IOS_BUILD) - #define GR_IOS_BUILD 0 -#endif -#if !defined(GR_LINUX_BUILD) - #define GR_LINUX_BUILD 0 -#endif -#if !defined(GR_MAC_BUILD) - #define GR_MAC_BUILD 0 -#endif -#if !defined(GR_WIN32_BUILD) - #define GR_WIN32_BUILD 0 -#endif -#if !defined(GR_QNX_BUILD) - #define GR_QNX_BUILD 0 -#endif #if !defined(GR_CACHE_STATS) #define GR_CACHE_STATS 0 #endif -/** - * If no build target has been defined, attempt to infer. - */ -#if !GR_ANDROID_BUILD && !GR_IOS_BUILD && !GR_LINUX_BUILD && !GR_MAC_BUILD && !GR_WIN32_BUILD && !GR_QNX_BUILD - #if defined(_WIN32) - #undef GR_WIN32_BUILD - #define GR_WIN32_BUILD 1 -// #error "WIN" - #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR - #undef GR_IOS_BUILD - #define GR_IOS_BUILD 1 -// #error "IOS" - #elif defined(SK_BUILD_FOR_ANDROID) - #undef GR_ANDROID_BUILD - #define GR_ANDROID_BUILD 1 -// #error "ANDROID" - #elif TARGET_OS_MAC - #undef GR_MAC_BUILD - #define GR_MAC_BUILD 1 -// #error "MAC" - #elif TARGET_OS_QNX || defined(__QNXNTO__) - #undef GR_QNX_BUILD - #define GR_QNX_BUILD 1 -// #error "QNX" - #else - #undef GR_LINUX_BUILD - #define GR_LINUX_BUILD 1 -// #error "LINUX" - #endif -#endif - -// we need both GR_DEBUG and GR_RELEASE to be defined as 0 or 1 -// -#ifndef GR_DEBUG - #ifdef GR_RELEASE - #define GR_DEBUG !GR_RELEASE - #else - #ifdef NDEBUG - #define GR_DEBUG 0 - #else - #define GR_DEBUG 1 - #endif - #endif -#endif - -#ifndef GR_RELEASE - #define GR_RELEASE !GR_DEBUG -#endif - -#if GR_DEBUG == GR_RELEASE - #error "GR_DEBUG and GR_RELEASE must not be the same" -#endif - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#if GR_WIN32_BUILD +#if defined(SK_BUILD_FOR_WIN32) // VC8 doesn't support stdint.h, so we define those types here. typedef signed char int8_t; typedef unsigned char uint8_t; @@ -142,8 +71,8 @@ typedef unsigned __int64 uint64_t; * A alternate user config file can be specified by defining * GR_USER_CONFIG_FILE. It should be defined relative to GrConfig.h * - * e.g. it can specify GR_DEBUG/GR_RELEASE as it please, change the BUILD - * target, or supply its own defines for anything else (e.g. GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT) + * e.g. it can change the BUILD target or supply its own defines for anything + * else (e.g. GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT) */ #if !defined(GR_USER_CONFIG_FILE) #include "GrUserConfig.h" @@ -157,36 +86,6 @@ typedef unsigned __int64 uint64_t; // postconfig section: // -// GR_IMPLEMENTATION should be define to 1 when building Gr and 0 when including -// it in another dependent build. The Gr makefile/ide-project should define this -// to 1. -#if !defined(GR_IMPLEMENTATION) - #define GR_IMPLEMENTATION 0 -#endif - -// If Gr is built as a shared library then GR_DLL should be defined to 1 (both -// when building Gr and when including its headers in dependent builds). Only -// currently supported minimally for Chrome's Win32 Multi-DLL build (TODO: -// correctly exort all of the public API correctly and support shared lib on -// other platforms). -#if !defined(GR_DLL) - #define GR_DLL 0 -#endif - -#if GR_DLL - #if GR_WIN32_BUILD - #if GR_IMPLEMENTATION - #define GR_API __declspec(dllexport) - #else - #define GR_API __declspec(dllimport) - #endif - #else - #define GR_API __attribute__((visibility("default"))) - #endif -#else - #define GR_API -#endif - // By now we must have a GR_..._BUILD symbol set to 1, and a decision about // debug -vs- release // @@ -228,7 +127,7 @@ typedef unsigned __int64 uint64_t; * GR_ALWAYSBREAK is an unconditional break in all builds. */ #if !defined(GR_ALWAYSBREAK) - #if GR_WIN32_BUILD + #if defined(SK_BUILD_FOR_WIN32) #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); __debugbreak() #else // TODO: do other platforms really not have continuable breakpoints? @@ -242,7 +141,7 @@ typedef unsigned __int64 uint64_t; * GR_DEBUGBREAK is an unconditional break in debug builds. */ #if !defined(GR_DEBUGBREAK) - #if GR_DEBUG + #ifdef SK_DEBUG #define GR_DEBUGBREAK GR_ALWAYSBREAK #else #define GR_DEBUGBREAK @@ -266,7 +165,7 @@ typedef unsigned __int64 uint64_t; * GR_DEBUGASSERT is an assertion in debug builds only. */ #if !defined(GR_DEBUGASSERT) - #if GR_DEBUG + #ifdef SK_DEBUG #define GR_DEBUGASSERT(COND) GR_ALWAYSASSERT(COND) #else #define GR_DEBUGASSERT(COND) @@ -276,25 +175,16 @@ typedef unsigned __int64 uint64_t; /** * Prettier forms of the above macros. */ -#define GrAssert(COND) GR_DEBUGASSERT(COND) #define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND) /** - * Crash from unrecoverable condition, optionally with a message. + * Crash from unrecoverable condition, optionally with a message. The debug variants only + * crash in a debug build. The message versions print the message regardless of release vs debug. */ inline void GrCrash() { GrAlwaysAssert(false); } inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } - -/** - * GR_DEBUGCODE compiles the code X in debug builds only - */ -#if !defined(GR_DEBUGCODE) - #if GR_DEBUG - #define GR_DEBUGCODE(X) X - #else - #define GR_DEBUGCODE(X) - #endif -#endif +inline void GrDebugCrash() { SkASSERT(false); } +inline void GrDebugCrash(const char* msg) { GrPrintf(msg); SkASSERT(false); } /** * GR_STATIC_ASSERT is a compile time assertion. Depending on the platform @@ -315,15 +205,6 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #endif #endif -/** - * GR_STATIC_RECT_VB controls whether rects are drawn by issuing a vertex - * for each corner or using a static vb that is positioned by modifying the - * view / texture matrix. - */ -#if !defined(GR_STATIC_RECT_VB) - #define GR_STATIC_RECT_VB 0 -#endif - /** * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should * lock a GrGeometryBuffer to update its contents. It will use lock() if the @@ -335,12 +216,21 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #endif /** - * GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT gives a threshold (in megabytes) for the + * GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT gives a threshold (in megabytes) for the * maximum size of the texture cache in vram. The value is only a default and * can be overridden at runtime. */ -#if !defined(GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT) - #define GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT 96 +#if !defined(GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT) + #define GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT 96 +#endif + +/** + * GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT specifies the maximum number of + * textures the texture cache can hold in vram. The value is only a default and + * can be overridden at runtime. + */ +#if !defined(GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT) + #define GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT 2048 #endif /** @@ -351,43 +241,4 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #define GR_STROKE_PATH_RENDERING 0 #endif -/////////////////////////////////////////////////////////////////////////////// -// tail section: -// -// Now we just assert if we are missing some required define, or if we detect -// and inconsistent combination of defines -// - - -/** - * Only one build target macro should be 1 and the rest should be 0. - */ -#define GR_BUILD_SUM (GR_WIN32_BUILD + GR_MAC_BUILD + GR_IOS_BUILD + GR_ANDROID_BUILD + GR_LINUX_BUILD + GR_QNX_BUILD) -#if 0 == GR_BUILD_SUM - #error "Missing a GR_BUILD define" -#elif 1 != GR_BUILD_SUM - #error "More than one GR_BUILD defined" -#endif - -#if 0 -#if GR_WIN32_BUILD -// #pragma message GR_WARN("GR_WIN32_BUILD") -#endif -#if GR_MAC_BUILD -// #pragma message GR_WARN("GR_MAC_BUILD") -#endif -#if GR_IOS_BUILD -// #pragma message GR_WARN("GR_IOS_BUILD") -#endif -#if GR_ANDROID_BUILD -// #pragma message GR_WARN("GR_ANDROID_BUILD") -#endif -#if GR_LINUX_BUILD -// #pragma message GR_WARN("GR_LINUX_BUILD") -#endif -#if GR_QNX_BUILD -// #pragma message GR_WARN("GR_QNX_BUILD") -#endif -#endif - #endif diff --git a/gfx/skia/include/gpu/GrContext.h b/gfx/skia/trunk/include/gpu/GrContext.h similarity index 84% rename from gfx/skia/include/gpu/GrContext.h rename to gfx/skia/trunk/include/gpu/GrContext.h index 4d328d13792b..ad3789b1a8ba 100644 --- a/gfx/skia/include/gpu/GrContext.h +++ b/gfx/skia/trunk/include/gpu/GrContext.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,20 +5,20 @@ * found in the LICENSE file. */ - #ifndef GrContext_DEFINED #define GrContext_DEFINED -#include "GrColor.h" -#include "GrAARectRenderer.h" #include "GrClipData.h" -#include "SkMatrix.h" +#include "GrColor.h" #include "GrPaint.h" #include "GrPathRendererChain.h" +#include "GrPoint.h" #include "GrRenderTarget.h" -#include "GrRefCnt.h" #include "GrTexture.h" +#include "SkMatrix.h" +#include "SkTypes.h" +class GrAARectRenderer; class GrAutoScratchTexture; class GrDrawState; class GrDrawTarget; @@ -30,17 +29,19 @@ class GrIndexBuffer; class GrIndexBufferAllocPool; class GrInOrderDrawBuffer; class GrOvalRenderer; +class GrPath; class GrPathRenderer; class GrResourceEntry; class GrResourceCache; class GrStencilBuffer; +class GrTestTarget; class GrTextureParams; class GrVertexBuffer; class GrVertexBufferAllocPool; class GrSoftwarePathRenderer; class SkStrokeRec; -class GR_API GrContext : public GrRefCnt { +class SK_API GrContext : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrContext) @@ -49,11 +50,6 @@ public: */ static GrContext* Create(GrBackend, GrBackendContext); - /** - * Returns the number of GrContext instances for the current thread. - */ - static int GetThreadInstanceCount(); - virtual ~GrContext(); /** @@ -61,8 +57,10 @@ public: * within the underlying 3D API's context/device/whatever. This call informs * the context that the state was modified and it should resend. Shouldn't * be called frequently for good performance. + * The flag bits, state, is dpendent on which backend is used by the + * context, either GL or D3D (possible in future). */ - void resetContext(); + void resetContext(uint32_t state = kAll_GrBackendState); /** * Callback function to allow classes to cleanup on GrContext destruction. @@ -129,11 +127,14 @@ public: * @param srcData Pointer to the pixel values. * @param rowBytes The number of bytes between rows of the texture. Zero * implies tightly packed rows. + * @param cacheKey (optional) If non-NULL, we'll write the cache key we used to cacheKey. */ GrTexture* createTexture(const GrTextureParams* params, const GrTextureDesc& desc, const GrCacheID& cacheID, - void* srcData, size_t rowBytes); + void* srcData, + size_t rowBytes, + GrResourceKey* cacheKey = NULL); /** * Search for an entry based on key and dimensions. If found, ref it and return it. The return @@ -208,6 +209,13 @@ public: */ void purgeCache(); + /** + * Purge all the unlocked resources from the cache. + * This entry point is mainly meant for timing texture uploads + * and is not defined in normal builds of Skia. + */ + void purgeAllUnlockedResources(); + /** * Creates a texture that is outside the cache. Does not count against * cache's budget. @@ -252,28 +260,39 @@ public: */ int getMaxTextureSize() const; + /** + * Temporarily override the true max texture size. Note: an override + * larger then the true max texture size will have no effect. + * This entry point is mainly meant for testing texture size dependent + * features and is only available if defined outside of Skia (see + * bleed GM. + */ + void setMaxTextureSizeOverride(int maxTextureSizeOverride); + /////////////////////////////////////////////////////////////////////////// // Render targets /** * Sets the render target. - * @param target the render target to set. (should not be NULL.) + * @param target the render target to set. */ - void setRenderTarget(GrRenderTarget* target); + void setRenderTarget(GrRenderTarget* target) { + fRenderTarget.reset(SkSafeRef(target)); + } /** * Gets the current render target. - * @return the currently bound render target. Should never be NULL. + * @return the currently bound render target. */ - const GrRenderTarget* getRenderTarget() const; - GrRenderTarget* getRenderTarget(); + const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); } + GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); } GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; } /** * Can the provided configuration act as a color render target? */ - bool isConfigRenderable(GrPixelConfig config) const; + bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const; /** * Return the max width or height of a render target supported by the @@ -321,25 +340,25 @@ public: * Gets the current transformation matrix. * @return the current matrix. */ - const SkMatrix& getMatrix() const; + const SkMatrix& getMatrix() const { return fViewMatrix; } /** * Sets the transformation matrix. * @param m the matrix to set. */ - void setMatrix(const SkMatrix& m); + void setMatrix(const SkMatrix& m) { fViewMatrix = m; } /** * Sets the current transformation matrix to identity. */ - void setIdentityMatrix(); + void setIdentityMatrix() { fViewMatrix.reset(); } /** * Concats the current matrix. The passed matrix is applied before the * current matrix. * @param m the matrix to concat. */ - void concatMatrix(const SkMatrix& m) const; + void concatMatrix(const SkMatrix& m) { fViewMatrix.preConcat(m); } /////////////////////////////////////////////////////////////////////////// @@ -348,13 +367,13 @@ public: * Gets the current clip. * @return the current clip. */ - const GrClipData* getClip() const; + const GrClipData* getClip() const { return fClip; } /** * Sets the clip. * @param clipData the clip to set. */ - void setClip(const GrClipData* clipData); + void setClip(const GrClipData* clipData) { fClip = clipData; } /////////////////////////////////////////////////////////////////////////// // Draws @@ -363,10 +382,12 @@ public: * Clear the entire or rect of the render target, ignoring any clips. * @param rect the rect to clear or the whole thing if rect is NULL. * @param color the color to clear to. + * @param canIgnoreRect allows partial clears to be converted to whole + * clears on platforms for which that is cheap * @param target if non-NULL, the render target to clear otherwise clear * the current render target */ - void clear(const GrIRect* rect, GrColor color, + void clear(const SkIRect* rect, GrColor color, bool canIgnoreRect, GrRenderTarget* target = NULL); /** @@ -377,17 +398,18 @@ public: /** * Draw the rect using a paint. * @param paint describes how to color pixels. - * @param strokeWidth If strokeWidth < 0, then the rect is filled, else - * the rect is mitered stroked based on strokeWidth. If - * strokeWidth == 0, then the stroke is always a single - * pixel thick. + * @param stroke the stroke information (width, join, cap). + * If stroke == NULL, then the rect is filled. + * Otherwise, if stroke width == 0, then the stroke + * is always a single pixel thick, else the rect is + * mitered/beveled stroked based on stroke width. * @param matrix Optional matrix applied to the rect. Applied before * context's matrix or the paint's matrix. * The rects coords are used to access the paint (through texture matrix) */ void drawRect(const GrPaint& paint, - const GrRect&, - SkScalar strokeWidth = -1, + const SkRect&, + const SkStrokeRec* stroke = NULL, const SkMatrix* matrix = NULL); /** @@ -404,11 +426,22 @@ public: * @param localMatrix Optional matrix to transform localRect. */ void drawRectToRect(const GrPaint& paint, - const GrRect& dstRect, - const GrRect& localRect, + const SkRect& dstRect, + const SkRect& localRect, const SkMatrix* dstMatrix = NULL, const SkMatrix* localMatrix = NULL); + /** + * Draw a roundrect using a paint. + * + * @param paint describes how to color pixels. + * @param rrect the roundrect to draw + * @param stroke the stroke information (width, join, cap) + */ + void drawRRect(const GrPaint& paint, + const SkRRect& rrect, + const SkStrokeRec& stroke); + /** * Draws a path. * @@ -451,7 +484,7 @@ public: * @param stroke the stroke information (width, style) */ void drawOval(const GrPaint& paint, - const GrRect& oval, + const SkRect& oval, const SkStrokeRec& stroke); /////////////////////////////////////////////////////////////////////////// @@ -461,14 +494,6 @@ public: * Flags that affect flush() behavior. */ enum FlushBits { - /** - * A client may want Gr to bind a GrRenderTarget in the 3D API so that - * it can be rendered to directly. However, Gr lazily sets state. Simply - * calling setRenderTarget() followed by flush() without flags may not - * bind the render target. This flag forces the context to bind the last - * set render target in the 3D API. - */ - kForceCurrentRenderTarget_FlushBit = 0x1, /** * A client may reach a point where it has partially rendered a frame * through a GrContext that it knows the user will never see. This flag @@ -612,43 +637,31 @@ public: */ void resolveRenderTarget(GrRenderTarget* target); - /** - * Applies a 2D Gaussian blur to a given texture. - * @param srcTexture The source texture to be blurred. - * @param canClobberSrc If true, srcTexture may be overwritten, and - * may be returned as the result. - * @param rect The destination rectangle. - * @param sigmaX The blur's standard deviation in X. - * @param sigmaY The blur's standard deviation in Y. - * @return the blurred texture, which may be srcTexture reffed, or a - * new texture. It is the caller's responsibility to unref this texture. - */ - GrTexture* gaussianBlur(GrTexture* srcTexture, - bool canClobberSrc, - const SkRect& rect, - float sigmaX, float sigmaY); +#ifdef SK_DEVELOPER + void dumpFontCache() const; +#endif /////////////////////////////////////////////////////////////////////////// // Helpers - class AutoRenderTarget : public ::GrNoncopyable { + class AutoRenderTarget : public ::SkNoncopyable { public: AutoRenderTarget(GrContext* context, GrRenderTarget* target) { fPrevTarget = context->getRenderTarget(); - GrSafeRef(fPrevTarget); + SkSafeRef(fPrevTarget); context->setRenderTarget(target); fContext = context; } AutoRenderTarget(GrContext* context) { fPrevTarget = context->getRenderTarget(); - GrSafeRef(fPrevTarget); + SkSafeRef(fPrevTarget); fContext = context; } ~AutoRenderTarget() { if (NULL != fContext) { fContext->setRenderTarget(fPrevTarget); } - GrSafeUnref(fPrevTarget); + SkSafeUnref(fPrevTarget); } private: GrContext* fContext; @@ -669,7 +682,7 @@ public: * paint if necessary. Hint: use SkTCopyOnFirstWrite if the AutoMatrix is conditionally * initialized. */ - class AutoMatrix : GrNoncopyable { + class AutoMatrix : public ::SkNoncopyable { public: AutoMatrix() : fContext(NULL) {} @@ -679,7 +692,7 @@ public: * Initializes by pre-concat'ing the context's current matrix with the preConcat param. */ void setPreConcat(GrContext* context, const SkMatrix& preConcat, GrPaint* paint = NULL) { - GrAssert(NULL != context); + SkASSERT(NULL != context); this->restore(); @@ -693,7 +706,7 @@ public: * update a paint but the matrix cannot be inverted. */ bool setIdentity(GrContext* context, GrPaint* paint = NULL) { - GrAssert(NULL != context); + SkASSERT(NULL != context); this->restore(); @@ -762,7 +775,7 @@ public: SkMatrix fMatrix; }; - class AutoClip : GrNoncopyable { + class AutoClip : public ::SkNoncopyable { public: // This enum exists to require a caller of the constructor to acknowledge that the clip will // initially be wide open. It also could be extended if there are other desirable initial @@ -773,14 +786,14 @@ public: AutoClip(GrContext* context, InitialClip initialState) : fContext(context) { - GrAssert(kWideOpen_InitialClip == initialState); + SkASSERT(kWideOpen_InitialClip == initialState); fNewClipData.fClipStack = &fNewClipStack; fOldClip = context->getClip(); context->setClip(&fNewClipData); } - AutoClip(GrContext* context, const GrRect& newClipRect) + AutoClip(GrContext* context, const SkRect& newClipRect) : fContext(context) , fNewClipStack(newClipRect) { fNewClipData.fClipStack = &fNewClipStack; @@ -809,7 +822,7 @@ public: , fAutoRT(ctx, rt) { fAutoMatrix.setIdentity(ctx); // should never fail with no paint param. - GrAssert(fAutoMatrix.succeeded()); + SkASSERT(fAutoMatrix.succeeded()); } private: @@ -823,9 +836,12 @@ public: GrGpu* getGpu() { return fGpu; } const GrGpu* getGpu() const { return fGpu; } GrFontCache* getFontCache() { return fFontCache; } - GrDrawTarget* getTextTarget(const GrPaint& paint); + GrDrawTarget* getTextTarget(); const GrIndexBuffer* getQuadIndexBuffer() const; + // Called by tests that draw directly to the context via GrDrawTarget + void getTestTarget(GrTestTarget*); + /** * Stencil buffers add themselves to the cache using addStencilBuffer. findStencilBuffer is * called to check the cache for a SB that matches an RT's criteria. @@ -841,6 +857,7 @@ public: GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType, GrPathRendererChain::StencilSupport* stencilSupport = NULL); + #if GR_CACHE_STATS void printCacheStats() const; #endif @@ -853,56 +870,65 @@ private: }; BufferedDraw fLastDrawWasBuffered; - GrGpu* fGpu; - GrDrawState* fDrawState; + GrGpu* fGpu; + SkMatrix fViewMatrix; + SkAutoTUnref fRenderTarget; + const GrClipData* fClip; // TODO: make this ref counted + GrDrawState* fDrawState; - GrResourceCache* fTextureCache; - GrFontCache* fFontCache; + GrResourceCache* fTextureCache; + GrFontCache* fFontCache; - GrPathRendererChain* fPathRendererChain; - GrSoftwarePathRenderer* fSoftwarePathRenderer; + GrPathRendererChain* fPathRendererChain; + GrSoftwarePathRenderer* fSoftwarePathRenderer; - GrVertexBufferAllocPool* fDrawBufferVBAllocPool; - GrIndexBufferAllocPool* fDrawBufferIBAllocPool; - GrInOrderDrawBuffer* fDrawBuffer; + GrVertexBufferAllocPool* fDrawBufferVBAllocPool; + GrIndexBufferAllocPool* fDrawBufferIBAllocPool; + GrInOrderDrawBuffer* fDrawBuffer; - GrAARectRenderer* fAARectRenderer; - GrOvalRenderer* fOvalRenderer; + // Set by OverbudgetCB() to request that GrContext flush before exiting a draw. + bool fFlushToReduceCacheSize; - bool fDidTestPMConversions; - int fPMToUPMConversion; - int fUPMToPMConversion; + GrAARectRenderer* fAARectRenderer; + GrOvalRenderer* fOvalRenderer; + + bool fDidTestPMConversions; + int fPMToUPMConversion; + int fUPMToPMConversion; struct CleanUpData { PFCleanUpFunc fFunc; void* fInfo; }; - SkTDArray fCleanUpData; + SkTDArray fCleanUpData; + + int fMaxTextureSizeOverride; GrContext(); // init must be called after the constructor. bool init(GrBackend, GrBackendContext); void setupDrawBuffer(); - void flushDrawBuffer(); - + class AutoRestoreEffects; + class AutoCheckFlush; /// Sets the paint and returns the target to draw into. The paint can be NULL in which case the /// draw state is left unmodified. - GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw); + GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw, AutoRestoreEffects*, AutoCheckFlush*); - void internalDrawPath(GrDrawTarget* target, const GrPaint& paint, const SkPath& path, + void internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path, const SkStrokeRec& stroke); GrTexture* createResizedTexture(const GrTextureDesc& desc, const GrCacheID& cacheID, void* srcData, size_t rowBytes, - bool needsFiltering); + bool filter); // Needed so GrTexture's returnToCache helper function can call // addExistingTextureToCache friend class GrTexture; + friend class GrStencilAndCoverPathRenderer; // Add an existing texture to the texture cache. This is intended solely // for use with textures released from an GrAutoScratchTexture. @@ -920,14 +946,29 @@ private: bool swapRAndB, const SkMatrix& matrix); - typedef GrRefCnt INHERITED; + /** + * This callback allows the resource cache to callback into the GrContext + * when the cache is still overbudget after a purge. + */ + static bool OverbudgetCB(void* data); + + /** Creates a new gpu path, based on the specified path and stroke and returns it. + * The caller owns a ref on the returned path which must be balanced by a call to unref. + * + * @param skPath the path geometry. + * @param stroke the path stroke. + * @return a new path or NULL if the operation is not supported by the backend. + */ + GrPath* createPath(const SkPath& skPath, const SkStrokeRec& stroke); + + typedef SkRefCnt INHERITED; }; /** * Gets and locks a scratch texture from a descriptor using either exact or approximate criteria. * Unlocks texture in the destructor. */ -class GrAutoScratchTexture : ::GrNoncopyable { +class GrAutoScratchTexture : public ::SkNoncopyable { public: GrAutoScratchTexture() : fContext(NULL) @@ -967,6 +1008,9 @@ public: * returned texture. */ GrTexture* detach() { + if (NULL == fTexture) { + return NULL; + } GrTexture* texture = fTexture; fTexture = NULL; @@ -974,10 +1018,10 @@ public: // The cache also has a ref which we are lending to the caller of detach(). When the caller // lets go of the ref and the ref count goes to 0 internal_dispose will see this flag is // set and re-ref the texture, thereby restoring the cache's ref. - GrAssert(texture->getRefCnt() > 1); + SkASSERT(texture->getRefCnt() > 1); texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit); texture->unref(); - GrAssert(NULL != texture->getCacheEntry()); + SkASSERT(NULL != texture->getCacheEntry()); return texture; } diff --git a/gfx/skia/include/gpu/GrContextFactory.h b/gfx/skia/trunk/include/gpu/GrContextFactory.h similarity index 78% rename from gfx/skia/include/gpu/GrContextFactory.h rename to gfx/skia/trunk/include/gpu/GrContextFactory.h index 3d9f1a386dd7..333afd29f6b7 100644 --- a/gfx/skia/include/gpu/GrContextFactory.h +++ b/gfx/skia/trunk/include/gpu/GrContextFactory.h @@ -26,12 +26,15 @@ * GrContexts backed by different types of GL contexts. It manages creating the * GL context and a GrContext that uses it. The GL/Gr contexts persist until the * factory is destroyed (though the caller can always grab a ref on the returned - * GrContext to make it outlive the factory). + * Gr and GL contexts to make them outlive the factory). */ -class GrContextFactory : GrNoncopyable { +class GrContextFactory : public SkNoncopyable { public: /** - * Types of GL contexts supported. + * Types of GL contexts supported. For historical and testing reasons the native GrContext will + * not use "GL_NV_path_rendering" even when the driver supports it. There is a separate context + * type that does not remove NVPR support and which will fail when the driver does not support + * the extension. */ enum GLContextType { kNative_GLContextType, @@ -41,6 +44,9 @@ public: #if SK_MESA kMESA_GLContextType, #endif + /** Similar to kNative but does not filter NVPR. It will fail if the GL driver does not + support NVPR */ + kNVPR_GLContextType, kNull_GLContextType, kDebug_GLContextType, @@ -73,6 +79,8 @@ public: case kMESA_GLContextType: return "mesa"; #endif + case kNVPR_GLContextType: + return "nvpr"; case kDebug_GLContextType: return "debug"; default: @@ -87,6 +95,7 @@ public: void destroyContexts() { for (int i = 0; i < fContexts.count(); ++i) { + fContexts[i].fGLContext->makeCurrent(); fContexts[i].fGrContext->unref(); fContexts[i].fGLContext->unref(); } @@ -107,6 +116,7 @@ public: SkAutoTUnref glCtx; SkAutoTUnref grCtx; switch (type) { + case kNVPR_GLContextType: // fallthru case kNative_GLContextType: glCtx.reset(SkNEW(SkNativeGLContext)); break; @@ -134,7 +144,22 @@ public: if (!glCtx.get()->init(kBogusSize, kBogusSize)) { return NULL; } - GrBackendContext p3dctx = reinterpret_cast(glCtx.get()->gl()); + + // Ensure NVPR is available for the NVPR type and block it from other types. + SkAutoTUnref glInterface(SkRef(glCtx.get()->gl())); + if (kNVPR_GLContextType == type) { + if (!glInterface->hasExtension("GL_NV_path_rendering")) { + return NULL; + } + } else { + glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface)); + if (!glInterface) { + return NULL; + } + } + + glCtx->makeCurrent(); + GrBackendContext p3dctx = reinterpret_cast(glInterface.get()); grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx)); if (!grCtx.get()) { return NULL; diff --git a/gfx/skia/trunk/include/gpu/GrCoordTransform.h b/gfx/skia/trunk/include/gpu/GrCoordTransform.h new file mode 100644 index 000000000000..14e2620e44b1 --- /dev/null +++ b/gfx/skia/trunk/include/gpu/GrCoordTransform.h @@ -0,0 +1,119 @@ +/* + * 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 GrCoordTransform_DEFINED +#define GrCoordTransform_DEFINED + +#include "GrEffect.h" +#include "SkMatrix.h" +#include "GrTexture.h" +#include "GrTypes.h" + +/** + * Coordinates available to GrEffect subclasses for requesting transformations. Transformed + * coordinates are made available in the the portion of fragment shader emitted by the effect. + */ +enum GrCoordSet { + /** + * The user-space coordinates that map to the fragment being rendered. These coords account for + * any change of coordinate system done on the CPU by GrContext before rendering, and also are + * correct for draws that take explicit local coords rather than inferring them from the + * primitive's positions (e.g. drawVertices). These are usually the coords a GrEffect wants. + */ + kLocal_GrCoordSet, + + /** + * The actual vertex position. Note that GrContext may not draw using the original view matrix + * specified by the caller, as it may have transformed vertices into another space. These are + * usually not the coordinates a GrEffect wants. + */ + kPosition_GrCoordSet +}; + +/** + * A class representing a linear transformation from one of the built-in coordinate sets (local or + * position). GrEffects just define these transformations, and the framework does the rest of the + * work to make the transformed coordinates available in their fragment shader. + */ +class GrCoordTransform : public SkNoncopyable { +public: + GrCoordTransform() { SkDEBUGCODE(fInEffect = false); } + + /** + * Create a transformation that maps [0, 1] to a texture's boundaries. + */ + GrCoordTransform(GrCoordSet sourceCoords, const GrTexture* texture) { + SkDEBUGCODE(fInEffect = false); + this->reset(sourceCoords, texture); + } + + /** + * Create a transformation from a matrix. The optional texture parameter is used to infer if the + * framework should internally do a y reversal to account for it being upside down by Skia's + * coord convention. + */ + GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) { + SkDEBUGCODE(fInEffect = false); + this->reset(sourceCoords, m, texture); + } + + void reset(GrCoordSet sourceCoords, const GrTexture* texture) { + SkASSERT(!fInEffect); + SkASSERT(NULL != texture); + this->reset(sourceCoords, GrEffect::MakeDivByTextureWHMatrix(texture), texture); + } + + void reset(GrCoordSet sourceCoords, const SkMatrix& m, const GrTexture* texture = NULL) { + SkASSERT(!fInEffect); + fSourceCoords = sourceCoords; + fMatrix = m; + fReverseY = NULL != texture && kBottomLeft_GrSurfaceOrigin == texture->origin(); + } + + GrCoordTransform& operator= (const GrCoordTransform& other) { + SkASSERT(!fInEffect); + fSourceCoords = other.fSourceCoords; + fMatrix = other.fMatrix; + fReverseY = other.fReverseY; + return *this; + } + + /** + * Access the matrix for editing. Note, this must be done before adding the transform to an + * effect, since effects are immutable. + */ + SkMatrix* accessMatrix() { + SkASSERT(!fInEffect); + return &fMatrix; + } + + bool operator== (const GrCoordTransform& other) const { + return fSourceCoords == other.fSourceCoords && + fMatrix.cheapEqualTo(other.fMatrix) && + fReverseY == other.fReverseY; + } + + GrCoordSet sourceCoords() const { return fSourceCoords; } + const SkMatrix& getMatrix() const { return fMatrix; } + bool reverseY() const { return fReverseY; } + +private: + GrCoordSet fSourceCoords; + SkMatrix fMatrix; + bool fReverseY; + + typedef SkNoncopyable INHERITED; + +#ifdef SK_DEBUG +public: + void setInEffect() const { fInEffect = true; } +private: + mutable bool fInEffect; +#endif +}; + +#endif diff --git a/gfx/skia/trunk/include/gpu/GrDistanceFieldTextContext.h b/gfx/skia/trunk/include/gpu/GrDistanceFieldTextContext.h new file mode 100755 index 000000000000..217faf3cb021 --- /dev/null +++ b/gfx/skia/trunk/include/gpu/GrDistanceFieldTextContext.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef 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 GrPaint&, SkColor, SkScalar textRatio); + virtual ~GrDistanceFieldTextContext(); + + virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, + GrFontScaler*) SK_OVERRIDE; + +private: + GrTextStrike* fStrike; + SkScalar fTextRatio; + + void flushGlyphs(); // automatically called by destructor + + enum { + kMinRequestedGlyphs = 1, + kDefaultRequestedGlyphs = 64, + kMinRequestedVerts = kMinRequestedGlyphs * 4, + kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4, + }; + + SkColor fSkPaintColor; + SkPoint* fVertices; + int32_t fMaxVertices; + GrTexture* fCurrTexture; + int fCurrVertex; +}; + +#endif diff --git a/gfx/skia/include/gpu/GrDrawEffect.h b/gfx/skia/trunk/include/gpu/GrDrawEffect.h similarity index 88% rename from gfx/skia/include/gpu/GrDrawEffect.h rename to gfx/skia/trunk/include/gpu/GrDrawEffect.h index 005de417eee6..9a7a75d55f6c 100644 --- a/gfx/skia/include/gpu/GrDrawEffect.h +++ b/gfx/skia/trunk/include/gpu/GrDrawEffect.h @@ -14,16 +14,15 @@ * The typical use case is that sometime after an effect was installed a decision was made to draw * in device coordinates (i.e. use an identity view-matrix). In such a case the GrDrawEffect's * coord-change-matrix would be the inverse of the view matrix that was set when the effect was - * installed. GrGLEffectMatrix is a handy class that implements a local coordinate matrix that - * automatically accounts for the coord-change matrix. + * installed. */ class GrDrawEffect { public: GrDrawEffect(const GrEffectStage& stage, bool explicitLocalCoords) : fEffectStage(&stage) , fExplicitLocalCoords(explicitLocalCoords) { - GrAssert(NULL != fEffectStage); - GrAssert(NULL != fEffectStage->getEffect()); + SkASSERT(NULL != fEffectStage); + SkASSERT(NULL != fEffectStage->getEffect()); } const GrEffectRef* effect() const { return fEffectStage->getEffect(); } diff --git a/gfx/skia/include/gpu/GrEffect.h b/gfx/skia/trunk/include/gpu/GrEffect.h similarity index 58% rename from gfx/skia/include/gpu/GrEffect.h rename to gfx/skia/trunk/include/gpu/GrEffect.h index 08f34e0364bc..5fed5329fb3a 100644 --- a/gfx/skia/include/gpu/GrEffect.h +++ b/gfx/skia/trunk/include/gpu/GrEffect.h @@ -10,15 +10,15 @@ #include "GrColor.h" #include "GrEffectUnitTest.h" -#include "GrNoncopyable.h" -#include "GrRefCnt.h" #include "GrTexture.h" #include "GrTextureAccess.h" #include "GrTypesPriv.h" class GrBackendEffectFactory; class GrContext; +class GrCoordTransform; class GrEffect; +class GrVertexEffect; class SkString; /** @@ -27,10 +27,15 @@ class SkString; * GrEffectRef ref count reaches zero the scratch GrResources owned by the effect can be recycled * in service of later draws. However, the deferred draw queue may still own direct references to * the underlying GrEffect. + * + * GrEffectRefs created by new are placed in a per-thread managed pool. The pool is destroyed when + * the thread ends. Therefore, all dynamically allocated GrEffectRefs must be unreffed before thread + * termination. */ class GrEffectRef : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrEffectRef); + virtual ~GrEffectRef(); GrEffect* get() { return fEffect; } const GrEffect* get() const { return fEffect; } @@ -41,13 +46,18 @@ public: void* operator new(size_t size); void operator delete(void* target); + void* operator new(size_t size, void* placement) { + return ::operator new(size, placement); + } + void operator delete(void* target, void* placement) { + ::operator delete(target, placement); + } + private: friend class GrEffect; // to construct these explicit GrEffectRef(GrEffect* effect); - virtual ~GrEffectRef(); - GrEffect* fEffect; typedef SkRefCnt INHERITED; @@ -63,27 +73,17 @@ private: There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static member function of a GrEffect subclass. - Because almost no code should ever handle a GrEffect outside of a GrEffectRef, we privately - inherit from GrRefCnt to help prevent accidental direct ref'ing/unref'ing of effects. + Because almost no code should ever handle a GrEffect directly outside of a GrEffectRef, we + privately inherit from SkRefCnt to help prevent accidental direct ref'ing/unref'ing of effects. + + Dynamically allocated GrEffects and their corresponding GrEffectRefs are managed by a per-thread + memory pool. The ref count of an effect must reach 0 before the thread terminates and the pool + is destroyed. To create a static effect use the macro GR_CREATE_STATIC_EFFECT declared below. */ -class GrEffect : private GrRefCnt { +class GrEffect : private SkRefCnt { public: SK_DECLARE_INST_COUNT(GrEffect) - /** - * The types of vertex coordinates available to an effect in the vertex shader. Effects can - * require their own vertex attribute but these coordinates are made available by the framework - * in all programs. kCustom_CoordsType is provided to signify that an alternative set of coords - * is used (usually an explicit vertex attribute) but its meaning is determined by the effect - * subclass. - */ - enum CoordsType { - kLocal_CoordsType, - kPosition_CoordsType, - - kCustom_CoordsType, - }; - virtual ~GrEffect(); /** @@ -95,6 +95,9 @@ public: */ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0; + /** Will this effect read the source color value? */ + bool willUseInputColor() const { return fWillUseInputColor; } + /** This object, besides creating back-end-specific helper objects, is used for run-time-type- identification. The factory should be an instance of templated class, GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have @@ -129,6 +132,12 @@ public: in generated shader code. */ const char* name() const; + int numTransforms() const { return fCoordTransforms.count(); } + + /** Returns the coordinate transformation at index. index must be valid according to + numTransforms(). */ + const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; } + int numTextures() const { return fTextureAccesses.count(); } /** Returns the access pattern for the texture at index. index must be valid according to @@ -139,9 +148,19 @@ public: GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); } /** Will this effect read the destination pixel value? */ - bool willReadDst() const { return fWillReadDst; } + bool willReadDstColor() const { return fWillReadDstColor; } - int numVertexAttribs() const { return fVertexAttribTypes.count(); } + /** Will this effect read the fragment position? */ + bool willReadFragmentPosition() const { return fWillReadFragmentPosition; } + + /** Will this effect emit custom vertex shader code? + (To set this value the effect must inherit from GrVertexEffect.) */ + bool hasVertexCode() const { return fHasVertexCode; } + + int numVertexAttribs() const { + SkASSERT(0 == fVertexAttribTypes.count() || fHasVertexCode); + return fVertexAttribTypes.count(); + } GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; } @@ -150,7 +169,7 @@ public: /** Useful for effects that want to insert a texture matrix that is implied by the texture dimensions */ static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) { - GrAssert(NULL != texture); + SkASSERT(NULL != texture); SkMatrix mat; mat.setIDiv(texture->width(), texture->height()); return mat; @@ -159,6 +178,13 @@ public: void* operator new(size_t size); void operator delete(void* target); + void* operator new(size_t size, void* placement) { + return ::operator new(size, placement); + } + void operator delete(void* target, void* placement) { + ::operator delete(target, placement); + } + /** These functions are used when recording effects into a deferred drawing queue. The inc call keeps the effect alive outside of GrEffectRef while allowing any resources owned by the effect to be returned to the cache for reuse. The dec call must balance the inc call. */ @@ -178,21 +204,29 @@ public: } protected: + /** + * Subclasses call this from their constructor to register coordinate transformations. The + * effect subclass manages the lifetime of the transformations (this function only stores a + * pointer). The GrCoordTransform is typically a member field of the GrEffect subclass. When the + * matrix has perspective, the transformed coordinates will have 3 components. Otherwise they'll + * have 2. This must only be called from the constructor because GrEffects are immutable. + */ + void addCoordTransform(const GrCoordTransform* coordTransform); + /** * Subclasses call this from their constructor to register GrTextureAccesses. The effect - * subclass manages the lifetime of the accesses (this function only stores a pointer). This - * must only be called from the constructor because GrEffects are immutable. + * subclass manages the lifetime of the accesses (this function only stores a pointer). The + * GrTextureAccess is typically a member field of the GrEffect subclass. This must only be + * called from the constructor because GrEffects are immutable. */ void addTextureAccess(const GrTextureAccess* textureAccess); - /** - * Subclasses call this from their constructor to register vertex attributes (at most - * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are - * immutable. - */ - void addVertexAttrib(GrSLType type); - - GrEffect() : fWillReadDst(false), fEffectRef(NULL) {} + GrEffect() + : fWillReadDstColor(false) + , fWillReadFragmentPosition(false) + , fWillUseInputColor(true) + , fHasVertexCode(false) + , fEffectRef(NULL) {} /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for an example factory function. */ @@ -209,6 +243,14 @@ protected: return CreateEffectRef(const_cast(effect)); } + /** Used by GR_CREATE_STATIC_EFFECT below */ + static GrEffectRef* CreateStaticEffectRef(void* refStorage, GrEffect* effect) { + SkASSERT(NULL == effect->fEffectRef); + effect->fEffectRef = SkNEW_PLACEMENT_ARGS(refStorage, GrEffectRef, (effect)); + return effect->fEffectRef; + } + + /** Helper used in subclass factory functions to unref the effect after it has been wrapped in a GrEffectRef. E.g.: @@ -240,7 +282,21 @@ protected: * from its constructor. Otherwise, when its generated backend-specific effect class attempts * to generate code that reads the destination pixel it will fail. */ - void setWillReadDst() { fWillReadDst = true; } + void setWillReadDstColor() { fWillReadDstColor = true; } + + /** + * If the effect will generate a backend-specific effect that will read the fragment position + * in the FS then it must call this method from its constructor. Otherwise, the request to + * access the fragment position will be denied. + */ + void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } + + /** + * If the effect will generate a result that does not depend on the input color value then it must + * call this function from its constructor. Otherwise, when its generated backend-specific code + * might fail during variable binding due to unused variables. + */ + void setWillNotUseInputColor() { fWillUseInputColor = false; } private: bool isEqual(const GrEffect& other) const { @@ -248,17 +304,16 @@ private: return false; } bool result = this->onIsEqual(other); -#if GR_DEBUG +#ifdef SK_DEBUG if (result) { - GrAssert(this->numTextures() == other.numTextures()); - for (int i = 0; i < this->numTextures(); ++i) { - GrAssert(*fTextureAccesses[i] == *other.fTextureAccesses[i]); - } + this->assertEquality(other); } #endif return result; } + SkDEBUGCODE(void assertEquality(const GrEffect& other) const;) + /** Subclass implements this to support isEqual(). It will only be called if it is known that the two effects are of the same subclass (i.e. they return the same object from getFactory()).*/ @@ -266,23 +321,45 @@ private: void EffectRefDestroyed() { fEffectRef = NULL; } - friend class GrEffectRef; // to call EffectRefDestroyed() - friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage - // from deferred state, to call isEqual on naked GrEffects, and - // to inc/dec deferred ref counts. + friend class GrEffectRef; // to call EffectRefDestroyed() + friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage + // from deferred state, to call isEqual on naked GrEffects, and + // to inc/dec deferred ref counts. + friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttribTypes. + SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; SkSTArray fVertexAttribTypes; - bool fWillReadDst; + bool fWillReadDstColor; + bool fWillReadFragmentPosition; + bool fWillUseInputColor; + bool fHasVertexCode; GrEffectRef* fEffectRef; - typedef GrRefCnt INHERITED; + typedef SkRefCnt INHERITED; }; inline GrEffectRef::GrEffectRef(GrEffect* effect) { - GrAssert(NULL != effect); + SkASSERT(NULL != effect); effect->ref(); fEffect = effect; } +/** + * This creates an effect outside of the effect memory pool. The effect's destructor will be called + * at global destruction time. NAME will be the name of the created GrEffectRef. + */ +#define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS) \ +enum { \ + k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8), \ + k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef) \ +}; \ +static SkAlignedSStorage g_##NAME##_Storage; \ +static void* NAME##_RefLocation = (char*)g_##NAME##_Storage.get() + k_##NAME##_EffectRefOffset; \ +static GrEffect* NAME##_Effect SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS);\ +static SkAutoTDestroy NAME##_ad(NAME##_Effect); \ +static GrEffectRef* NAME(GrEffect::CreateStaticEffectRef(NAME##_RefLocation, NAME##_Effect)); \ +static SkAutoTDestroy NAME##_Ref_ad(NAME) + + #endif diff --git a/gfx/skia/trunk/include/gpu/GrEffectStage.h b/gfx/skia/trunk/include/gpu/GrEffectStage.h new file mode 100644 index 000000000000..8b6cb11dfc6b --- /dev/null +++ b/gfx/skia/trunk/include/gpu/GrEffectStage.h @@ -0,0 +1,223 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#ifndef GrEffectStage_DEFINED +#define GrEffectStage_DEFINED + +#include "GrBackendEffectFactory.h" +#include "GrEffect.h" +#include "SkMatrix.h" +#include "GrTypes.h" + +#include "SkShader.h" + +class GrEffectStage { +public: + explicit GrEffectStage(const GrEffectRef* effectRef, int attrIndex0 = -1, int attrIndex1 = -1) + : fEffectRef(SkRef(effectRef)) { + fCoordChangeMatrixSet = false; + fVertexAttribIndices[0] = attrIndex0; + fVertexAttribIndices[1] = attrIndex1; + } + + GrEffectStage(const GrEffectStage& other) { + *this = other; + } + + class DeferredStage; + // This constructor balances DeferredStage::saveFrom(). + explicit GrEffectStage(const DeferredStage& deferredStage) { + deferredStage.restoreTo(this); + } + + GrEffectStage& operator= (const GrEffectStage& other) { + fCoordChangeMatrixSet = other.fCoordChangeMatrixSet; + if (other.fCoordChangeMatrixSet) { + fCoordChangeMatrix = other.fCoordChangeMatrix; + } + fEffectRef.reset(SkRef(other.fEffectRef.get())); + memcpy(fVertexAttribIndices, other.fVertexAttribIndices, sizeof(fVertexAttribIndices)); + return *this; + } + + bool operator== (const GrEffectStage& other) const { + SkASSERT(NULL != fEffectRef.get()); + SkASSERT(NULL != other.fEffectRef.get()); + + if (!(*this->getEffect())->isEqual(*other.getEffect())) { + return false; + } + + if (fCoordChangeMatrixSet != other.fCoordChangeMatrixSet) { + return false; + } + + if (!fCoordChangeMatrixSet) { + return true; + } + + return fCoordChangeMatrix == other.fCoordChangeMatrix; + } + + bool operator!= (const GrEffectStage& s) const { return !(*this == s); } + + /** + * This is called when the coordinate system in which the geometry is specified will change. + * + * @param matrix The transformation from the old coord system in which geometry is specified + * to the new one from which it will actually be drawn. + */ + void localCoordChange(const SkMatrix& matrix) { + if (fCoordChangeMatrixSet) { + fCoordChangeMatrix.preConcat(matrix); + } else { + fCoordChangeMatrixSet = true; + fCoordChangeMatrix = matrix; + } + } + + class SavedCoordChange { + private: + bool fCoordChangeMatrixSet; + SkMatrix fCoordChangeMatrix; + SkDEBUGCODE(mutable SkAutoTUnref fEffectRef;) + + friend class GrEffectStage; + }; + + /** + * This gets the current coordinate system change. It is the accumulation of + * localCoordChange calls since the effect was installed. It is used when then caller + * wants to temporarily change the source geometry coord system, draw something, and then + * restore the previous coord system (e.g. temporarily draw in device coords). + */ + void saveCoordChange(SavedCoordChange* savedCoordChange) const { + savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet; + if (fCoordChangeMatrixSet) { + savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix; + } + SkASSERT(NULL == savedCoordChange->fEffectRef.get()); + SkDEBUGCODE(SkRef(fEffectRef.get());) + SkDEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef.get());) + } + + /** + * This balances the saveCoordChange call. + */ + void restoreCoordChange(const SavedCoordChange& savedCoordChange) { + fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet; + if (fCoordChangeMatrixSet) { + fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix; + } + SkASSERT(savedCoordChange.fEffectRef.get() == fEffectRef); + SkDEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);) + } + + /** + * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its + * GrEffect to be recycled through the cache. + */ + class DeferredStage { + public: + DeferredStage() : fEffect(NULL) { + SkDEBUGCODE(fInitialized = false;) + } + + ~DeferredStage() { + if (NULL != fEffect) { + fEffect->decDeferredRefCounts(); + } + } + + void saveFrom(const GrEffectStage& stage) { + SkASSERT(!fInitialized); + SkASSERT(NULL != stage.fEffectRef.get()); + stage.fEffectRef->get()->incDeferredRefCounts(); + fEffect = stage.fEffectRef->get(); + fCoordChangeMatrixSet = stage.fCoordChangeMatrixSet; + if (fCoordChangeMatrixSet) { + fCoordChangeMatrix = stage.fCoordChangeMatrix; + } + fVertexAttribIndices[0] = stage.fVertexAttribIndices[0]; + fVertexAttribIndices[1] = stage.fVertexAttribIndices[1]; + SkDEBUGCODE(fInitialized = true;) + } + + void restoreTo(GrEffectStage* stage) const { + SkASSERT(fInitialized); + stage->fEffectRef.reset(GrEffect::CreateEffectRef(fEffect)); + stage->fCoordChangeMatrixSet = fCoordChangeMatrixSet; + if (fCoordChangeMatrixSet) { + stage->fCoordChangeMatrix = fCoordChangeMatrix; + } + stage->fVertexAttribIndices[0] = fVertexAttribIndices[0]; + stage->fVertexAttribIndices[1] = fVertexAttribIndices[1]; + } + + bool isEqual(const GrEffectStage& stage, bool ignoreCoordChange) const { + if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0] || + fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) { + return false; + } + + if (!(*stage.getEffect())->isEqual(*fEffect)) { + return false; + } + + if (ignoreCoordChange) { + // ignore the coordinate change matrix since there are + // explicit uv coordinates + return true; + } + + if (fCoordChangeMatrixSet != stage.fCoordChangeMatrixSet) { + return false; + } + + if (!fCoordChangeMatrixSet) { + return true; + } + + return fCoordChangeMatrix == stage.fCoordChangeMatrix; + } + + private: + const GrEffect* fEffect; + bool fCoordChangeMatrixSet; + SkMatrix fCoordChangeMatrix; + int fVertexAttribIndices[2]; + SkDEBUGCODE(bool fInitialized;) + }; + + /** + * Gets the matrix representing all changes of coordinate system since the GrEffect was + * installed in the stage. + */ + const SkMatrix& getCoordChangeMatrix() const { + if (fCoordChangeMatrixSet) { + return fCoordChangeMatrix; + } else { + return SkMatrix::I(); + } + } + + const GrEffectRef* getEffect() const { return fEffectRef.get(); } + + const int* getVertexAttribIndices() const { return fVertexAttribIndices; } + int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); } + +private: + bool fCoordChangeMatrixSet; + SkMatrix fCoordChangeMatrix; + SkAutoTUnref fEffectRef; + int fVertexAttribIndices[2]; +}; + +#endif diff --git a/gfx/skia/include/gpu/GrEffectUnitTest.h b/gfx/skia/trunk/include/gpu/GrEffectUnitTest.h similarity index 89% rename from gfx/skia/include/gpu/GrEffectUnitTest.h rename to gfx/skia/trunk/include/gpu/GrEffectUnitTest.h index 557602fd5df9..850db9ba34dc 100644 --- a/gfx/skia/include/gpu/GrEffectUnitTest.h +++ b/gfx/skia/trunk/include/gpu/GrEffectUnitTest.h @@ -8,9 +8,9 @@ #ifndef GrEffectUnitTest_DEFINED #define GrEffectUnitTest_DEFINED -#include "GrNoncopyable.h" #include "SkRandom.h" #include "SkTArray.h" +#include "SkTypes.h" class SkMatrix; class GrDrawTargetCaps; @@ -25,7 +25,7 @@ enum { /** * A helper for use in GrEffect::TestCreate functions. */ -const SkMatrix& TestMatrix(SkMWCRandom*); +const SkMatrix& TestMatrix(SkRandom*); } @@ -35,10 +35,10 @@ class GrContext; class GrEffectRef; class GrTexture; -class GrEffectTestFactory : GrNoncopyable { +class GrEffectTestFactory : public SkNoncopyable { public: - typedef GrEffectRef* (*CreateProc)(SkMWCRandom*, + typedef GrEffectRef* (*CreateProc)(SkRandom*, GrContext*, const GrDrawTargetCaps& caps, GrTexture* dummyTextures[]); @@ -48,7 +48,7 @@ public: GetFactories()->push_back(this); } - static GrEffectRef* CreateStage(SkMWCRandom* random, + static GrEffectRef* CreateStage(SkRandom* random, GrContext* context, const GrDrawTargetCaps& caps, GrTexture* dummyTextures[]) { @@ -67,14 +67,14 @@ private: */ #define GR_DECLARE_EFFECT_TEST \ static GrEffectTestFactory gTestFactory; \ - static GrEffectRef* TestCreate(SkMWCRandom*, \ + static GrEffectRef* TestCreate(SkRandom*, \ GrContext*, \ const GrDrawTargetCaps&, \ GrTexture* dummyTextures[2]) /** GrEffect subclasses should insert this macro in their implementation file. They must then * also implement this static function: - * GrEffect* TestCreate(SkMWCRandom*, + * GrEffect* TestCreate(SkRandom*, * GrContext*, * const GrDrawTargetCaps&, * GrTexture* dummyTextures[2]); @@ -91,7 +91,7 @@ private: // The unit test relies on static initializers. Just declare the TestCreate function so that // its definitions will compile. #define GR_DECLARE_EFFECT_TEST \ - static GrEffectRef* TestCreate(SkMWCRandom*, \ + static GrEffectRef* TestCreate(SkRandom*, \ GrContext*, \ const GrDrawTargetCaps&, \ GrTexture* dummyTextures[2]) diff --git a/gfx/skia/include/gpu/GrFontScaler.h b/gfx/skia/trunk/include/gpu/GrFontScaler.h similarity index 86% rename from gfx/skia/include/gpu/GrFontScaler.h rename to gfx/skia/trunk/include/gpu/GrFontScaler.h index e3a7a2ac7234..e51c4ac9a508 100644 --- a/gfx/skia/include/gpu/GrFontScaler.h +++ b/gfx/skia/trunk/include/gpu/GrFontScaler.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,8 +5,6 @@ * found in the LICENSE file. */ - - #ifndef GrFontScaler_DEFINED #define GrFontScaler_DEFINED @@ -23,19 +20,19 @@ class SkPath; * The client is responsible for subclassing, and instantiating this. The * instance is create for a specific font+size+matrix. */ -class GrFontScaler : public GrRefCnt { +class GrFontScaler : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrFontScaler) virtual const GrKey* getKey() = 0; virtual GrMaskFormat getMaskFormat() = 0; - virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0; + virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds) = 0; virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, int rowBytes, void* image) = 0; virtual bool getGlyphPath(uint16_t glyphID, SkPath*) = 0; private: - typedef GrRefCnt INHERITED; + typedef SkRefCnt INHERITED; }; #endif diff --git a/gfx/skia/include/gpu/GrGlyph.h b/gfx/skia/trunk/include/gpu/GrGlyph.h similarity index 93% rename from gfx/skia/include/gpu/GrGlyph.h rename to gfx/skia/trunk/include/gpu/GrGlyph.h index 4945f2a58a75..fe4c835773c3 100644 --- a/gfx/skia/include/gpu/GrGlyph.h +++ b/gfx/skia/trunk/include/gpu/GrGlyph.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,15 +5,13 @@ * found in the LICENSE file. */ - - #ifndef GrGlyph_DEFINED #define GrGlyph_DEFINED #include "GrRect.h" #include "SkPath.h" -class GrAtlas; +class GrPlot; /* Need this to be quad-state: - complete w/ image @@ -25,14 +22,14 @@ class GrAtlas; struct GrGlyph { typedef uint32_t PackedID; - GrAtlas* fAtlas; + GrPlot* fPlot; SkPath* fPath; PackedID fPackedID; GrIRect16 fBounds; GrIPoint16 fAtlasLocation; - void init(GrGlyph::PackedID packed, const GrIRect& bounds) { - fAtlas = NULL; + void init(GrGlyph::PackedID packed, const SkIRect& bounds) { + fPlot = NULL; fPath = NULL; fPackedID = packed; fBounds.set(bounds); diff --git a/gfx/skia/include/gpu/GrKey.h b/gfx/skia/trunk/include/gpu/GrKey.h similarity index 89% rename from gfx/skia/include/gpu/GrKey.h rename to gfx/skia/trunk/include/gpu/GrKey.h index 80eb537ca405..e9d6feb45318 100644 --- a/gfx/skia/include/gpu/GrKey.h +++ b/gfx/skia/trunk/include/gpu/GrKey.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,14 +5,10 @@ * found in the LICENSE file. */ - - #ifndef GrKey_DEFINED #define GrKey_DEFINED -#include "GrRefCnt.h" - -class GrKey : public GrRefCnt { +class GrKey : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrKey) @@ -37,7 +32,7 @@ protected: private: const Hash fHash; - typedef GrRefCnt INHERITED; + typedef SkRefCnt INHERITED; }; #endif diff --git a/gfx/skia/include/gpu/GrPaint.h b/gfx/skia/trunk/include/gpu/GrPaint.h similarity index 50% rename from gfx/skia/include/gpu/GrPaint.h rename to gfx/skia/trunk/include/gpu/GrPaint.h index 25ec69976284..50a32a5743a5 100644 --- a/gfx/skia/include/gpu/GrPaint.h +++ b/gfx/skia/trunk/include/gpu/GrPaint.h @@ -43,11 +43,6 @@ */ class GrPaint { public: - enum { - kMaxColorStages = 3, - kMaxCoverageStages = 1, - }; - GrPaint() { this->reset(); } GrPaint(const GrPaint& paint) { *this = paint; } @@ -90,84 +85,49 @@ public: bool isDither() const { return fDither; } /** - * Enables a SkXfermode::Mode-based color filter applied to the primitive color. The constant - * color passed to this function is considered the "src" color and the primitive's color is - * considered the "dst" color. Defaults to kDst_Mode which equates to simply passing through - * the primitive color unmodified. + * Appends an additional color effect to the color computation. */ - void setXfermodeColorFilter(SkXfermode::Mode mode, GrColor color) { - fColorFilterColor = color; - fColorFilterXfermode = mode; - } - SkXfermode::Mode getColorFilterMode() const { return fColorFilterXfermode; } - GrColor getColorFilterColor() const { return fColorFilterColor; } - - /** - * Disables the SkXfermode::Mode color filter. - */ - void resetColorFilter() { - fColorFilterXfermode = SkXfermode::kDst_Mode; - fColorFilterColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); - } - - /** - * Specifies a stage of the color pipeline. Usually the texture matrices of color stages apply - * to the primitive's positions. Some GrContext calls take explicit coords as an array or a - * rect. In this case these are the pre-matrix coords to colorStage(0). - */ - GrEffectStage* colorStage(int i) { - GrAssert((unsigned)i < kMaxColorStages); - return fColorStages + i; - } - - const GrEffectStage& getColorStage(int i) const { - GrAssert((unsigned)i < kMaxColorStages); - return fColorStages[i]; - } - - bool isColorStageEnabled(int i) const { - GrAssert((unsigned)i < kMaxColorStages); - return (NULL != fColorStages[i].getEffect()); - } - - /** - * Specifies a stage of the coverage pipeline. Coverage stages' texture matrices are always - * applied to the primitive's position, never to explicit texture coords. - */ - GrEffectStage* coverageStage(int i) { - GrAssert((unsigned)i < kMaxCoverageStages); - return fCoverageStages + i; - } - - const GrEffectStage& getCoverageStage(int i) const { - GrAssert((unsigned)i < kMaxCoverageStages); - return fCoverageStages[i]; - } - - bool isCoverageStageEnabled(int i) const { - GrAssert((unsigned)i < kMaxCoverageStages); - return (NULL != fCoverageStages[i].getEffect()); - } - - bool hasCoverageStage() const { - for (int i = 0; i < kMaxCoverageStages; ++i) { - if (this->isCoverageStageEnabled(i)) { - return true; - } + const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { + SkASSERT(NULL != effect); + if (!(*effect)->willUseInputColor()) { + fColorStages.reset(); } - return false; + SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1)); + return effect; } - bool hasColorStage() const { - for (int i = 0; i < kMaxColorStages; ++i) { - if (this->isColorStageEnabled(i)) { - return true; - } + /** + * Appends an additional coverage effect to the coverage computation. + */ + const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { + SkASSERT(NULL != effect); + if (!(*effect)->willUseInputColor()) { + fCoverageStages.reset(); } - return false; + SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1)); + return effect; } - bool hasStage() const { return this->hasColorStage() || this->hasCoverageStage(); } + /** + * Helpers for adding color or coverage effects that sample a texture. The matrix is applied + * to the src space position to compute texture coordinates. + */ + void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix); + void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix); + + void addColorTextureEffect(GrTexture* texture, + const SkMatrix& matrix, + const GrTextureParams& params); + void addCoverageTextureEffect(GrTexture* texture, + const SkMatrix& matrix, + const GrTextureParams& params); + + int numColorStages() const { return fColorStages.count(); } + int numCoverageStages() const { return fCoverageStages.count(); } + int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); } + + const GrEffectStage& getColorStage(int s) const { return fColorStages[s]; } + const GrEffectStage& getCoverageStage(int s) const { return fCoverageStages[s]; } GrPaint& operator=(const GrPaint& paint) { fSrcBlendCoeff = paint.fSrcBlendCoeff; @@ -178,19 +138,9 @@ public: fColor = paint.fColor; fCoverage = paint.fCoverage; - fColorFilterColor = paint.fColorFilterColor; - fColorFilterXfermode = paint.fColorFilterXfermode; + fColorStages = paint.fColorStages; + fCoverageStages = paint.fCoverageStages; - for (int i = 0; i < kMaxColorStages; ++i) { - if (paint.isColorStageEnabled(i)) { - fColorStages[i] = paint.fColorStages[i]; - } - } - for (int i = 0; i < kMaxCoverageStages; ++i) { - if (paint.isCoverageStageEnabled(i)) { - fCoverageStages[i] = paint.fCoverageStages[i]; - } - } return *this; } @@ -203,67 +153,70 @@ public: this->resetColor(); this->resetCoverage(); this->resetStages(); - this->resetColorFilter(); } - // internal use - // GrPaint's textures and masks map to the first N stages - // of GrDrawTarget in that order (textures followed by masks) - enum { - kFirstColorStage = 0, - kFirstCoverageStage = kMaxColorStages, - kTotalStages = kFirstColorStage + kMaxColorStages + kMaxCoverageStages, - }; + /** + * Determines whether the drawing with this paint is opaque with respect to both color blending + * and fractional coverage. It does not consider whether AA has been enabled on the paint or + * not. Depending upon whether multisampling or coverage-based AA is in use, AA may make the + * result only apply to the interior of primitives. + * + */ + bool isOpaque() const; + + /** + * Returns true if isOpaque would return true and the paint represents a solid constant color + * draw. If the result is true, constantColor will be updated to contain the constant color. + */ + bool isOpaqueAndConstantColor(GrColor* constantColor) const; private: + + /** + * Helper for isOpaque and isOpaqueAndConstantColor. + */ + bool getOpaqueAndKnownColor(GrColor* solidColor, uint32_t* solidColorKnownComponents) const; + /** * Called when the source coord system from which geometry is rendered changes. It ensures that * the local coordinates seen by effects remains unchanged. oldToNew gives the transformation * from the previous coord system to the new coord system. */ void localCoordChange(const SkMatrix& oldToNew) { - for (int i = 0; i < kMaxColorStages; ++i) { - if (this->isColorStageEnabled(i)) { - fColorStages[i].localCoordChange(oldToNew); - } + for (int i = 0; i < fColorStages.count(); ++i) { + fColorStages[i].localCoordChange(oldToNew); } - for (int i = 0; i < kMaxCoverageStages; ++i) { - if (this->isCoverageStageEnabled(i)) { - fCoverageStages[i].localCoordChange(oldToNew); - } + for (int i = 0; i < fCoverageStages.count(); ++i) { + fCoverageStages[i].localCoordChange(oldToNew); } } bool localCoordChangeInverse(const SkMatrix& newToOld) { SkMatrix oldToNew; bool computed = false; - for (int i = 0; i < kMaxColorStages; ++i) { - if (this->isColorStageEnabled(i)) { - if (!computed && !newToOld.invert(&oldToNew)) { - return false; - } else { - computed = true; - } - fColorStages[i].localCoordChange(oldToNew); + for (int i = 0; i < fColorStages.count(); ++i) { + if (!computed && !newToOld.invert(&oldToNew)) { + return false; + } else { + computed = true; } + fColorStages[i].localCoordChange(oldToNew); } - for (int i = 0; i < kMaxCoverageStages; ++i) { - if (this->isCoverageStageEnabled(i)) { - if (!computed && !newToOld.invert(&oldToNew)) { - return false; - } else { - computed = true; - } - fCoverageStages[i].localCoordChange(oldToNew); + for (int i = 0; i < fCoverageStages.count(); ++i) { + if (!computed && !newToOld.invert(&oldToNew)) { + return false; + } else { + computed = true; } + fCoverageStages[i].localCoordChange(oldToNew); } return true; } friend class GrContext; // To access above two functions - GrEffectStage fColorStages[kMaxColorStages]; - GrEffectStage fCoverageStages[kMaxCoverageStages]; + SkSTArray<4, GrEffectStage> fColorStages; + SkSTArray<2, GrEffectStage> fCoverageStages; GrBlendCoeff fSrcBlendCoeff; GrBlendCoeff fDstBlendCoeff; @@ -273,9 +226,6 @@ private: GrColor fColor; uint8_t fCoverage; - GrColor fColorFilterColor; - SkXfermode::Mode fColorFilterXfermode; - void resetBlend() { fSrcBlendCoeff = kOne_GrBlendCoeff; fDstBlendCoeff = kZero_GrBlendCoeff; @@ -295,12 +245,8 @@ private: } void resetStages() { - for (int i = 0; i < kMaxColorStages; ++i) { - fColorStages[i].reset(); - } - for (int i = 0; i < kMaxCoverageStages; ++i) { - fCoverageStages[i].reset(); - } + fColorStages.reset(); + fCoverageStages.reset(); } }; diff --git a/gfx/skia/include/gpu/GrPathRendererChain.h b/gfx/skia/trunk/include/gpu/GrPathRendererChain.h similarity index 99% rename from gfx/skia/include/gpu/GrPathRendererChain.h rename to gfx/skia/trunk/include/gpu/GrPathRendererChain.h index d51a4bbf1544..ca8c35bdeb37 100644 --- a/gfx/skia/include/gpu/GrPathRendererChain.h +++ b/gfx/skia/trunk/include/gpu/GrPathRendererChain.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,11 +5,10 @@ * found in the LICENSE file. */ - #ifndef GrPathRendererChain_DEFINED #define GrPathRendererChain_DEFINED -#include "GrRefCnt.h" +#include "SkRefCnt.h" #include "SkTArray.h" class GrContext; @@ -64,7 +62,6 @@ public: StencilSupport* stencilSupport); private: - GrPathRendererChain(); void init(); @@ -79,5 +76,4 @@ private: typedef SkRefCnt INHERITED; }; - #endif diff --git a/gfx/skia/include/gpu/GrPoint.h b/gfx/skia/trunk/include/gpu/GrPoint.h similarity index 100% rename from gfx/skia/include/gpu/GrPoint.h rename to gfx/skia/trunk/include/gpu/GrPoint.h diff --git a/gfx/skia/include/gpu/GrRect.h b/gfx/skia/trunk/include/gpu/GrRect.h similarity index 86% rename from gfx/skia/include/gpu/GrRect.h rename to gfx/skia/trunk/include/gpu/GrRect.h index 821e13703084..cacc5117b532 100644 --- a/gfx/skia/include/gpu/GrRect.h +++ b/gfx/skia/trunk/include/gpu/GrRect.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,17 +5,12 @@ * found in the LICENSE file. */ - - #ifndef GrRect_DEFINED #define GrRect_DEFINED -#include "GrPoint.h" +#include "SkTypes.h" #include "SkRect.h" -typedef SkIRect GrIRect; -typedef SkRect GrRect; - struct GrIRect16 { int16_t fLeft, fTop, fRight, fBottom; @@ -25,7 +19,7 @@ struct GrIRect16 { int area() const { return this->width() * this->height(); } bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } - void set(const GrIRect& r) { + void set(const SkIRect& r) { fLeft = SkToS16(r.fLeft); fTop = SkToS16(r.fTop); fRight = SkToS16(r.fRight); diff --git a/gfx/skia/include/gpu/GrRenderTarget.h b/gfx/skia/trunk/include/gpu/GrRenderTarget.h similarity index 89% rename from gfx/skia/include/gpu/GrRenderTarget.h rename to gfx/skia/trunk/include/gpu/GrRenderTarget.h index fcb4c3d3b16a..f43aba9d589e 100644 --- a/gfx/skia/include/gpu/GrRenderTarget.h +++ b/gfx/skia/trunk/include/gpu/GrRenderTarget.h @@ -8,8 +8,8 @@ #ifndef GrRenderTarget_DEFINED #define GrRenderTarget_DEFINED -#include "GrRect.h" #include "GrSurface.h" +#include "SkRect.h" class GrStencilBuffer; class GrTexture; @@ -90,12 +90,12 @@ public: * @param rect a rect bounding the area needing resolve. NULL indicates * the whole RT needs resolving. */ - void flagAsNeedingResolve(const GrIRect* rect = NULL); + void flagAsNeedingResolve(const SkIRect* rect = NULL); /** * Call to override the region that needs to be resolved. */ - void overrideResolveRect(const GrIRect rect); + void overrideResolveRect(const SkIRect rect); /** * Call to indicate that GrRenderTarget was externally resolved. This may @@ -111,7 +111,7 @@ public: /** * Returns a rect bounding the region needing resolving. */ - const GrIRect& getResolveRect() const { return fResolveRect; } + const SkIRect& getResolveRect() const { return fResolveRect; } /** * If the render target is multisampled this will perform a multisample @@ -148,26 +148,22 @@ protected: fResolveRect.setLargestInverted(); } - friend class GrTexture; - // When a texture unrefs an owned render target this func - // removes the back pointer. This could be called from - // texture's destructor but would have to be done in derived - // classes. By the time of texture base destructor it has already - // lost its pointer to the rt. - void onTextureReleaseRenderTarget() { - GrAssert(NULL != fTexture); - fTexture = NULL; - } - // override of GrResource virtual void onAbandon() SK_OVERRIDE; virtual void onRelease() SK_OVERRIDE; private: + friend class GrTexture; + // called by ~GrTexture to remove the non-ref'ed back ptr. + void owningTextureDestroyed() { + SkASSERT(NULL != fTexture); + fTexture = NULL; + } + GrStencilBuffer* fStencilBuffer; GrTexture* fTexture; // not ref'ed - GrIRect fResolveRect; + SkIRect fResolveRect; typedef GrSurface INHERITED; }; diff --git a/gfx/skia/include/gpu/GrResource.h b/gfx/skia/trunk/include/gpu/GrResource.h similarity index 71% rename from gfx/skia/include/gpu/GrResource.h rename to gfx/skia/trunk/include/gpu/GrResource.h index 72e6928b2be4..93dec58d8063 100644 --- a/gfx/skia/include/gpu/GrResource.h +++ b/gfx/skia/trunk/include/gpu/GrResource.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,12 +5,10 @@ * found in the LICENSE file. */ - #ifndef GrResource_DEFINED #define GrResource_DEFINED -#include "GrRefCnt.h" - +#include "SkRefCnt.h" #include "SkTInternalLList.h" class GrGpu; @@ -21,7 +18,7 @@ class GrResourceEntry; /** * Base class for the GPU resources created by a GrContext. */ -class GrResource : public GrRefCnt { +class GrResource : public SkRefCnt { public: SK_DECLARE_INST_COUNT(GrResource) @@ -69,8 +66,23 @@ public: void setCacheEntry(GrResourceEntry* cacheEntry) { fCacheEntry = cacheEntry; } GrResourceEntry* getCacheEntry() { return fCacheEntry; } - void incDeferredRefCount() const { GrAssert(fDeferredRefCount >= 0); ++fDeferredRefCount; } - void decDeferredRefCount() const { GrAssert(fDeferredRefCount > 0); --fDeferredRefCount; } + void incDeferredRefCount() const { + SkASSERT(fDeferredRefCount >= 0); + ++fDeferredRefCount; + } + + void decDeferredRefCount() const { + SkASSERT(fDeferredRefCount > 0); + --fDeferredRefCount; + if (0 == fDeferredRefCount && this->needsDeferredUnref()) { + SkASSERT(this->getRefCnt() > 1); + this->unref(); + } + } + + int getDeferredRefCount() const { return fDeferredRefCount; } + + void setNeedsDeferredUnref() { fFlags |= kDeferredUnref_FlagBit; } protected: /** @@ -89,10 +101,11 @@ protected: virtual void onAbandon() {}; bool isInCache() const { return NULL != fCacheEntry; } - bool isWrapped() const { return kWrapped_Flag & fFlags; } + bool isWrapped() const { return kWrapped_FlagBit & fFlags; } + bool needsDeferredUnref() const { return SkToBool(kDeferredUnref_FlagBit & fFlags); } private: -#if GR_DEBUG +#ifdef SK_DEBUG friend class GrGpu; // for assert in GrGpu to access getGpu #endif @@ -107,11 +120,24 @@ private: mutable int fDeferredRefCount; // How many references in deferred drawing buffers. enum Flags { - kWrapped_Flag = 0x1, + /** + * This resource wraps a GPU resource given to us by the user. + * Lifetime management is left up to the user (i.e., we will not + * free it). + */ + kWrapped_FlagBit = 0x1, + + /** + * This texture should be de-refed when the deferred ref count goes + * to zero. A resource gets into this state when the resource cache + * is holding a ref-of-obligation (i.e., someone needs to own it but + * no one else wants to) but doesn't really want to keep it around. + */ + kDeferredUnref_FlagBit = 0x2, }; uint32_t fFlags; - typedef GrRefCnt INHERITED; + typedef SkRefCnt INHERITED; }; #endif diff --git a/gfx/skia/include/gpu/GrSurface.h b/gfx/skia/trunk/include/gpu/GrSurface.h similarity index 76% rename from gfx/skia/include/gpu/GrSurface.h rename to gfx/skia/trunk/include/gpu/GrSurface.h index 02fc0d5dea0b..15e44ab59367 100644 --- a/gfx/skia/include/gpu/GrSurface.h +++ b/gfx/skia/trunk/include/gpu/GrSurface.h @@ -11,9 +11,11 @@ #include "GrTypes.h" #include "GrResource.h" +#include "SkRect.h" class GrTexture; class GrRenderTarget; +struct SkImageInfo; class GrSurface : public GrResource { public: @@ -33,8 +35,14 @@ public: */ int height() const { return fDesc.fHeight; } + /** + * Helper that gets the width and height of the surface as a bounding rectangle. + */ + void getBoundsRect(SkRect* rect) const { rect->setWH(SkIntToScalar(this->width()), + SkIntToScalar(this->height())); } + GrSurfaceOrigin origin() const { - GrAssert(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin); + SkASSERT(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin); return fDesc.fOrigin; } @@ -51,6 +59,8 @@ public: */ const GrTextureDesc& desc() const { return fDesc; } + void asImageInfo(SkImageInfo*) const; + /** * @return the texture associated with the surface, may be NULL. */ @@ -63,6 +73,22 @@ public: virtual GrRenderTarget* asRenderTarget() = 0; virtual const GrRenderTarget* asRenderTarget() const = 0; + /** + * Checks whether this GrSurface refers to the same GPU object as other. This + * catches the case where a GrTexture and GrRenderTarget refer to the same + * GPU memory. + */ + bool isSameAs(const GrSurface* other) const { + const GrRenderTarget* thisRT = this->asRenderTarget(); + if (NULL != thisRT) { + return thisRT == other->asRenderTarget(); + } else { + const GrTexture* thisTex = this->asTexture(); + SkASSERT(NULL != thisTex); // We must be one or the other + return thisTex == other->asTexture(); + } + } + /** * Reads a rectangle of pixels from the surface. * @param left left edge of the rectangle to read (inclusive) @@ -103,6 +129,12 @@ public: size_t rowBytes = 0, uint32_t pixelOpsFlags = 0) = 0; + /** + * Write the contents of the surface to a PNG. Returns true if successful. + * @param filename Full path to desired file + */ + bool savePixels(const char* filename); + protected: GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc) : INHERITED(gpu, isWrapped) diff --git a/gfx/skia/include/gpu/GrTBackendEffectFactory.h b/gfx/skia/trunk/include/gpu/GrTBackendEffectFactory.h similarity index 64% rename from gfx/skia/include/gpu/GrTBackendEffectFactory.h rename to gfx/skia/trunk/include/gpu/GrTBackendEffectFactory.h index 8697f8eb7a57..3711c7e86939 100644 --- a/gfx/skia/include/gpu/GrTBackendEffectFactory.h +++ b/gfx/skia/trunk/include/gpu/GrTBackendEffectFactory.h @@ -10,6 +10,7 @@ #include "GrBackendEffectFactory.h" #include "GrDrawEffect.h" +#include "gl/GrGLProgramEffects.h" /** * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton. @@ -32,22 +33,32 @@ public: GLSL code generation. */ virtual EffectKey glEffectKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) const SK_OVERRIDE { - GrAssert(kIllegalEffectClassID != fEffectClassID); + SkASSERT(kIllegalEffectClassID != fEffectClassID); EffectKey effectKey = GLEffect::GenKey(drawEffect, caps); - EffectKey textureKey = GLEffect::GenTextureKey(drawEffect, caps); - EffectKey attribKey = GLEffect::GenAttribKey(drawEffect); -#if GR_DEBUG - static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1)); - GrAssert(!(kIllegalIDMask & effectKey)); + EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps); + EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect); + EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect); +#ifdef SK_DEBUG + static const EffectKey kIllegalEffectKeyMask = (uint16_t) (~((1U << kEffectKeyBits) - 1)); + SkASSERT(!(kIllegalEffectKeyMask & effectKey)); static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1)); - GrAssert(!(kIllegalTextureKeyMask & textureKey)); + SkASSERT(!(kIllegalTextureKeyMask & textureKey)); + + static const EffectKey kIllegalTransformKeyMask = (uint16_t) (~((1U << kTransformKeyBits) - 1)); + SkASSERT(!(kIllegalTransformKeyMask & transformKey)); static const EffectKey kIllegalAttribKeyMask = (uint16_t) (~((1U << kAttribKeyBits) - 1)); - GrAssert(!(kIllegalAttribKeyMask & textureKey)); + SkASSERT(!(kIllegalAttribKeyMask & textureKey)); + + static const EffectKey kIllegalClassIDMask = (uint16_t) (~((1U << kClassIDBits) - 1)); + SkASSERT(!(kIllegalClassIDMask & fEffectClassID)); #endif - return fEffectClassID | (attribKey << (kEffectKeyBits+kTextureKeyBits)) | - (textureKey << kEffectKeyBits) | effectKey; + return (fEffectClassID << (kEffectKeyBits+kTextureKeyBits+kTransformKeyBits+kAttribKeyBits)) | + (attribKey << (kEffectKeyBits+kTextureKeyBits+kTransformKeyBits)) | + (transformKey << (kEffectKeyBits+kTextureKeyBits)) | + (textureKey << kEffectKeyBits) | + (effectKey); } /** Returns a new instance of the appropriate *GL* implementation class @@ -71,7 +82,7 @@ public: protected: GrTBackendEffectFactory() { - fEffectClassID = GenID() << (kEffectKeyBits + kTextureKeyBits) ; + fEffectClassID = GenID(); } }; diff --git a/gfx/skia/trunk/include/gpu/GrTextContext.h b/gfx/skia/trunk/include/gpu/GrTextContext.h new file mode 100644 index 000000000000..b367cf228d57 --- /dev/null +++ b/gfx/skia/trunk/include/gpu/GrTextContext.h @@ -0,0 +1,40 @@ +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrTextContext_DEFINED +#define GrTextContext_DEFINED + +#include "GrContext.h" +#include "GrGlyph.h" +#include "GrPaint.h" + +class GrContext; +class GrDrawTarget; +class GrFontScaler; + +/* + * This class wraps the state for a single text render + */ +class GrTextContext { +public: + virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, + GrFontScaler*) = 0; + +protected: + GrTextContext(GrContext*, const GrPaint&); + virtual ~GrTextContext() {} + + GrPaint fPaint; + GrContext* fContext; + GrDrawTarget* fDrawTarget; + + SkIRect fClipRect; + +private: +}; + +#endif diff --git a/gfx/skia/include/gpu/GrTexture.h b/gfx/skia/trunk/include/gpu/GrTexture.h similarity index 87% rename from gfx/skia/include/gpu/GrTexture.h rename to gfx/skia/trunk/include/gpu/GrTexture.h index 5d8ecaaaf257..e56f6f401c00 100644 --- a/gfx/skia/include/gpu/GrTexture.h +++ b/gfx/skia/trunk/include/gpu/GrTexture.h @@ -11,8 +11,8 @@ #include "GrSurface.h" #include "SkPoint.h" +#include "GrRenderTarget.h" -class GrRenderTarget; class GrResourceKey; class GrTextureParams; @@ -44,6 +44,14 @@ public: return 0 != (fDesc.fFlags & flags); } + void dirtyMipMaps(bool mipMapsDirty) { + fMipMapsDirty = mipMapsDirty; + } + + bool mipMapsAreDirty() const { + return fMipMapsDirty; + } + /** * Approximate number of bytes used by the texture */ @@ -80,10 +88,10 @@ public: * render target */ virtual GrRenderTarget* asRenderTarget() SK_OVERRIDE { - return fRenderTarget; + return fRenderTarget.get(); } virtual const GrRenderTarget* asRenderTarget() const SK_OVERRIDE { - return fRenderTarget; + return fRenderTarget.get(); } // GrTexture @@ -92,21 +100,14 @@ public: * only. */ GrFixed normalizeFixedX(GrFixed x) const { - GrAssert(GrIsPow2(fDesc.fWidth)); + SkASSERT(GrIsPow2(fDesc.fWidth)); return x >> fShiftFixedX; } GrFixed normalizeFixedY(GrFixed y) const { - GrAssert(GrIsPow2(fDesc.fHeight)); + SkASSERT(GrIsPow2(fDesc.fHeight)); return y >> fShiftFixedY; } - /** - * Removes the reference on the associated GrRenderTarget held by this - * texture. Afterwards asRenderTarget() will return NULL. The - * GrRenderTarget survives the release if another ref is held on it. - */ - void releaseRenderTarget(); - /** * Return the native ID or handle to the texture, depending on the * platform. e.g. on OpenGL, return the texture ID. @@ -119,36 +120,37 @@ public: */ virtual void invalidateCachedState() = 0; -#if GR_DEBUG +#ifdef SK_DEBUG void validate() const { this->INHERITED::validate(); this->validateDesc(); } -#else - void validate() const {} #endif + static GrResourceKey ComputeKey(const GrGpu* gpu, const GrTextureParams* params, const GrTextureDesc& desc, const GrCacheID& cacheID); static GrResourceKey ComputeScratchKey(const GrTextureDesc& desc); static bool NeedsResizing(const GrResourceKey& key); - static bool NeedsFiltering(const GrResourceKey& key); + static bool NeedsBilerp(const GrResourceKey& key); protected: - GrRenderTarget* fRenderTarget; // texture refs its rt representation - // base class cons sets to NULL - // subclass cons can create and set + // A texture refs its rt representation but not vice-versa. It is up to + // the subclass constructor to initialize this pointer. + SkAutoTUnref fRenderTarget; GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc) : INHERITED(gpu, isWrapped, desc) - , fRenderTarget(NULL) { + , fRenderTarget(NULL) + , fMipMapsDirty(true) { // only make sense if alloc size is pow2 fShiftFixedX = 31 - SkCLZ(fDesc.fWidth); fShiftFixedY = 31 - SkCLZ(fDesc.fHeight); } + virtual ~GrTexture(); // GrResource overrides virtual void onRelease() SK_OVERRIDE; @@ -162,6 +164,8 @@ private: int fShiftFixedX; int fShiftFixedY; + bool fMipMapsDirty; + virtual void internal_dispose() const SK_OVERRIDE; typedef GrSurface INHERITED; diff --git a/gfx/skia/include/gpu/GrTextureAccess.h b/gfx/skia/trunk/include/gpu/GrTextureAccess.h similarity index 76% rename from gfx/skia/include/gpu/GrTextureAccess.h rename to gfx/skia/trunk/include/gpu/GrTextureAccess.h index e5ea535d99ae..87b8d827cd01 100644 --- a/gfx/skia/include/gpu/GrTextureAccess.h +++ b/gfx/skia/trunk/include/gpu/GrTextureAccess.h @@ -8,9 +8,9 @@ #ifndef GrTextureAccess_DEFINED #define GrTextureAccess_DEFINED -#include "GrNoncopyable.h" #include "SkRefCnt.h" #include "SkShader.h" +#include "SkTypes.h" class GrTexture; @@ -18,7 +18,7 @@ class GrTexture; * Represents the filtering and tile modes used to access a texture. It is mostly used with * GrTextureAccess (defined below). Also, some of the texture cache methods require knowledge about * filtering and tiling to perform a cache lookup. If it wasn't for this latter usage this would - * be folded into GrTextureAccess. + * be folded into GrTextureAccess. The default is clamp tile modes and no filtering. */ class GrTextureParams { public: @@ -26,12 +26,18 @@ public: this->reset(); } - GrTextureParams(SkShader::TileMode tileXAndY, bool bilerp) { - this->reset(tileXAndY, bilerp); + enum FilterMode { + kNone_FilterMode, + kBilerp_FilterMode, + kMipMap_FilterMode + }; + + GrTextureParams(SkShader::TileMode tileXAndY, FilterMode filterMode) { + this->reset(tileXAndY, filterMode); } - GrTextureParams(SkShader::TileMode tileModes[2], bool bilerp) { - this->reset(tileModes, bilerp); + GrTextureParams(const SkShader::TileMode tileModes[2], FilterMode filterMode) { + this->reset(tileModes, filterMode); } GrTextureParams(const GrTextureParams& params) { @@ -41,35 +47,35 @@ public: GrTextureParams& operator= (const GrTextureParams& params) { fTileModes[0] = params.fTileModes[0]; fTileModes[1] = params.fTileModes[1]; - fBilerp = params.fBilerp; + fFilterMode = params.fFilterMode; return *this; } void reset() { - this->reset(SkShader::kClamp_TileMode, false); + this->reset(SkShader::kClamp_TileMode, kNone_FilterMode); } - void reset(SkShader::TileMode tileXAndY, bool bilerp) { + void reset(SkShader::TileMode tileXAndY, FilterMode filterMode) { fTileModes[0] = fTileModes[1] = tileXAndY; - fBilerp = bilerp; + fFilterMode = filterMode; } - void reset(SkShader::TileMode tileModes[2], bool bilerp) { + void reset(const SkShader::TileMode tileModes[2], FilterMode filterMode) { fTileModes[0] = tileModes[0]; fTileModes[1] = tileModes[1]; - fBilerp = bilerp; + fFilterMode = filterMode; } void setClampNoFilter() { fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; - fBilerp = false; + fFilterMode = kNone_FilterMode; } void setClamp() { fTileModes[0] = fTileModes[1] = SkShader::kClamp_TileMode; } - void setBilerp(bool bilerp) { fBilerp = bilerp; } + void setFilterMode(FilterMode filterMode) { fFilterMode = filterMode; } void setTileModeX(const SkShader::TileMode tm) { fTileModes[0] = tm; } void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; } @@ -84,12 +90,12 @@ public: SkShader::kClamp_TileMode != fTileModes[1]; } - bool isBilerp() const { return fBilerp; } + FilterMode filterMode() const { return fFilterMode; } bool operator== (const GrTextureParams& other) const { return fTileModes[0] == other.fTileModes[0] && fTileModes[1] == other.fTileModes[1] && - fBilerp == other.fBilerp; + fFilterMode == other.fFilterMode; } bool operator!= (const GrTextureParams& other) const { return !(*this == other); } @@ -97,7 +103,7 @@ public: private: SkShader::TileMode fTileModes[2]; - bool fBilerp; + FilterMode fFilterMode; }; /** A class representing the swizzle access pattern for a texture. Note that if the texture is @@ -106,7 +112,7 @@ private: * key. However, if a GrEffect uses different swizzles based on its input then it must * consider that variation in its key-generation. */ -class GrTextureAccess : GrNoncopyable { +class GrTextureAccess : public SkNoncopyable { public: /** * A default GrTextureAccess must have reset() called on it in a GrEffect subclass's @@ -119,7 +125,7 @@ public: */ GrTextureAccess(GrTexture*, const GrTextureParams&); explicit GrTextureAccess(GrTexture*, - bool bilerp = false, + GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode, SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); /** @@ -129,23 +135,23 @@ public: GrTextureAccess(GrTexture*, const char* swizzle, const GrTextureParams&); GrTextureAccess(GrTexture*, const char* swizzle, - bool bilerp = false, + GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode, SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); void reset(GrTexture*, const GrTextureParams&); void reset(GrTexture*, - bool bilerp = false, + GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode, SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); void reset(GrTexture*, const char* swizzle, const GrTextureParams&); void reset(GrTexture*, const char* swizzle, - bool bilerp = false, + GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode, SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode); bool operator== (const GrTextureAccess& other) const { -#if GR_DEBUG +#ifdef SK_DEBUG // below assumes all chars in fSwizzle are initialized even if string is < 4 chars long. - GrAssert(memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1) == + SkASSERT(memcmp(fSwizzle, other.fSwizzle, sizeof(fSwizzle)-1) == strcmp(fSwizzle, other.fSwizzle)); #endif return fParams == other.fParams && @@ -176,7 +182,7 @@ private: uint32_t fSwizzleMask; char fSwizzle[5]; - typedef GrNoncopyable INHERITED; + typedef SkNoncopyable INHERITED; }; #endif diff --git a/gfx/skia/include/gpu/GrTypes.h b/gfx/skia/trunk/include/gpu/GrTypes.h similarity index 89% rename from gfx/skia/include/gpu/GrTypes.h rename to gfx/skia/trunk/include/gpu/GrTypes.h index 5e48dac460e5..0bb432d663c5 100644 --- a/gfx/skia/include/gpu/GrTypes.h +++ b/gfx/skia/trunk/include/gpu/GrTypes.h @@ -74,7 +74,7 @@ template const T& GrMax(const T& a, const T& b) { * divide, rounding up */ static inline int32_t GrIDivRoundUp(int x, int y) { - GrAssert(y > 0); + SkASSERT(y > 0); return (x + (y-1)) / y; } static inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) { @@ -125,16 +125,6 @@ static inline size_t GrSizeAlignDown(size_t x, uint32_t alignment) { */ #define GR_ARRAY_COUNT(array) SK_ARRAY_COUNT(array) -//!< allocate a block of memory, will never return NULL -extern void* GrMalloc(size_t bytes); - -//!< free block allocated by GrMalloc. ptr may be NULL -extern void GrFree(void* ptr); - -static inline void Gr_bzero(void* dst, size_t size) { - memset(dst, 0, size); -} - /////////////////////////////////////////////////////////////////////////////// /** @@ -152,7 +142,7 @@ static inline uint32_t GrNextPow2(uint32_t n) { } static inline int GrNextPow2(int n) { - GrAssert(n >= 0); // this impl only works for non-neg. + SkASSERT(n >= 0); // this impl only works for non-neg. return n ? (1 << (32 - SkCLZ(n - 1))) : 1; } @@ -163,10 +153,10 @@ static inline int GrNextPow2(int n) { */ typedef int32_t GrFixed; -#if GR_DEBUG +#ifdef SK_DEBUG static inline int16_t GrToS16(intptr_t x) { - GrAssert((int16_t)x == x); + SkASSERT((int16_t)x == x); return (int16_t)x; } @@ -248,19 +238,25 @@ enum GrMaskFormat { kA8_GrMaskFormat, //!< 1-byte per pixel kA565_GrMaskFormat, //!< 2-bytes per pixel kA888_GrMaskFormat, //!< 4-bytes per pixel + kARGB_GrMaskFormat, //!< 4-bytes per pixel, color format - kCount_GrMaskFormats //!< used to allocate arrays sized for mask formats + kLast_GrMaskFormat = kARGB_GrMaskFormat }; +static const int kMaskFormatCount = kLast_GrMaskFormat + 1; /** * Return the number of bytes-per-pixel for the specified mask format. */ static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) { - GrAssert((unsigned)format <= 2); + SkASSERT((unsigned)format <= 3); // kA8 (0) -> 1 // kA565 (1) -> 2 // kA888 (2) -> 4 - return 1 << (int)format; + // kARGB (3) -> 4 + static const int sBytesPerPixel[] = { 1, 2, 4, 4 }; + SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sBytesPerPixel) == kMaskFormatCount, array_size_mismatch); + + return sBytesPerPixel[(int) format]; } /** @@ -379,6 +375,11 @@ enum GrTextureFlags { * Hint that the CPU may modify this texture after creation. */ kDynamicUpdate_GrTextureFlagBit = 0x4, + /** + * Indicates that all allocations (color buffer, FBO completeness, etc) + * should be verified. + */ + kCheckAllocation_GrTextureFlagBit = 0x8, kDummy_GrTextureFlagBit, kLastPublic_GrTextureFlagBit = kDummy_GrTextureFlagBit-1, @@ -467,7 +468,7 @@ public: * Initialize the cache ID to a domain and key. */ GrCacheID(Domain domain, const Key& key) { - GrAssert(kInvalid_Domain != domain); + SkASSERT(kInvalid_Domain != domain); this->reset(domain, key); } @@ -479,8 +480,8 @@ public: /** Has this been initialized to a valid domain */ bool isValid() const { return kInvalid_Domain != fDomain; } - const Key& getKey() const { GrAssert(this->isValid()); return fKey; } - Domain getDomain() const { GrAssert(this->isValid()); return fDomain; } + const Key& getKey() const { SkASSERT(this->isValid()); return fKey; } + Domain getDomain() const { SkASSERT(this->isValid()); return fDomain; } /** Creates a new unique ID domain. */ static Domain GenerateDomain(); @@ -500,39 +501,6 @@ enum GrClipType { kPath_ClipType }; -/** - * Commands used to describe a path. Each command - * is accompanied by some number of points. - */ -enum GrPathCmd { - kMove_PathCmd, //!< Starts a new subpath at - // at the returned point - // 1 point - kLine_PathCmd, //!< Adds a line segment - // 2 points - kQuadratic_PathCmd, //!< Adds a quadratic segment - // 3 points - kCubic_PathCmd, //!< Adds a cubic segment - // 4 points - kClose_PathCmd, //!< Closes the current subpath - // by connecting a line to the - // starting point. - // 0 points - kEnd_PathCmd //!< Indicates the end of the last subpath - // when iterating - // 0 points. -}; - -/** - * Gets the number of points associated with a path command. - */ -static int inline NumPathCmdPoints(GrPathCmd cmd) { - static const int gNumPoints[] = { - 1, 2, 3, 4, 0, 0 - }; - return gNumPoints[cmd]; -} - /////////////////////////////////////////////////////////////////////////////// // opaque type for 3D API object handles @@ -628,6 +596,32 @@ struct GrBackendRenderTargetDesc { GrBackendObject fRenderTargetHandle; }; +/** + * The GrContext's cache of backend context state can be partially invalidated. + * These enums are specific to the GL backend and we'd add a new set for an alternative backend. + */ +enum GrGLBackendState { + kRenderTarget_GrGLBackendState = 1 << 0, + kTextureBinding_GrGLBackendState = 1 << 1, + // View state stands for scissor and viewport + kView_GrGLBackendState = 1 << 2, + kBlend_GrGLBackendState = 1 << 3, + kAA_GrGLBackendState = 1 << 4, + kVertex_GrGLBackendState = 1 << 5, + kStencil_GrGLBackendState = 1 << 6, + kPixelStore_GrGLBackendState = 1 << 7, + kProgram_GrGLBackendState = 1 << 8, + kFixedFunction_GrGLBackendState = 1 << 9, + kMisc_GrGLBackendState = 1 << 10, + kPathRendering_GrGLBackendState = 1 << 11, + kALL_GrGLBackendState = 0xffff +}; + +/** + * This value translates to reseting all the context state for any backend. + */ +static const uint32_t kAll_GrBackendState = 0xffffffff; + /////////////////////////////////////////////////////////////////////////////// #endif diff --git a/gfx/skia/include/gpu/GrTypesPriv.h b/gfx/skia/trunk/include/gpu/GrTypesPriv.h similarity index 93% rename from gfx/skia/include/gpu/GrTypesPriv.h rename to gfx/skia/trunk/include/gpu/GrTypesPriv.h index 6737d57f0884..8888066d4faa 100644 --- a/gfx/skia/include/gpu/GrTypesPriv.h +++ b/gfx/skia/trunk/include/gpu/GrTypesPriv.h @@ -33,7 +33,7 @@ static const int kGrSLTypeCount = kLast_GrSLType + 1; * Gets the vector size of the SLType. Returns -1 for void, matrices, and samplers. */ static inline int GrSLTypeVectorCount(GrSLType type) { - GrAssert(type >= 0 && type < static_cast(kGrSLTypeCount)); + SkASSERT(type >= 0 && type < static_cast(kGrSLTypeCount)); static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1 }; return kCounts[type]; @@ -48,8 +48,10 @@ static inline int GrSLTypeVectorCount(GrSLType type) { GR_STATIC_ASSERT(GR_ARRAY_COUNT(kCounts) == kGrSLTypeCount); } +/** Return the type enum for a vector of floats of length n (1..4), + e.g. 1 -> kFloat_GrSLType, 2 -> kVec2_GrSLType, ... */ static inline GrSLType GrSLFloatVectorType(int count) { - GrAssert(count > 0 && count <= 4); + SkASSERT(count > 0 && count <= 4); return (GrSLType)(count); GR_STATIC_ASSERT(kFloat_GrSLType == 1); @@ -76,7 +78,7 @@ static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1; * Returns the vector size of the type. */ static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) { - GrAssert(type >= 0 && type < kGrVertexAttribTypeCount); + SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); static const int kCounts[] = { 1, 2, 3, 4, 4 }; return kCounts[type]; @@ -92,7 +94,7 @@ static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) { * Returns the size of the attrib type in bytes. */ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { - GrAssert(type >= 0 && type < kGrVertexAttribTypeCount); + SkASSERT(type >= 0 && type < kGrVertexAttribTypeCount); static const size_t kSizes[] = { sizeof(float), // kFloat_GrVertexAttribType 2*sizeof(float), // kVec2f_GrVertexAttribType @@ -134,7 +136,7 @@ static const int kGrFixedFunctionVertexAttribBindingCnt = kLastFixedFunction_GrVertexAttribBinding + 1; static inline int GrFixedFunctionVertexAttribVectorCount(GrVertexAttribBinding binding) { - GrAssert(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt); + SkASSERT(binding >= 0 && binding < kGrFixedFunctionVertexAttribBindingCnt); static const int kVecCounts[] = { 2, 2, 4, 4 }; return kVecCounts[binding]; diff --git a/gfx/skia/include/gpu/GrUserConfig.h b/gfx/skia/trunk/include/gpu/GrUserConfig.h similarity index 68% rename from gfx/skia/include/gpu/GrUserConfig.h rename to gfx/skia/trunk/include/gpu/GrUserConfig.h index 77ab850bac9c..6a5ef185fff7 100644 --- a/gfx/skia/include/gpu/GrUserConfig.h +++ b/gfx/skia/trunk/include/gpu/GrUserConfig.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef GrUserConfig_DEFINED #define GrUserConfig_DEFINED @@ -14,22 +12,6 @@ #error "default user config pulled in but GR_USER_CONFIG_FILE is defined." #endif -#if 0 - #undef GR_RELEASE - #undef GR_DEBUG - #define GR_RELEASE 0 - #define GR_DEBUG 1 -#endif - -/** - * When drawing rects this causes Ganesh to use a vertex buffer containing - * a unit square that is positioned by a matrix. Enable on systems where - * emitting per-rect-draw verts is more expensive than constant/matrix - * updates. Defaults to 0. - */ -//#define GR_STATIC_RECT_VB 1 - - /** * This gives a threshold in bytes of when to lock a GrGeometryBuffer vs using * updateData. (Note the depending on the underlying 3D API the update functions @@ -41,7 +23,13 @@ * This gives a threshold in megabytes for the maximum size of the texture cache * in vram. The value is only a default and can be overridden at runtime. */ -//#define GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT 96 +//#define GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT 96 + +/** + * This specifies the maximum number of textures the texture cache can hold + * in vram. The value is only a default and can be overridden at runtime. + */ +//#define GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT 2048 /* * This allows us to set a callback to be called before each GL call to ensure diff --git a/gfx/skia/include/gpu/SkGpuDevice.h b/gfx/skia/trunk/include/gpu/SkGpuDevice.h similarity index 66% rename from gfx/skia/include/gpu/SkGpuDevice.h rename to gfx/skia/trunk/include/gpu/SkGpuDevice.h index 8aa7d4aac8de..8b2170da6dbc 100644 --- a/gfx/skia/include/gpu/SkGpuDevice.h +++ b/gfx/skia/trunk/include/gpu/SkGpuDevice.h @@ -13,19 +13,20 @@ #include "SkGr.h" #include "SkBitmap.h" -#include "SkDevice.h" +#include "SkBitmapDevice.h" #include "SkRegion.h" #include "GrContext.h" struct SkDrawProcs; struct GrSkDrawProcs; + class GrTextContext; /** - * Subclass of SkDevice, which directs all drawing to the GrGpu owned by the + * Subclass of SkBitmapDevice, which directs all drawing to the GrGpu owned by the * canvas. */ -class SK_API SkGpuDevice : public SkDevice { +class SK_API SkGpuDevice : public SkBitmapDevice { public: /** @@ -43,16 +44,16 @@ public: SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height, int sampleCount = 0); /** + * DEPRECATED -- need to make this private, call Create(surface) * New device that will render to the specified renderTarget. - * DEPRECATED: Use Create(surface) */ SkGpuDevice(GrContext*, GrRenderTarget*); /** + * DEPRECATED -- need to make this private, call Create(surface) * New device that will render to the texture (as a rendertarget). * The GrTexture's asRenderTarget() must be non-NULL or device will not * function. - * DEPRECATED: Use Create(surface) */ SkGpuDevice(GrContext*, GrTexture*); @@ -60,9 +61,23 @@ public: GrContext* context() const { return fContext; } - virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE; + virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE; - // overrides from SkDevice + // overrides from SkBaseDevice + virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { + return 0; + } + virtual int width() const SK_OVERRIDE { + return NULL == fRenderTarget ? 0 : fRenderTarget->width(); + } + virtual int height() const SK_OVERRIDE { + return NULL == fRenderTarget ? 0 : fRenderTarget->height(); + } + virtual bool isOpaque() const SK_OVERRIDE { + return NULL == fRenderTarget ? false + : kRGB_565_GrPixelConfig == fRenderTarget->config(); + } + virtual SkBitmap::Config config() const SK_OVERRIDE; virtual void clear(SkColor color) SK_OVERRIDE; virtual void writePixels(const SkBitmap& bitmap, int x, int y, @@ -73,17 +88,19 @@ public: const SkPoint[], const SkPaint& paint) SK_OVERRIDE; virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint) SK_OVERRIDE; + virtual void drawRRect(const SkDraw&, const SkRRect& r, + const SkPaint& paint) SK_OVERRIDE; virtual void drawOval(const SkDraw&, const SkRect& oval, const SkPaint& paint) SK_OVERRIDE; virtual void drawPath(const SkDraw&, const SkPath& path, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) SK_OVERRIDE; virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, const SkMatrix&, const SkPaint&) SK_OVERRIDE; virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect* srcOrNull, const SkRect& dst, - const SkPaint& paint) SK_OVERRIDE; + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, const SkPaint& paint); virtual void drawText(const SkDraw&, const void* text, size_t len, @@ -99,11 +116,11 @@ public: const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint&) SK_OVERRIDE; - virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) SK_OVERRIDE; virtual bool filterTextFlags(const SkPaint&, TextFlags*) SK_OVERRIDE; - virtual void flush(); + virtual void flush() SK_OVERRIDE; virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE; virtual void onDetachFromCanvas() SK_OVERRIDE; @@ -114,14 +131,14 @@ public: */ virtual void makeRenderTargetCurrent(); - virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE; - virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&, + virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE; + virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkMatrix&, SkBitmap*, SkIPoint*) SK_OVERRIDE; class SkAutoCachedTexture; // used internally protected: - // overrides from SkDevice + // overrides from SkBaseDevice virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) SK_OVERRIDE; @@ -133,6 +150,9 @@ private: GrClipData fClipData; + GrTextContext* fMainTextContext; + GrTextContext* fFallbackTextContext; + // state for our render-target GrRenderTarget* fRenderTarget; bool fNeedClear; @@ -143,14 +163,13 @@ private: // used by createCompatibleDevice SkGpuDevice(GrContext*, GrTexture* texture, bool needClear); - // override from SkDevice - virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque, - Usage usage) SK_OVERRIDE; + // override from SkBaseDevice + virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) SK_OVERRIDE; - SkDrawProcs* initDrawForText(GrTextContext*); - bool bindDeviceAsTexture(GrPaint* paint); + virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE; // sets the render target, clip, and matrix on GrContext. Use forceIdenity to override // SkDraw's matrix and draw in device coords. @@ -162,33 +181,38 @@ private: void drawBitmapCommon(const SkDraw&, const SkBitmap& bitmap, const SkRect* srcRectPtr, - const SkMatrix&, - const SkPaint&); + const SkSize* dstSizePtr, // ignored iff srcRectPtr == NULL + const SkPaint&, + SkCanvas::DrawBitmapRectFlags flags); /** * Helper functions called by drawBitmapCommon. By the time these are called the SkDraw's - * matrix has already been set on GrContext + * matrix, clip, and the device's render target has already been set on GrContext. */ + + // The tileSize and clippedSrcRect will be valid only if true is returned. bool shouldTileBitmap(const SkBitmap& bitmap, const GrTextureParams& sampler, - const SkRect* srcRectPtr) const; + const SkRect* srcRectPtr, + int maxTileSize, + int* tileSize, + SkIRect* clippedSrcRect) const; void internalDrawBitmap(const SkBitmap&, const SkRect&, - const SkMatrix&, const GrTextureParams& params, - GrPaint* grPaint); + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags, + bool bicubic); void drawTiledBitmap(const SkBitmap& bitmap, const SkRect& srcRect, - const SkMatrix& m, + const SkIRect& clippedSrcRect, const GrTextureParams& params, - GrPaint* grPaint); + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags, + int tileSize, + bool bicubic); - /** - * Returns non-initialized instance. - */ - GrTextContext* getTextContext(); - - typedef SkDevice INHERITED; + typedef SkBitmapDevice INHERITED; }; #endif diff --git a/gfx/skia/include/gpu/SkGr.h b/gfx/skia/trunk/include/gpu/SkGr.h similarity index 81% rename from gfx/skia/include/gpu/SkGr.h rename to gfx/skia/trunk/include/gpu/SkGr.h index cf37f472188c..db08548f5d54 100644 --- a/gfx/skia/include/gpu/SkGr.h +++ b/gfx/skia/trunk/include/gpu/SkGr.h @@ -25,10 +25,6 @@ #include "SkRegion.h" #include "SkClipStack.h" -#if (GR_DEBUG && defined(SK_RELEASE)) || (GR_RELEASE && defined(SK_DEBUG)) -// #error "inconsistent GR_DEBUG and SK_DEBUG" -#endif - //////////////////////////////////////////////////////////////////////////////// // Sk to Gr Type conversions @@ -45,15 +41,6 @@ GR_STATIC_ASSERT((int)kIDA_GrBlendCoeff == (int)SkXfermode::kIDA_Coeff); #define sk_blend_to_grblend(X) ((GrBlendCoeff)(X)) -GR_STATIC_ASSERT((int)SkPath::kMove_Verb == (int)kMove_PathCmd); -GR_STATIC_ASSERT((int)SkPath::kLine_Verb == (int)kLine_PathCmd); -GR_STATIC_ASSERT((int)SkPath::kQuad_Verb == (int)kQuadratic_PathCmd); -GR_STATIC_ASSERT((int)SkPath::kCubic_Verb == (int)kCubic_PathCmd); -GR_STATIC_ASSERT((int)SkPath::kClose_Verb == (int)kClose_PathCmd); -GR_STATIC_ASSERT((int)SkPath::kDone_Verb == (int)kEnd_PathCmd); - -#define sk_path_verb_to_gr_path_command(X) ((GrPathCmd)(X)) - /////////////////////////////////////////////////////////////////////////////// #include "SkColorPriv.h" @@ -63,6 +50,7 @@ GR_STATIC_ASSERT((int)SkPath::kDone_Verb == (int)kEnd_PathCmd); * kUnknown_PixelConfig if the conversion cannot be done. */ GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config); +bool GrPixelConfig2ColorType(GrPixelConfig, SkColorType*); static inline GrColor SkColor2GrColor(SkColor c) { SkPMColor pm = SkPreMultiplyColor(c); @@ -94,7 +82,7 @@ public: // overrides virtual const GrKey* getKey(); virtual GrMaskFormat getMaskFormat(); - virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds); + virtual bool getPackedGlyphBounds(GrGlyph::PackedID, SkIRect* bounds); virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height, int rowBytes, void* image); virtual bool getGlyphPath(uint16_t glyphID, SkPath*); diff --git a/gfx/skia/include/gpu/SkGrPixelRef.h b/gfx/skia/trunk/include/gpu/SkGrPixelRef.h similarity index 77% rename from gfx/skia/include/gpu/SkGrPixelRef.h rename to gfx/skia/trunk/include/gpu/SkGrPixelRef.h index ec1e22ec0204..1e495611fc20 100644 --- a/gfx/skia/include/gpu/SkGrPixelRef.h +++ b/gfx/skia/trunk/include/gpu/SkGrPixelRef.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 Google Inc. * @@ -6,8 +5,6 @@ * found in the LICENSE file. */ - - #ifndef SkGrPixelRef_DEFINED #define SkGrPixelRef_DEFINED @@ -23,14 +20,14 @@ */ class SK_API SkROLockPixelsPixelRef : public SkPixelRef { public: - SkROLockPixelsPixelRef(); + SK_DECLARE_INST_COUNT(SkROLockPixelsPixelRef) + SkROLockPixelsPixelRef(const SkImageInfo&); virtual ~SkROLockPixelsPixelRef(); protected: - // override from SkPixelRef - virtual void* onLockPixels(SkColorTable** ptr); - virtual void onUnlockPixels(); - virtual bool onLockPixelsAreWritable() const; // return false; + virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE; + virtual void onUnlockPixels() SK_OVERRIDE; + virtual bool onLockPixelsAreWritable() const SK_OVERRIDE; // return false; private: SkBitmap fBitmap; @@ -42,16 +39,17 @@ private: */ class SK_API SkGrPixelRef : public SkROLockPixelsPixelRef { public: + SK_DECLARE_INST_COUNT(SkGrPixelRef) /** * Constructs a pixel ref around a GrSurface. If the caller has locked the GrSurface in the * cache and would like the pixel ref to unlock it in its destructor then transferCacheLock * should be set to true. */ - SkGrPixelRef(GrSurface* surface, bool transferCacheLock = false); + SkGrPixelRef(const SkImageInfo&, GrSurface*, bool transferCacheLock = false); virtual ~SkGrPixelRef(); // override from SkPixelRef - virtual SkGpuTexture* getTexture() SK_OVERRIDE; + virtual GrTexture* getTexture() SK_OVERRIDE; SK_DECLARE_UNFLATTENABLE_OBJECT() diff --git a/gfx/skia/include/gpu/SkGrTexturePixelRef.h b/gfx/skia/trunk/include/gpu/SkGrTexturePixelRef.h similarity index 100% rename from gfx/skia/include/gpu/SkGrTexturePixelRef.h rename to gfx/skia/trunk/include/gpu/SkGrTexturePixelRef.h diff --git a/gfx/skia/include/gpu/gl/GrGLConfig.h b/gfx/skia/trunk/include/gpu/gl/GrGLConfig.h similarity index 93% rename from gfx/skia/include/gpu/gl/GrGLConfig.h rename to gfx/skia/trunk/include/gpu/gl/GrGLConfig.h index 81cba1badf0e..444be00f158d 100644 --- a/gfx/skia/include/gpu/gl/GrGLConfig.h +++ b/gfx/skia/trunk/include/gpu/gl/GrGLConfig.h @@ -39,7 +39,7 @@ * GR_GL_LOG_CALLS is 1. Defaults to 0. * * GR_GL_CHECK_ERROR: if enabled Gr can do a glGetError() after every GL call. - * Defaults to 1 if GR_DEBUG is set, otherwise 0. When GR_GL_CHECK_ERROR is 1 + * Defaults to 1 if SK_DEBUG is set, otherwise 0. When GR_GL_CHECK_ERROR is 1 * this can be toggled in a debugger using the gCheckErrorGL global. The initial * value of gCheckErrorGL is controlled by by GR_GL_CHECK_ERROR_START. * @@ -93,10 +93,6 @@ * stencil formats as attachments. If the FBO is complete we will assume * subsequent attachments with the same formats are complete as well. * - * GR_GL_USE_NV_PATH_RENDERING: Enable experimental support for - * GL_NV_path_rendering. There are known issues with clipping, non-AA paths, and - * perspective. - * * GR_GL_MUST_USE_VBO: Indicates that all vertices and indices must be rendered * from VBOs. Chromium's command buffer doesn't allow glVertexAttribArray with * ARARY_BUFFER 0 bound or glDrawElements with ELEMENT_ARRAY_BUFFER 0 bound. @@ -107,7 +103,11 @@ */ #if !defined(GR_GL_LOG_CALLS) - #define GR_GL_LOG_CALLS GR_DEBUG + #ifdef SK_DEBUG + #define GR_GL_LOG_CALLS 1 + #else + #define GR_GL_LOG_CALLS 0 + #endif #endif #if !defined(GR_GL_LOG_CALLS_START) @@ -115,7 +115,11 @@ #endif #if !defined(GR_GL_CHECK_ERROR) - #define GR_GL_CHECK_ERROR GR_DEBUG + #ifdef SK_DEBUG + #define GR_GL_CHECK_ERROR 1 + #else + #define GR_GL_CHECK_ERROR 0 + #endif #endif #if !defined(GR_GL_CHECK_ERROR_START) @@ -150,10 +154,6 @@ #define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT 0 #endif -#if !defined(GR_GL_USE_NV_PATH_RENDERING) - #define GR_GL_USE_NV_PATH_RENDERING 0 -#endif - #if !defined(GR_GL_MUST_USE_VBO) #define GR_GL_MUST_USE_VBO 0 #endif @@ -188,7 +188,7 @@ * OS/driver level fix. */ #define GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND \ - (GR_MAC_BUILD && \ + (defined(SK_BUILD_FOR_MAC) && \ !GR_GL_USE_BUFFER_DATA_NULL_HINT) #endif diff --git a/gfx/skia/include/gpu/gl/GrGLConfig_chrome.h b/gfx/skia/trunk/include/gpu/gl/GrGLConfig_chrome.h similarity index 75% rename from gfx/skia/include/gpu/gl/GrGLConfig_chrome.h rename to gfx/skia/trunk/include/gpu/gl/GrGLConfig_chrome.h index e08692fb61f9..acad90450c11 100644 --- a/gfx/skia/include/gpu/gl/GrGLConfig_chrome.h +++ b/gfx/skia/trunk/include/gpu/gl/GrGLConfig_chrome.h @@ -11,14 +11,20 @@ // glGetError() forces a sync with gpu process on chrome #define GR_GL_CHECK_ERROR_START 0 +#if defined(SK_BUILD_FOR_WIN32) // ANGLE creates a temp VB for vertex attributes not specified per-vertex. -#define GR_GL_NO_CONSTANT_ATTRIBUTES GR_WIN32_BUILD +#define GR_GL_NO_CONSTANT_ATTRIBUTES 1 // For RGBA teximage/readpixels ANGLE will sw-convert to/from BGRA. -#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW GR_WIN32_BUILD +#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 1 // ANGLE can go faster if the entire fbo is read rather than a subrect -#define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL GR_WIN32_BUILD +#define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL 1 +#else +#define GR_GL_NO_CONSTANT_ATTRIBUTES 0 +#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 0 +#define GR_GL_FULL_READPIXELS_FASTER_THAN_PARTIAL 0 +#endif // cmd buffer allocates memory and memsets it to zero when it sees glBufferData // with NULL. @@ -41,4 +47,8 @@ // (const char* const instead of char**). #define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE 1 +#if !defined(GR_GL_IGNORE_ES3_MSAA) + #define GR_GL_IGNORE_ES3_MSAA 1 +#endif + #endif diff --git a/gfx/skia/include/gpu/gl/GrGLExtensions.h b/gfx/skia/trunk/include/gpu/gl/GrGLExtensions.h similarity index 56% rename from gfx/skia/include/gpu/gl/GrGLExtensions.h rename to gfx/skia/trunk/include/gpu/gl/GrGLExtensions.h index d0970a650d56..76516cf11f9f 100644 --- a/gfx/skia/include/gpu/gl/GrGLExtensions.h +++ b/gfx/skia/trunk/include/gpu/gl/GrGLExtensions.h @@ -8,10 +8,12 @@ #ifndef GrGLExtensions_DEFINED #define GrGLExtensions_DEFINED -#include "GrGLInterface.h" +#include "GrGLFunctions.h" #include "SkString.h" #include "SkTArray.h" +struct GrGLInterface; + /** * This helper queries the current GL context for its extensions, remembers them, and can be * queried. It supports both glGetString- and glGetStringi-style extension string APIs and will @@ -19,29 +21,46 @@ */ class GrGLExtensions { public: - bool init(GrGLBinding binding, const GrGLInterface* iface) { - GrAssert(binding & iface->fBindingsExported); - return this->init(binding, iface->fGetString, iface->fGetStringi, iface->fGetIntegerv); + GrGLExtensions() : fInitialized(false), fStrings(SkNEW(SkTArray)) {} + + GrGLExtensions(const GrGLExtensions&); + + GrGLExtensions& operator=(const GrGLExtensions&); + + void swap(GrGLExtensions* that) { + fStrings.swap(&that->fStrings); + SkTSwap(fInitialized, that->fInitialized); } + /** * We sometimes need to use this class without having yet created a GrGLInterface. This version * of init expects that getString is always non-NULL while getIntegerv and getStringi are non- * NULL if on desktop GL with version 3.0 or higher. Otherwise it will fail. */ - bool init(GrGLBinding binding, + bool init(GrGLStandard standard, GrGLGetStringProc getString, GrGLGetStringiProc getStringi, GrGLGetIntegervProc getIntegerv); + bool isInitialized() const { return fInitialized; } + /** * Queries whether an extension is present. This will fail if init() has not been called. */ - bool has(const char*) const; + bool has(const char[]) const; - void reset() { fStrings.reset(); } + /** + * Removes an extension if present. Returns true if the extension was present before the call. + */ + bool remove(const char[]); + + void reset() { fStrings->reset(); } + + void print(const char* sep = "\n") const; private: - SkTArray fStrings; + bool fInitialized; + SkAutoTDelete > fStrings; }; #endif diff --git a/gfx/skia/include/gpu/gl/GrGLFunctions.h b/gfx/skia/trunk/include/gpu/gl/GrGLFunctions.h similarity index 91% rename from gfx/skia/include/gpu/gl/GrGLFunctions.h rename to gfx/skia/trunk/include/gpu/gl/GrGLFunctions.h index 037ebfdd9f15..b6d68c7ff4bd 100644 --- a/gfx/skia/include/gpu/gl/GrGLFunctions.h +++ b/gfx/skia/trunk/include/gpu/gl/GrGLFunctions.h @@ -11,12 +11,29 @@ #include "GrGLConfig.h" +//////////////////////////////////////////////////////////////////////////////// + +/** + * Classifies GL contexts by which standard they implement (currently as Desktop + * vs. ES). + */ +enum GrGLStandard { + kNone_GrGLStandard, + kGL_GrGLStandard, + kGLES_GrGLStandard, +}; + +// Temporary aliases until Chromium can be updated. +typedef GrGLStandard GrGLBinding; +static const GrGLStandard kES2_GrGLBinding = kGLES_GrGLStandard; +static const GrGLStandard kDesktop_GrGLBinding = kGL_GrGLStandard; + +/////////////////////////////////////////////////////////////////////////////// + /** * Declares typedefs for all the GL functions used in GrGLInterface */ -/////////////////////////////////////////////////////////////////////////////// - typedef unsigned int GrGLenum; typedef unsigned char GrGLboolean; typedef unsigned int GrGLbitfield; @@ -35,8 +52,18 @@ typedef float GrGLclampf; typedef double GrGLdouble; typedef double GrGLclampd; typedef void GrGLvoid; -typedef long GrGLintptr; -typedef long GrGLsizeiptr; +#ifndef SK_IGNORE_64BIT_OPENGL_CHANGES +#ifdef _WIN64 +typedef signed long long int GrGLintptr; +typedef signed long long int GrGLsizeiptr; +#else +typedef signed long int GrGLintptr; +typedef signed long int GrGLsizeiptr; +#endif +#else +typedef signed long int GrGLintptr; +typedef signed long int GrGLsizeiptr; +#endif /////////////////////////////////////////////////////////////////////////////// @@ -61,9 +88,11 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearProc)(GrGLbitfield mask); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClearStencilProc)(GrGLint s); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLClientActiveTextureProc)(GrGLenum texture); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLColorMaskProc)(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCompileShaderProc)(GrGLuint shader); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCompressedTexImage2DProc)(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCopyTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height); typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLCreateProgramProc)(void); typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLCreateShaderProc)(GrGLenum type); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCullFaceProc)(GrGLenum mode); @@ -77,12 +106,14 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteVertexArraysProc)(GrGLsizei n, const GrGLuint *arrays); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDepthMaskProc)(GrGLboolean flag); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableProc)(GrGLenum cap); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableClientStateProc)(GrGLenum cap); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableVertexAttribArrayProc)(GrGLuint index); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBufferProc)(GrGLenum mode); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBuffersProc)(GrGLsizei n, const GrGLenum* bufs); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableProc)(GrGLenum cap); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableClientStateProc)(GrGLenum cap); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableVertexAttribArrayProc)(GrGLuint index); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEndQueryProc)(GrGLenum target); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFinishProc)(); @@ -93,6 +124,7 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFrontFaceProc)(GrGLenum mode); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenBuffersProc)(GrGLsizei n, GrGLuint* buffers); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenFramebuffersProc)(GrGLsizei n, GrGLuint *framebuffers); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenerateMipmapProc)(GrGLenum target); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenQueriesProc)(GrGLsizei n, GrGLuint *ids); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenRenderbuffersProc)(GrGLsizei n, GrGLuint *renderbuffers); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGenTexturesProc)(GrGLsizei n, GrGLuint* textures); @@ -124,9 +156,10 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageProc)(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageMultisampleProc)(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); - typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLRenderbufferStorageMultisampleCoverageProc)(GrGLenum target, GrGLsizei coverageSamples, GrGLsizei colorSamples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLResolveMultisampleFramebufferProc)(); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLScissorProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLBindUniformLocation)(GrGLuint program, GrGLint location, const char* name); + #if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char* const * str, const GrGLint* length); #else @@ -138,10 +171,14 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilMaskSeparateProc)(GrGLenum face, GrGLuint mask); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilOpProc)(GrGLenum fail, GrGLenum zfail, GrGLenum zpass); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilOpSeparateProc)(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexGenfProc)(GrGLenum coord, GrGLenum pname, GrGLfloat param); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexGenfvProc)(GrGLenum coord, GrGLenum pname, const GrGLfloat* params); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexGeniProc)(GrGLenum coord, GrGLenum pname, GrGLint param); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexImage2DProc)(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexParameteriProc)(GrGLenum target, GrGLenum pname, GrGLint param); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexParameterivProc)(GrGLenum target, GrGLenum pname, const GrGLint* params); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexStorage2DProc)(GrGLenum target, GrGLsizei levels, GrGLenum internalformat, GrGLsizei width, GrGLsizei height); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDiscardFramebufferProc)(GrGLenum target, GrGLsizei numAttachments, const GrGLenum* attachments); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1fProc)(GrGLint location, GrGLfloat v0); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUniform1iProc)(GrGLint location, GrGLint v0); @@ -166,6 +203,7 @@ extern "C" { typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLUseProgramProc)(GrGLuint program); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr); + typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexPointerProc)(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height); // Experimental: Functions for GL_NV_path_rendering. These will be diff --git a/gfx/skia/trunk/include/gpu/gl/GrGLInterface.h b/gfx/skia/trunk/include/gpu/gl/GrGLInterface.h new file mode 100644 index 000000000000..f5bcd16682a9 --- /dev/null +++ b/gfx/skia/trunk/include/gpu/gl/GrGLInterface.h @@ -0,0 +1,564 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLInterface_DEFINED +#define GrGLInterface_DEFINED + +#include "GrGLFunctions.h" +#include "GrGLExtensions.h" +#include "SkRefCnt.h" + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Rather than depend on platform-specific GL headers and libraries, we require + * the client to provide a struct of GL function pointers. This struct can be + * specified per-GrContext as a parameter to GrContext::Create. If NULL is + * passed to Create then a "default" GL interface is created. If the default is + * also NULL GrContext creation will fail. + * + * The default interface is returned by GrGLDefaultInterface. This function's + * implementation is platform-specific. Several have been provided, along with + * an implementation that simply returns NULL. + * + * By defining GR_GL_PER_GL_CALL_IFACE_CALLBACK to 1 the client can specify a + * callback function that will be called prior to each GL function call. See + * comments in GrGLConfig.h + */ + +struct GrGLInterface; + +const GrGLInterface* GrGLDefaultInterface(); + +/** + * Creates a GrGLInterface for a "native" GL context (e.g. WGL on windows, + * GLX on linux, AGL on Mac). The interface is only valid for the GL context + * that is current when the interface is created. + */ +const GrGLInterface* GrGLCreateNativeInterface(); + +#if SK_MESA +/** + * Creates a GrGLInterface for an OSMesa context. + */ +const GrGLInterface* GrGLCreateMesaInterface(); +#endif + +#if SK_ANGLE +/** + * Creates a GrGLInterface for an ANGLE context. + */ +const GrGLInterface* GrGLCreateANGLEInterface(); +#endif + +/** + * Creates a null GrGLInterface that doesn't draw anything. Used for measuring + * CPU overhead. + */ +const SK_API GrGLInterface* GrGLCreateNullInterface(); + +/** + * Creates a debugging GrGLInterface that doesn't draw anything. Used for + * finding memory leaks and invalid memory accesses. + */ +const GrGLInterface* GrGLCreateDebugInterface(); + +#if GR_GL_PER_GL_FUNC_CALLBACK +typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*); +typedef intptr_t GrGLInterfaceCallbackData; +#endif + +/** Function that returns a new interface identical to "interface" but without support for + GL_NV_path_rendering. */ +const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface*); + +/** + * GrContext uses the following interface to make all calls into OpenGL. When a + * GrContext is created it is given a GrGLInterface. The interface's function + * pointers must be valid for the OpenGL context associated with the GrContext. + * On some platforms, such as Windows, function pointers for OpenGL extensions + * may vary between OpenGL contexts. So the caller must be careful to use a + * GrGLInterface initialized for the correct context. All functions that should + * be available based on the OpenGL's version and extension string must be + * non-NULL or GrContext creation will fail. This can be tested with the + * validate() method when the OpenGL context has been made current. + */ +struct SK_API GrGLInterface : public SkRefCnt { +private: + // simple wrapper class that exists only to initialize a pointer to NULL + template class GLPtr { + public: + GLPtr() : fPtr(NULL) {} + GLPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; } + operator FNPTR_TYPE() const { return fPtr; } + private: + FNPTR_TYPE fPtr; + }; + + // This is a temporary workaround to keep Chromium's GrGLInterface factories compiling until + // they're updated to use the Functions struct. + template class GLPtrAlias { + public: + GLPtrAlias(GLPtr* base) : fBase(base) {} + void operator=(FNPTR_TYPE ptr) { *fBase = ptr; } + private: + GLPtr* fBase; + }; + + typedef SkRefCnt INHERITED; + +public: + SK_DECLARE_INST_COUNT(GrGLInterface) + + GrGLInterface(); + + static GrGLInterface* NewClone(const GrGLInterface*); + + // Validates that the GrGLInterface supports its advertised standard. This means the necessary + // function pointers have been initialized for both the GL version and any advertised + // extensions. + bool validate() const; + + // Indicates the type of GL implementation + union { + GrGLStandard fStandard; + GrGLStandard fBindingsExported; // Legacy name, will be remove when Chromium is updated. + }; + + GrGLExtensions fExtensions; + + // This wrapper and const hackery is necessary because the factories in Chromium do not yet + // initialize fExtensions. + bool hasExtension(const char ext[]) const { + if (!fExtensions.isInitialized()) { + GrGLExtensions* extensions = const_cast(&fExtensions); + if (!extensions->init(fStandard, fFunctions.fGetString, + fFunctions.fGetStringi, fFunctions.fGetIntegerv)) { + return false; + } + } + return fExtensions.has(ext); + } + + /** + * The function pointers are in a struct so that we can have a compiler generated assignment + * operator. + */ + struct Functions { + GLPtr fActiveTexture; + GLPtr fAttachShader; + GLPtr fBeginQuery; + GLPtr fBindAttribLocation; + GLPtr fBindBuffer; + GLPtr fBindFragDataLocation; + GLPtr fBindFragDataLocationIndexed; + GLPtr fBindFramebuffer; + GLPtr fBindRenderbuffer; + GLPtr fBindTexture; + GLPtr fBindVertexArray; + GLPtr fBlendColor; + GLPtr fBlendFunc; + GLPtr fBlitFramebuffer; + GLPtr fBufferData; + GLPtr fBufferSubData; + GLPtr fCheckFramebufferStatus; + GLPtr fClear; + GLPtr fClearColor; + GLPtr fClearStencil; + GLPtr fClientActiveTexture; + GLPtr fColorMask; + GLPtr fCompileShader; + GLPtr fCompressedTexImage2D; + GLPtr fCopyTexSubImage2D; + GLPtr fCreateProgram; + GLPtr fCreateShader; + GLPtr fCullFace; + GLPtr fDeleteBuffers; + GLPtr fDeleteFramebuffers; + GLPtr fDeleteProgram; + GLPtr fDeleteQueries; + GLPtr fDeleteRenderbuffers; + GLPtr fDeleteShader; + GLPtr fDeleteTextures; + GLPtr fDeleteVertexArrays; + GLPtr fDepthMask; + GLPtr fDisable; + GLPtr fDisableClientState; + GLPtr fDisableVertexAttribArray; + GLPtr fDrawArrays; + GLPtr fDrawBuffer; + GLPtr fDrawBuffers; + GLPtr fDrawElements; + GLPtr fEnable; + GLPtr fEnableClientState; + GLPtr fEnableVertexAttribArray; + GLPtr fEndQuery; + GLPtr fFinish; + GLPtr fFlush; + GLPtr fFramebufferRenderbuffer; + GLPtr fFramebufferTexture2D; + GLPtr fFramebufferTexture2DMultisample; + GLPtr fFrontFace; + GLPtr fGenBuffers; + GLPtr fGenFramebuffers; + GLPtr fGenerateMipmap; + GLPtr fGenQueries; + GLPtr fGenRenderbuffers; + GLPtr fGenTextures; + GLPtr fGenVertexArrays; + GLPtr fGetBufferParameteriv; + GLPtr fGetError; + GLPtr fGetFramebufferAttachmentParameteriv; + GLPtr fGetIntegerv; + GLPtr fGetQueryObjecti64v; + GLPtr fGetQueryObjectiv; + GLPtr fGetQueryObjectui64v; + GLPtr fGetQueryObjectuiv; + GLPtr fGetQueryiv; + GLPtr fGetProgramInfoLog; + GLPtr fGetProgramiv; + GLPtr fGetRenderbufferParameteriv; + GLPtr fGetShaderInfoLog; + GLPtr fGetShaderiv; + GLPtr fGetString; + GLPtr fGetStringi; + GLPtr fGetTexLevelParameteriv; + GLPtr fGetUniformLocation; + GLPtr fLineWidth; + GLPtr fLinkProgram; + GLPtr fLoadIdentity; + GLPtr fLoadMatrixf; + GLPtr fMapBuffer; + GLPtr fMatrixMode; + GLPtr fPixelStorei; + GLPtr fQueryCounter; + GLPtr fReadBuffer; + GLPtr fReadPixels; + GLPtr fRenderbufferStorage; + + // On OpenGL ES there are multiple incompatible extensions that add support for MSAA + // and ES3 adds MSAA support to the standard. On an ES3 driver we may still use the + // older extensions for performance reasons or due to ES3 driver bugs. We want the function + // that creates the GrGLInterface to provide all available functions and internally + // we will select among them. They all have a method called glRenderbufferStorageMultisample*. + // So we have separate function pointers for GL_IMG/EXT_multisampled_to_texture, + // GL_CHROMIUM/ANGLE_framebuffer_multisample/ES3, and GL_APPLE_framebuffer_multisample + // variations. + // + // If a driver supports multiple GL_ARB_framebuffer_multisample-style extensions then we will + // assume the function pointers for the standard (or equivalent GL_ARB) version have + // been preferred over GL_EXT, GL_CHROMIUM, or GL_ANGLE variations that have reduced + // functionality. + + // GL_EXT_multisampled_render_to_texture (preferred) or GL_IMG_multisampled_render_to_texture + GLPtr fRenderbufferStorageMultisampleES2EXT; + // GL_APPLE_framebuffer_multisample + GLPtr fRenderbufferStorageMultisampleES2APPLE; + + // This is used to store the pointer for GL_ARB/EXT/ANGLE/CHROMIUM_framebuffer_multisample or + // the standard function in ES3+ or GL 3.0+. + GLPtr fRenderbufferStorageMultisample; + + // Pointer to BindUniformLocationCHROMIUM from the GL_CHROMIUM_bind_uniform_location extension. + GLPtr fBindUniformLocation; + + GLPtr fResolveMultisampleFramebuffer; + GLPtr fScissor; + GLPtr fShaderSource; + GLPtr fStencilFunc; + GLPtr fStencilFuncSeparate; + GLPtr fStencilMask; + GLPtr fStencilMaskSeparate; + GLPtr fStencilOp; + GLPtr fStencilOpSeparate; + GLPtr fTexGenf; + GLPtr fTexGenfv; + GLPtr fTexGeni; + GLPtr fTexImage2D; + GLPtr fTexParameteri; + GLPtr fTexParameteriv; + GLPtr fTexSubImage2D; + GLPtr fTexStorage2D; + GLPtr fDiscardFramebuffer; + GLPtr fUniform1f; + GLPtr fUniform1i; + GLPtr fUniform1fv; + GLPtr fUniform1iv; + GLPtr fUniform2f; + GLPtr fUniform2i; + GLPtr fUniform2fv; + GLPtr fUniform2iv; + GLPtr fUniform3f; + GLPtr fUniform3i; + GLPtr fUniform3fv; + GLPtr fUniform3iv; + GLPtr fUniform4f; + GLPtr fUniform4i; + GLPtr fUniform4fv; + GLPtr fUniform4iv; + GLPtr fUniformMatrix2fv; + GLPtr fUniformMatrix3fv; + GLPtr fUniformMatrix4fv; + GLPtr fUnmapBuffer; + GLPtr fUseProgram; + GLPtr fVertexAttrib4fv; + GLPtr fVertexAttribPointer; + GLPtr fVertexPointer; + GLPtr fViewport; + + // Experimental: Functions for GL_NV_path_rendering. These will be + // alphabetized with the above functions once this is fully supported + // (and functions we are unlikely to use will possibly be omitted). + GLPtr fPathCommands; + GLPtr fPathCoords; + GLPtr fPathSubCommands; + GLPtr fPathSubCoords; + GLPtr fPathString; + GLPtr fPathGlyphs; + GLPtr fPathGlyphRange; + GLPtr fWeightPaths; + GLPtr fCopyPath; + GLPtr fInterpolatePaths; + GLPtr fTransformPath; + GLPtr fPathParameteriv; + GLPtr fPathParameteri; + GLPtr fPathParameterfv; + GLPtr fPathParameterf; + GLPtr fPathDashArray; + GLPtr fGenPaths; + GLPtr fDeletePaths; + GLPtr fIsPath; + GLPtr fPathStencilFunc; + GLPtr fPathStencilDepthOffset; + GLPtr fStencilFillPath; + GLPtr fStencilStrokePath; + GLPtr fStencilFillPathInstanced; + GLPtr fStencilStrokePathInstanced; + GLPtr fPathCoverDepthFunc; + GLPtr fPathColorGen; + GLPtr fPathTexGen; + GLPtr fPathFogGen; + GLPtr fCoverFillPath; + GLPtr fCoverStrokePath; + GLPtr fCoverFillPathInstanced; + GLPtr fCoverStrokePathInstanced; + GLPtr fGetPathParameteriv; + GLPtr fGetPathParameterfv; + GLPtr fGetPathCommands; + GLPtr fGetPathCoords; + GLPtr fGetPathDashArray; + GLPtr fGetPathMetrics; + GLPtr fGetPathMetricRange; + GLPtr fGetPathSpacing; + GLPtr fGetPathColorGeniv; + GLPtr fGetPathColorGenfv; + GLPtr fGetPathTexGeniv; + GLPtr fGetPathTexGenfv; + GLPtr fIsPointInFillPath; + GLPtr fIsPointInStrokePath; + GLPtr fGetPathLength; + GLPtr fPointAlongPath; + } fFunctions; + + // Temporary workaround aliases to keep Chromium GrGLInterface factories compiling until they + // assign the members of fFunctions. + GLPtrAlias fActiveTexture; + GLPtrAlias fAttachShader; + GLPtrAlias fBeginQuery; + GLPtrAlias fBindAttribLocation; + GLPtrAlias fBindBuffer; + GLPtrAlias fBindFragDataLocation; + GLPtrAlias fBindFragDataLocationIndexed; + GLPtrAlias fBindFramebuffer; + GLPtrAlias fBindRenderbuffer; + GLPtrAlias fBindTexture; + GLPtrAlias fBindVertexArray; + GLPtrAlias fBlendColor; + GLPtrAlias fBlendFunc; + GLPtrAlias fBlitFramebuffer; + GLPtrAlias fBufferData; + GLPtrAlias fBufferSubData; + GLPtrAlias fCheckFramebufferStatus; + GLPtrAlias fClear; + GLPtrAlias fClearColor; + GLPtrAlias fClearStencil; + GLPtrAlias fClientActiveTexture; + GLPtrAlias fColorMask; + GLPtrAlias fCompileShader; + GLPtrAlias fCompressedTexImage2D; + GLPtrAlias fCopyTexSubImage2D; + GLPtrAlias fCreateProgram; + GLPtrAlias fCreateShader; + GLPtrAlias fCullFace; + GLPtrAlias fDeleteBuffers; + GLPtrAlias fDeleteFramebuffers; + GLPtrAlias fDeleteProgram; + GLPtrAlias fDeleteQueries; + GLPtrAlias fDeleteRenderbuffers; + GLPtrAlias fDeleteShader; + GLPtrAlias fDeleteTextures; + GLPtrAlias fDeleteVertexArrays; + GLPtrAlias fDepthMask; + GLPtrAlias fDisable; + GLPtrAlias fDisableClientState; + GLPtrAlias fDisableVertexAttribArray; + GLPtrAlias fDrawArrays; + GLPtrAlias fDrawBuffer; + GLPtrAlias fDrawBuffers; + GLPtrAlias fDrawElements; + GLPtrAlias fEnable; + GLPtrAlias fEnableClientState; + GLPtrAlias fEnableVertexAttribArray; + GLPtrAlias fEndQuery; + GLPtrAlias fFinish; + GLPtrAlias fFlush; + GLPtrAlias fFramebufferRenderbuffer; + GLPtrAlias fFramebufferTexture2D; + GLPtrAlias fFramebufferTexture2DMultisample; + GLPtrAlias fFrontFace; + GLPtrAlias fGenBuffers; + GLPtrAlias fGenFramebuffers; + GLPtrAlias fGenerateMipmap; + GLPtrAlias fGenQueries; + GLPtrAlias fGenRenderbuffers; + GLPtrAlias fGenTextures; + GLPtrAlias fGenVertexArrays; + GLPtrAlias fGetBufferParameteriv; + GLPtrAlias fGetError; + GLPtrAlias fGetFramebufferAttachmentParameteriv; + GLPtrAlias fGetIntegerv; + GLPtrAlias fGetQueryObjecti64v; + GLPtrAlias fGetQueryObjectiv; + GLPtrAlias fGetQueryObjectui64v; + GLPtrAlias fGetQueryObjectuiv; + GLPtrAlias fGetQueryiv; + GLPtrAlias fGetProgramInfoLog; + GLPtrAlias fGetProgramiv; + GLPtrAlias fGetRenderbufferParameteriv; + GLPtrAlias fGetShaderInfoLog; + GLPtrAlias fGetShaderiv; + GLPtrAlias fGetString; + GLPtrAlias fGetStringi; + GLPtrAlias fGetTexLevelParameteriv; + GLPtrAlias fGetUniformLocation; + GLPtrAlias fLineWidth; + GLPtrAlias fLinkProgram; + GLPtrAlias fLoadIdentity; + GLPtrAlias fLoadMatrixf; + GLPtrAlias fMapBuffer; + GLPtrAlias fMatrixMode; + GLPtrAlias fPixelStorei; + GLPtrAlias fQueryCounter; + GLPtrAlias fReadBuffer; + GLPtrAlias fReadPixels; + GLPtrAlias fRenderbufferStorage; + GLPtrAlias fRenderbufferStorageMultisampleES2EXT; + GLPtrAlias fRenderbufferStorageMultisampleES2APPLE; + GLPtrAlias fRenderbufferStorageMultisample; + GLPtrAlias fBindUniformLocation; + GLPtrAlias fResolveMultisampleFramebuffer; + GLPtrAlias fScissor; + GLPtrAlias fShaderSource; + GLPtrAlias fStencilFunc; + GLPtrAlias fStencilFuncSeparate; + GLPtrAlias fStencilMask; + GLPtrAlias fStencilMaskSeparate; + GLPtrAlias fStencilOp; + GLPtrAlias fStencilOpSeparate; + GLPtrAlias fTexGenf; + GLPtrAlias fTexGenfv; + GLPtrAlias fTexGeni; + GLPtrAlias fTexImage2D; + GLPtrAlias fTexParameteri; + GLPtrAlias fTexParameteriv; + GLPtrAlias fTexSubImage2D; + GLPtrAlias fTexStorage2D; + GLPtrAlias fDiscardFramebuffer; + GLPtrAlias fUniform1f; + GLPtrAlias fUniform1i; + GLPtrAlias fUniform1fv; + GLPtrAlias fUniform1iv; + GLPtrAlias fUniform2f; + GLPtrAlias fUniform2i; + GLPtrAlias fUniform2fv; + GLPtrAlias fUniform2iv; + GLPtrAlias fUniform3f; + GLPtrAlias fUniform3i; + GLPtrAlias fUniform3fv; + GLPtrAlias fUniform3iv; + GLPtrAlias fUniform4f; + GLPtrAlias fUniform4i; + GLPtrAlias fUniform4fv; + GLPtrAlias fUniform4iv; + GLPtrAlias fUniformMatrix2fv; + GLPtrAlias fUniformMatrix3fv; + GLPtrAlias fUniformMatrix4fv; + GLPtrAlias fUnmapBuffer; + GLPtrAlias fUseProgram; + GLPtrAlias fVertexAttrib4fv; + GLPtrAlias fVertexAttribPointer; + GLPtrAlias fVertexPointer; + GLPtrAlias fViewport; + GLPtrAlias fPathCommands; + GLPtrAlias fPathCoords; + GLPtrAlias fPathSubCommands; + GLPtrAlias fPathSubCoords; + GLPtrAlias fPathString; + GLPtrAlias fPathGlyphs; + GLPtrAlias fPathGlyphRange; + GLPtrAlias fWeightPaths; + GLPtrAlias fCopyPath; + GLPtrAlias fInterpolatePaths; + GLPtrAlias fTransformPath; + GLPtrAlias fPathParameteriv; + GLPtrAlias fPathParameteri; + GLPtrAlias fPathParameterfv; + GLPtrAlias fPathParameterf; + GLPtrAlias fPathDashArray; + GLPtrAlias fGenPaths; + GLPtrAlias fDeletePaths; + GLPtrAlias fIsPath; + GLPtrAlias fPathStencilFunc; + GLPtrAlias fPathStencilDepthOffset; + GLPtrAlias fStencilFillPath; + GLPtrAlias fStencilStrokePath; + GLPtrAlias fStencilFillPathInstanced; + GLPtrAlias fStencilStrokePathInstanced; + GLPtrAlias fPathCoverDepthFunc; + GLPtrAlias fPathColorGen; + GLPtrAlias fPathTexGen; + GLPtrAlias fPathFogGen; + GLPtrAlias fCoverFillPath; + GLPtrAlias fCoverStrokePath; + GLPtrAlias fCoverFillPathInstanced; + GLPtrAlias fCoverStrokePathInstanced; + GLPtrAlias fGetPathParameteriv; + GLPtrAlias fGetPathParameterfv; + GLPtrAlias fGetPathCommands; + GLPtrAlias fGetPathCoords; + GLPtrAlias fGetPathDashArray; + GLPtrAlias fGetPathMetrics; + GLPtrAlias fGetPathMetricRange; + GLPtrAlias fGetPathSpacing; + GLPtrAlias fGetPathColorGeniv; + GLPtrAlias fGetPathColorGenfv; + GLPtrAlias fGetPathTexGeniv; + GLPtrAlias fGetPathTexGenfv; + GLPtrAlias fIsPointInFillPath; + GLPtrAlias fIsPointInStrokePath; + GLPtrAlias fGetPathLength; + GLPtrAlias fPointAlongPath; + + // Per-GL func callback +#if GR_GL_PER_GL_FUNC_CALLBACK + GrGLInterfaceCallbackProc fCallback; + GrGLInterfaceCallbackData fCallbackData; +#endif + +}; + +#endif diff --git a/gfx/skia/include/gpu/gl/SkANGLEGLContext.h b/gfx/skia/trunk/include/gpu/gl/SkANGLEGLContext.h similarity index 94% rename from gfx/skia/include/gpu/gl/SkANGLEGLContext.h rename to gfx/skia/trunk/include/gpu/gl/SkANGLEGLContext.h index 63765a0131fc..99ef4e9a9964 100644 --- a/gfx/skia/include/gpu/gl/SkANGLEGLContext.h +++ b/gfx/skia/trunk/include/gpu/gl/SkANGLEGLContext.h @@ -22,6 +22,7 @@ public: virtual ~SkANGLEGLContext(); virtual void makeCurrent() const SK_OVERRIDE; + virtual void swapBuffers() const SK_OVERRIDE; class AutoContextRestore { public: diff --git a/gfx/skia/include/gpu/gl/SkDebugGLContext.h b/gfx/skia/trunk/include/gpu/gl/SkDebugGLContext.h similarity index 90% rename from gfx/skia/include/gpu/gl/SkDebugGLContext.h rename to gfx/skia/trunk/include/gpu/gl/SkDebugGLContext.h index 2437aaeb5f19..545ef40027af 100644 --- a/gfx/skia/include/gpu/gl/SkDebugGLContext.h +++ b/gfx/skia/trunk/include/gpu/gl/SkDebugGLContext.h @@ -16,6 +16,7 @@ public: SkDebugGLContext() {}; virtual void makeCurrent() const SK_OVERRIDE {}; + virtual void swapBuffers() const SK_OVERRIDE {}; protected: virtual const GrGLInterface* createGLContext() SK_OVERRIDE; diff --git a/gfx/skia/include/gpu/gl/SkGLContextHelper.h b/gfx/skia/trunk/include/gpu/gl/SkGLContextHelper.h similarity index 58% rename from gfx/skia/include/gpu/gl/SkGLContextHelper.h rename to gfx/skia/trunk/include/gpu/gl/SkGLContextHelper.h index 386a6958fb6e..ea940c8bc05e 100644 --- a/gfx/skia/include/gpu/gl/SkGLContextHelper.h +++ b/gfx/skia/trunk/include/gpu/gl/SkGLContextHelper.h @@ -8,7 +8,6 @@ #ifndef SkGLContextHelper_DEFINED #define SkGLContextHelper_DEFINED -#include "GrGLExtensions.h" #include "GrGLInterface.h" /** @@ -16,7 +15,7 @@ * Provides a GrGLInterface struct of function pointers for the context. */ -class SkGLContextHelper : public SkRefCnt { +class SK_API SkGLContextHelper : public SkRefCnt { public: SK_DECLARE_INST_COUNT(SkGLContextHelper) @@ -34,9 +33,21 @@ public: virtual void makeCurrent() const = 0; + /** + * The primary purpose of this function it to provide a means of scheduling + * work on the GPU (since all of the subclasses create primary buffers for + * testing that are small and not meant to be rendered to the screen). + * + * If the drawing surface provided by the platform is double buffered this + * call will cause the platform to swap which buffer is currently being + * targeted. If the current surface does not include a back buffer, this + * call has no effect. + */ + virtual void swapBuffers() const = 0; + bool hasExtension(const char* extensionName) const { - GrAssert(NULL != fGL); - return fExtensions.has(extensionName); + SkASSERT(NULL != fGL); + return fGL->hasExtension(extensionName); } protected: @@ -54,7 +65,6 @@ protected: virtual void destroyGLContext() = 0; private: - GrGLExtensions fExtensions; GrGLuint fFBO; GrGLuint fColorBufferID; GrGLuint fDepthStencilBufferID; @@ -67,11 +77,11 @@ private: * Helper macros for using the GL context through the GrGLInterface. Example: * SK_GL(glCtx, GenTextures(1, &texID)); */ -#define SK_GL(ctx, X) (ctx).gl()->f ## X; \ - SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fGetError()) -#define SK_GL_RET(ctx, RET, X) (RET) = (ctx).gl()->f ## X; \ - SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fGetError()) -#define SK_GL_NOERRCHECK(ctx, X) (ctx).gl()->f ## X -#define SK_GL_RET_NOERRCHECK(ctx, RET, X) (RET) = (ctx).gl()->f ## X +#define SK_GL(ctx, X) (ctx).gl()->fFunctions.f ## X; \ + SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fFunctions.fGetError()) +#define SK_GL_RET(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X; \ + SkASSERT(GR_GL_NO_ERROR == (ctx).gl()->fFunctions.fGetError()) +#define SK_GL_NOERRCHECK(ctx, X) (ctx).gl()->fFunctions.f ## X +#define SK_GL_RET_NOERRCHECK(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X #endif diff --git a/gfx/skia/include/gpu/gl/SkMesaGLContext.h b/gfx/skia/trunk/include/gpu/gl/SkMesaGLContext.h similarity index 94% rename from gfx/skia/include/gpu/gl/SkMesaGLContext.h rename to gfx/skia/trunk/include/gpu/gl/SkMesaGLContext.h index 6470d2eef09c..55235fa6032a 100644 --- a/gfx/skia/include/gpu/gl/SkMesaGLContext.h +++ b/gfx/skia/trunk/include/gpu/gl/SkMesaGLContext.h @@ -22,6 +22,7 @@ public: virtual ~SkMesaGLContext(); virtual void makeCurrent() const SK_OVERRIDE; + virtual void swapBuffers() const SK_OVERRIDE; class AutoContextRestore { public: diff --git a/gfx/skia/include/gpu/gl/SkNativeGLContext.h b/gfx/skia/trunk/include/gpu/gl/SkNativeGLContext.h similarity index 96% rename from gfx/skia/include/gpu/gl/SkNativeGLContext.h rename to gfx/skia/trunk/include/gpu/gl/SkNativeGLContext.h index 27a8f09bacb3..7254de1509cf 100644 --- a/gfx/skia/include/gpu/gl/SkNativeGLContext.h +++ b/gfx/skia/trunk/include/gpu/gl/SkNativeGLContext.h @@ -19,7 +19,7 @@ #include #include #elif defined(SK_BUILD_FOR_WIN32) - #include + #include #include #endif @@ -30,6 +30,7 @@ public: virtual ~SkNativeGLContext(); virtual void makeCurrent() const SK_OVERRIDE; + virtual void swapBuffers() const SK_OVERRIDE; class AutoContextRestore { public: diff --git a/gfx/skia/include/gpu/gl/SkNullGLContext.h b/gfx/skia/trunk/include/gpu/gl/SkNullGLContext.h similarity index 80% rename from gfx/skia/include/gpu/gl/SkNullGLContext.h rename to gfx/skia/trunk/include/gpu/gl/SkNullGLContext.h index 4f2639c8d7c0..02d968eeff4b 100644 --- a/gfx/skia/include/gpu/gl/SkNullGLContext.h +++ b/gfx/skia/trunk/include/gpu/gl/SkNullGLContext.h @@ -10,13 +10,15 @@ #include "SkGLContextHelper.h" -class SkNullGLContext : public SkGLContextHelper { +class SK_API SkNullGLContext : public SkGLContextHelper { public: SkNullGLContext() {}; virtual void makeCurrent() const SK_OVERRIDE {}; + virtual void swapBuffers() const SK_OVERRIDE {}; + protected: virtual const GrGLInterface* createGLContext() SK_OVERRIDE; diff --git a/gfx/skia/trunk/include/images/SkForceLinking.h b/gfx/skia/trunk/include/images/SkForceLinking.h new file mode 100644 index 000000000000..39901f612ed2 --- /dev/null +++ b/gfx/skia/trunk/include/images/SkForceLinking.h @@ -0,0 +1,20 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * This function's sole purpose is to trick the linker into not discarding + * SkImageDecoder subclasses just because we do not directly call them. + * This is necessary in applications that will create image decoders from + * a stream. + * Call this function with an expression that evaluates to false to ensure + * that the linker includes the subclasses. + * Passing true will result in leaked objects. + */ +int SkForceLinking(bool doNotPassTrue); + +#define __SK_FORCE_IMAGE_DECODER_LINKING \ +static int linking_forced = SkForceLinking(false) diff --git a/gfx/skia/include/images/SkImageRef.h b/gfx/skia/trunk/include/images/SkImageRef.h similarity index 84% rename from gfx/skia/include/images/SkImageRef.h rename to gfx/skia/trunk/include/images/SkImageRef.h index bca4305b5bf3..ec14456fac50 100644 --- a/gfx/skia/include/images/SkImageRef.h +++ b/gfx/skia/trunk/include/images/SkImageRef.h @@ -16,7 +16,7 @@ #include "SkString.h" class SkImageRefPool; -class SkStream; +class SkStreamRewindable; // define this to enable dumping whenever we add/remove/purge an imageref //#define DUMP_IMAGEREF_LIFECYCLE @@ -34,7 +34,8 @@ public: @param config The preferred config of the decoded bitmap. @param sampleSize Requested sampleSize for decoding. Defaults to 1. */ - SkImageRef(SkStream*, SkBitmap::Config config, int sampleSize = 1, SkBaseMutex* mutex = NULL); + SkImageRef(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1, + SkBaseMutex* mutex = NULL); virtual ~SkImageRef(); /** this value is passed onto the decoder. Default is true @@ -64,31 +65,30 @@ protected: /** Override if you want to install a custom allocator. When this is called we will have already acquired the mutex! */ - virtual bool onDecode(SkImageDecoder* codec, SkStream*, SkBitmap*, + virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable*, SkBitmap*, SkBitmap::Config, SkImageDecoder::Mode); /* Overrides from SkPixelRef When these are called, we will have already acquired the mutex! */ - virtual void* onLockPixels(SkColorTable**); + virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE; // override this in your subclass to clean up when we're unlocking pixels - virtual void onUnlockPixels() {} + virtual void onUnlockPixels() SK_OVERRIDE {} - SkImageRef(SkFlattenableReadBuffer&, SkBaseMutex* mutex = NULL); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkImageRef(SkReadBuffer&, SkBaseMutex* mutex = NULL); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; SkBitmap fBitmap; private: - SkStream* setStream(SkStream*); + SkStreamRewindable* setStream(SkStreamRewindable*); // called with mutex already held. returns true if the bitmap is in the // requested state (or further, i.e. has pixels) bool prepareBitmap(SkImageDecoder::Mode); SkImageDecoderFactory* fFactory; // may be null - SkStream* fStream; - SkBitmap::Config fConfig; + SkStreamRewindable* fStream; int fSampleSize; bool fDoDither; bool fErrorInDecoding; diff --git a/gfx/skia/include/images/SkImageRef_GlobalPool.h b/gfx/skia/trunk/include/images/SkImageRef_GlobalPool.h similarity index 86% rename from gfx/skia/include/images/SkImageRef_GlobalPool.h rename to gfx/skia/trunk/include/images/SkImageRef_GlobalPool.h index 914b0eb4350d..7b99a6e53d41 100644 --- a/gfx/skia/include/images/SkImageRef_GlobalPool.h +++ b/gfx/skia/trunk/include/images/SkImageRef_GlobalPool.h @@ -15,7 +15,8 @@ class SkImageRef_GlobalPool : public SkImageRef { public: // if pool is null, use the global pool - SkImageRef_GlobalPool(SkStream*, SkBitmap::Config, int sampleSize = 1); + SkImageRef_GlobalPool(const SkImageInfo&, SkStreamRewindable*, + int sampleSize = 1); virtual ~SkImageRef_GlobalPool(); SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_GlobalPool) @@ -46,13 +47,13 @@ public: static void DumpPool(); protected: - virtual bool onDecode(SkImageDecoder* codec, SkStream* stream, + virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, SkBitmap* bitmap, SkBitmap::Config config, SkImageDecoder::Mode mode); virtual void onUnlockPixels(); - SkImageRef_GlobalPool(SkFlattenableReadBuffer&); + SkImageRef_GlobalPool(SkReadBuffer&); private: typedef SkImageRef INHERITED; diff --git a/gfx/skia/include/images/SkImages.h b/gfx/skia/trunk/include/images/SkImages.h similarity index 82% rename from gfx/skia/include/images/SkImages.h rename to gfx/skia/trunk/include/images/SkImages.h index f28b05624232..abe10da66493 100644 --- a/gfx/skia/include/images/SkImages.h +++ b/gfx/skia/trunk/include/images/SkImages.h @@ -5,9 +5,6 @@ * found in the LICENSE file. */ -#ifndef SkImages_DEFINED -#define SkImages_DEFINED - class SkImages { public: /** @@ -15,5 +12,3 @@ public: */ static void InitializeFlattenables(); }; - -#endif diff --git a/gfx/skia/include/images/SkMovie.h b/gfx/skia/trunk/include/images/SkMovie.h similarity index 96% rename from gfx/skia/include/images/SkMovie.h rename to gfx/skia/trunk/include/images/SkMovie.h index f32d6094b273..e52a3a8f4040 100644 --- a/gfx/skia/include/images/SkMovie.h +++ b/gfx/skia/trunk/include/images/SkMovie.h @@ -13,7 +13,7 @@ #include "SkRefCnt.h" #include "SkCanvas.h" -class SkStream; +class SkStreamRewindable; class SkMovie : public SkRefCnt { public: @@ -22,7 +22,7 @@ public: /** Try to create a movie from the stream. If the stream format is not supported, return NULL. */ - static SkMovie* DecodeStream(SkStream*); + static SkMovie* DecodeStream(SkStreamRewindable*); /** Try to create a movie from the specified file path. If the file is not found, or the format is not supported, return NULL. If a movie is returned, the stream may be retained by the movie (via ref()) until diff --git a/gfx/skia/include/images/SkPageFlipper.h b/gfx/skia/trunk/include/images/SkPageFlipper.h similarity index 100% rename from gfx/skia/include/images/SkPageFlipper.h rename to gfx/skia/trunk/include/images/SkPageFlipper.h diff --git a/gfx/skia/trunk/include/pathops/SkPathOps.h b/gfx/skia/trunk/include/pathops/SkPathOps.h new file mode 100644 index 000000000000..a98f4ea4d6d5 --- /dev/null +++ b/gfx/skia/trunk/include/pathops/SkPathOps.h @@ -0,0 +1,57 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef SkPathOps_DEFINED +#define SkPathOps_DEFINED + +#include "SkPreConfig.h" + +class SkPath; + +// FIXME: move everything below into the SkPath class +/** + * The logical operations that can be performed when combining two paths. + */ +enum SkPathOp { + kDifference_PathOp, //!< subtract the op path from the first path + kIntersect_PathOp, //!< intersect the two paths + kUnion_PathOp, //!< union (inclusive-or) the two paths + kXOR_PathOp, //!< exclusive-or the two paths + kReverseDifference_PathOp, //!< subtract the first path from the op path +}; + +/** Set this path to the result of applying the Op to this path and the + specified path: this = (this op operand). + The resulting path will be constructed from non-overlapping contours. + The curve order is reduced where possible so that cubics may be turned + into quadratics, and quadratics maybe turned into lines. + + Returns true if operation was able to produce a result; + otherwise, result is unmodified. + + @param one The first operand (for difference, the minuend) + @param two The second operand (for difference, the subtrahend) + @param result The product of the operands. The result may be one of the + inputs. + @return True if operation succeeded. + */ +bool SK_API Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result); + +/** Set this path to a set of non-overlapping contours that describe the + same area as the original path. + The curve order is reduced where possible so that cubics may + be turned into quadratics, and quadratics maybe turned into lines. + + Returns true if operation was able to produce a result; + otherwise, result is unmodified. + + @param path The path to simplify. + @param result The simplified path. The result may be the input. + @return True if simplification succeeded. + */ +bool SK_API Simplify(const SkPath& path, SkPath* result); + +#endif diff --git a/gfx/skia/include/pdf/SkPDFDevice.h b/gfx/skia/trunk/include/pdf/SkPDFDevice.h similarity index 75% rename from gfx/skia/include/pdf/SkPDFDevice.h rename to gfx/skia/trunk/include/pdf/SkPDFDevice.h index f8261b5da10f..9b21f8f90a22 100644 --- a/gfx/skia/include/pdf/SkPDFDevice.h +++ b/gfx/skia/trunk/include/pdf/SkPDFDevice.h @@ -10,15 +10,17 @@ #ifndef SkPDFDevice_DEFINED #define SkPDFDevice_DEFINED +#include "SkBitmapDevice.h" +#include "SkBitmap.h" #include "SkCanvas.h" -#include "SkDevice.h" #include "SkPaint.h" #include "SkPath.h" +#include "SkPicture.h" #include "SkRect.h" #include "SkRefCnt.h" #include "SkStream.h" #include "SkTDArray.h" -#include "SkTScopedPtr.h" +#include "SkTemplates.h" class SkPDFArray; class SkPDFDevice; @@ -28,9 +30,11 @@ class SkPDFFormXObject; class SkPDFGlyphSetMap; class SkPDFGraphicState; class SkPDFObject; +class SkPDFResourceDict; class SkPDFShader; class SkPDFStream; -template class SK_API SkTSet; +class SkRRect; +template class SkTSet; // Private classes. struct ContentEntry; @@ -41,7 +45,7 @@ struct NamedDestination; The drawing context for the PDF backend. */ -class SkPDFDevice : public SkDevice { +class SkPDFDevice : public SkBitmapDevice { public: /** Create a PDF drawing context with the given width and height. * 72 points/in means letter paper is 612x792. @@ -61,7 +65,7 @@ public: * inverse scale+translate to accommodate the one that SkPDFDevice * always does. */ - // TODO(vandebo): The sizes should be SkSize and not SkISize. + // Deprecated, please use SkDocument::CreatePdf() instead. SK_API SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize, const SkMatrix& initialTransform); SK_API virtual ~SkPDFDevice(); @@ -80,14 +84,16 @@ public: size_t count, const SkPoint[], const SkPaint& paint) SK_OVERRIDE; virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint); + virtual void drawRRect(const SkDraw&, const SkRRect& rr, + const SkPaint& paint) SK_OVERRIDE; virtual void drawPath(const SkDraw&, const SkPath& origpath, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) SK_OVERRIDE; virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, - const SkPaint& paint) SK_OVERRIDE; + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, - const SkIRect* srcRectOrNull, const SkMatrix& matrix, const SkPaint&) SK_OVERRIDE; virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) SK_OVERRIDE; @@ -104,7 +110,7 @@ public: const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) SK_OVERRIDE; - virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) SK_OVERRIDE; virtual void onAttachToCanvas(SkCanvas* canvas) SK_OVERRIDE; @@ -126,27 +132,26 @@ public: */ SK_API void setDrawingArea(DrawingArea drawingArea); + /** Sets the DCTEncoder for images. + * @param encoder The encoder to encode a bitmap as JPEG (DCT). + * Result of encodings are cached, if the encoder changes the + * behaivor dynamically and an image is added to a second catalog, + * we will likely use the result of the first encoding call. + * By returning false from the encoder function, the encoder result + * is not used. + * Callers might not want to encode small images, as the time spent + * encoding and decoding might not be worth the space savings, + * if any at all. + */ + void setDCTEncoder(SkPicture::EncodeBitmap encoder) { + fEncoder = encoder; + } + // PDF specific methods. /** Returns the resource dictionary for this device. */ - SK_API SkPDFDict* getResourceDict(); - - /** Get the list of resources (PDF objects) used on this page. - * This method will add to newResourceObjects any objects that this method - * depends on, but not already in knownResourceObjects. This might operate - * recursively so if this object depends on another object and that object - * depends on two more, all three objects will be added. - * - * @param knownResourceObjects The set of resources to be ignored. - * @param newResourceObjects The set to append dependant resources to. - * @param recursive If recursive is true, get the resources of the - * device's resources recursively. (Useful for adding - * objects to the catalog.) - */ - SK_API void getResources(const SkTSet& knownResourceObjects, - SkTSet* newResourceObjects, - bool recursive) const; + SK_API SkPDFResourceDict* getResourceDict(); /** Get the fonts used on this device. */ @@ -189,11 +194,26 @@ public: return *(fFontGlyphUsage.get()); } + + /** + * rasterDpi - the DPI at which features without native PDF support + * will be rasterized (e.g. draw image with perspective, + * draw text with perspective, ...) + * A larger DPI would create a PDF that reflects the original + * intent with better fidelity, but it can make for larger + * PDF files too, which would use more memory while rendering, + * and it would be slower to be processed or sent online or + * to printer. + */ + void setRasterDpi(SkScalar rasterDpi) { + fRasterDpi = rasterDpi; + } + protected: virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888) SK_OVERRIDE; - virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE; + virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE; private: // TODO(vandebo): push most of SkPDFDevice's state into a core object in @@ -206,7 +226,7 @@ private: SkClipStack fExistingClipStack; SkRegion fExistingClipRegion; SkPDFArray* fAnnotations; - SkPDFDict* fResourceDict; + SkPDFResourceDict* fResourceDict; SkTDArray fNamedDestinations; SkTDArray fGraphicStateResources; @@ -214,41 +234,43 @@ private: SkTDArray fFontResources; SkTDArray fShaderResources; - SkTScopedPtr fContentEntries; + SkAutoTDelete fContentEntries; ContentEntry* fLastContentEntry; - SkTScopedPtr fMarginContentEntries; + SkAutoTDelete fMarginContentEntries; ContentEntry* fLastMarginContentEntry; DrawingArea fDrawingArea; const SkClipStack* fClipStack; // Accessor and setter functions based on the current DrawingArea. - SkTScopedPtr* getContentEntries(); + SkAutoTDelete* getContentEntries(); ContentEntry* getLastContentEntry(); void setLastContentEntry(ContentEntry* contentEntry); // Glyph ids used for each font on this device. - SkTScopedPtr fFontGlyphUsage; + SkAutoTDelete fFontGlyphUsage; + + SkPicture::EncodeBitmap fEncoder; + SkScalar fRasterDpi; SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack, const SkRegion& existingClipRegion); - // override from SkDevice - virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque, - Usage usage) SK_OVERRIDE; + // override from SkBaseDevice + virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) SK_OVERRIDE; void init(); void cleanUp(bool clearFontUsage); SkPDFFormXObject* createFormXObjectFromDevice(); - // Clear the passed clip from all existing content entries. - void clearClipFromContent(const SkClipStack* clipStack, - const SkRegion& clipRegion); - void drawFormXObjectWithClip(SkPDFFormXObject* form, + void drawFormXObjectWithMask(int xObjectIndex, + SkPDFFormXObject* mask, const SkClipStack* clipStack, const SkRegion& clipRegion, + SkXfermode::Mode mode, bool invertClip); // If the paint or clip is such that we shouldn't draw anything, this @@ -262,7 +284,8 @@ private: bool hasText, SkPDFFormXObject** dst); void finishContentEntry(SkXfermode::Mode xfermode, - SkPDFFormXObject* dst); + SkPDFFormXObject* dst, + SkPath* shape); bool isContentEmpty(); void populateGraphicStateEntryFromPaint(const SkMatrix& matrix, @@ -272,6 +295,7 @@ private: bool hasText, GraphicStateEntry* entry); int addGraphicStateResource(SkPDFGraphicState* gs); + int addXObjectResource(SkPDFObject* xObject); void updateFont(const SkPaint& paint, uint16_t glyphID, ContentEntry* contentEntry); @@ -290,6 +314,11 @@ private: */ void copyContentEntriesToData(ContentEntry* entry, SkWStream* data) const; +#ifdef SK_PDF_USE_PATHOPS + bool handleInversePath(const SkDraw& d, const SkPath& origPath, + const SkPaint& paint, bool pathIsMutable, + const SkMatrix* prePathMatrix = NULL); +#endif bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, const SkPaint& paint); bool handlePointAnnotation(const SkPoint* points, size_t count, @@ -302,7 +331,12 @@ private: void defineNamedDestination(SkData* nameData, const SkPoint& point, const SkMatrix& matrix); - typedef SkDevice INHERITED; + typedef SkBitmapDevice INHERITED; + + // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create + // an SkPDFDevice + //friend class SkDocument_PDF; + //friend class SkPDFImageShader; }; #endif diff --git a/gfx/skia/include/pdf/SkPDFDocument.h b/gfx/skia/trunk/include/pdf/SkPDFDocument.h similarity index 95% rename from gfx/skia/include/pdf/SkPDFDocument.h rename to gfx/skia/trunk/include/pdf/SkPDFDocument.h index 8f4ee485642a..9f651fdcedb0 100644 --- a/gfx/skia/include/pdf/SkPDFDocument.h +++ b/gfx/skia/trunk/include/pdf/SkPDFDocument.h @@ -13,7 +13,7 @@ #include "SkAdvancedTypefaceMetrics.h" #include "SkRefCnt.h" #include "SkTDArray.h" -#include "SkTScopedPtr.h" +#include "SkTemplates.h" class SkPDFCatalog; class SkPDFDevice; @@ -21,7 +21,7 @@ class SkPDFDict; class SkPDFPage; class SkPDFObject; class SkWStream; -template class SK_API SkTSet; +template class SkTSet; /** \class SkPDFDocument @@ -74,7 +74,7 @@ public: int counts[SkAdvancedTypefaceMetrics::kNotEmbeddable_Font + 1]) const; private: - SkTScopedPtr fCatalog; + SkAutoTDelete fCatalog; int64_t fXRefFileOffset; SkTDArray fPages; @@ -83,7 +83,6 @@ private: SkTSet* fFirstPageResources; SkTSet* fOtherPageResources; SkTDArray fSubstitutes; - int fSecondPageFirstResourceIndex; SkPDFDict* fTrailerDict; diff --git a/gfx/skia/include/pipe/SkGPipe.h b/gfx/skia/trunk/include/pipe/SkGPipe.h similarity index 93% rename from gfx/skia/include/pipe/SkGPipe.h rename to gfx/skia/trunk/include/pipe/SkGPipe.h index 27af16db8c13..879ab043ff51 100644 --- a/gfx/skia/include/pipe/SkGPipe.h +++ b/gfx/skia/trunk/include/pipe/SkGPipe.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -11,8 +10,9 @@ #ifndef SkGPipe_DEFINED #define SkGPipe_DEFINED -#include "SkWriter32.h" #include "SkFlattenable.h" +#include "SkPicture.h" +#include "SkWriter32.h" class SkCanvas; @@ -40,13 +40,20 @@ public: }; void setCanvas(SkCanvas*); + + /** + * Set a function for decoding bitmaps that have encoded data. + */ + void setBitmapDecoder(SkPicture::InstallPixelRefProc proc) { fProc = proc; } + // data must be 4-byte aligned // length must be a multiple of 4 Status playback(const void* data, size_t length, uint32_t playbackFlags = 0, size_t* bytesRead = NULL); private: - SkCanvas* fCanvas; - class SkGPipeState* fState; + SkCanvas* fCanvas; + class SkGPipeState* fState; + SkPicture::InstallPixelRefProc fProc; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/gfx/skia/include/ports/SkFontConfigInterface.h b/gfx/skia/trunk/include/ports/SkFontConfigInterface.h similarity index 75% rename from gfx/skia/include/ports/SkFontConfigInterface.h rename to gfx/skia/trunk/include/ports/SkFontConfigInterface.h index 0769362c8b31..8c12a5628ad0 100644 --- a/gfx/skia/include/ports/SkFontConfigInterface.h +++ b/gfx/skia/trunk/include/ports/SkFontConfigInterface.h @@ -8,7 +8,10 @@ #ifndef SkFontConfigInterface_DEFINED #define SkFontConfigInterface_DEFINED +#include "SkDataTable.h" +#include "SkFontStyle.h" #include "SkRefCnt.h" +#include "SkTArray.h" #include "SkTypeface.h" /** @@ -19,6 +22,8 @@ */ class SK_API SkFontConfigInterface : public SkRefCnt { public: + SK_DECLARE_INST_COUNT(SkFontConfigInterface) + /** * Returns the global SkFontConfigInterface instance, and if it is not * NULL, calls ref() on it. The caller must balance this with a call to @@ -46,10 +51,21 @@ public: fTTCIndex == other.fTTCIndex && fString == other.fString; } + bool operator!=(const FontIdentity& other) const { + return !(*this == other); + } uint32_t fID; int32_t fTTCIndex; SkString fString; + SkFontStyle fStyle; + + // If buffer is NULL, just return the number of bytes that would have + // been written. Will pad contents to a multiple of 4. + size_t writeToMemory(void* buffer = NULL) const; + + // Recreate from a flattened buffer, returning the number of bytes read. + size_t readFromMemory(const void* buffer, size_t length); }; /** @@ -81,6 +97,16 @@ public: * libfontconfig. This does not affect the refcnt of the returned instance. */ static SkFontConfigInterface* GetSingletonDirectInterface(); + + // New APIS, which have default impls for now (which do nothing) + + virtual SkDataTable* getFamilyNames() { return SkDataTable::NewEmpty(); } + virtual bool matchFamilySet(const char inFamilyName[], + SkString* outFamilyName, + SkTArray*) { + return false; + } + typedef SkRefCnt INHERITED; }; #endif diff --git a/gfx/skia/include/ports/SkFontMgr.h b/gfx/skia/trunk/include/ports/SkFontMgr.h similarity index 62% rename from gfx/skia/include/ports/SkFontMgr.h rename to gfx/skia/trunk/include/ports/SkFontMgr.h index 3160f80acb6c..df57aa762216 100644 --- a/gfx/skia/include/ports/SkFontMgr.h +++ b/gfx/skia/trunk/include/ports/SkFontMgr.h @@ -14,24 +14,38 @@ class SkData; class SkStream; class SkString; +class SkTypeface; -class SkFontStyleSet : public SkRefCnt { +class SK_API SkFontStyleSet : public SkRefCnt { public: + SK_DECLARE_INST_COUNT(SkFontStyleSet) + virtual int count() = 0; virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0; virtual SkTypeface* createTypeface(int index) = 0; virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0; static SkFontStyleSet* CreateEmpty(); + +private: + typedef SkRefCnt INHERITED; }; -class SkFontMgr : public SkRefCnt { -public: - int countFamilies(); - void getFamilyName(int index, SkString* familyName); - SkFontStyleSet* createStyleSet(int index); +class SkTypeface; - SkFontStyleSet* matchFamily(const char familyName[]); +class SK_API SkFontMgr : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkFontMgr) + + int countFamilies() const; + void getFamilyName(int index, SkString* familyName) const; + SkFontStyleSet* createStyleSet(int index) const; + + /** + * The caller must call unref() on the returned object. + * Never returns NULL; will return an empty set if the name is not found. + */ + SkFontStyleSet* matchFamily(const char familyName[]) const; /** * Find the closest matching typeface to the specified familyName and style @@ -39,23 +53,23 @@ public: * object. Will never return NULL, as it will return the default font if * no matching font is found. */ - SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&); + SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&) const; - SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&); + SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&) const; /** * Create a typeface for the specified data and TTC index (pass 0 for none) * or NULL if the data is not recognized. The caller must call unref() on * the returned object if it is not null. */ - SkTypeface* createFromData(SkData*, int ttcIndex = 0); + SkTypeface* createFromData(SkData*, int ttcIndex = 0) const; /** * Create a typeface for the specified stream and TTC index * (pass 0 for none) or NULL if the stream is not recognized. The caller * must call unref() on the returned object if it is not null. */ - SkTypeface* createFromStream(SkStream*, int ttcIndex = 0); + SkTypeface* createFromStream(SkStream*, int ttcIndex = 0) const; /** * Create a typeface for the specified fileName and TTC index @@ -63,7 +77,10 @@ public: * not recognized. The caller must call unref() on the returned object * if it is not null. */ - SkTypeface* createFromFile(const char path[], int ttcIndex = 0); + SkTypeface* createFromFile(const char path[], int ttcIndex = 0) const; + + SkTypeface* legacyCreateTypeface(const char familyName[], + unsigned typefaceStyleBits) const; /** * Return a ref to the default fontmgr. The caller must call unref() on @@ -72,24 +89,27 @@ public: static SkFontMgr* RefDefault(); protected: - virtual int onCountFamilies() = 0; - virtual void onGetFamilyName(int index, SkString* familyName) = 0; - virtual SkFontStyleSet* onCreateStyleSet(int index) = 0; + virtual int onCountFamilies() const = 0; + virtual void onGetFamilyName(int index, SkString* familyName) const = 0; + virtual SkFontStyleSet* onCreateStyleSet(int index)const = 0; - virtual SkFontStyleSet* onMatchFamily(const char familyName[]) = 0; + /** May return NULL if the name is not found. */ + virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const = 0; virtual SkTypeface* onMatchFamilyStyle(const char familyName[], - const SkFontStyle&) = 0; + const SkFontStyle&) const = 0; virtual SkTypeface* onMatchFaceStyle(const SkTypeface*, - const SkFontStyle&) = 0; + const SkFontStyle&) const = 0; - virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) = 0; - virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) = 0; - virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) = 0; + virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) const = 0; + virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) const = 0; + virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const = 0; + virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], + unsigned styleBits) const = 0; private: static SkFontMgr* Factory(); // implemented by porting layer - static SkMutex* Mutex(); // implemented by porting layer + friend void set_up_default(SkFontMgr** singleton); typedef SkRefCnt INHERITED; }; diff --git a/gfx/skia/include/ports/SkFontStyle.h b/gfx/skia/trunk/include/ports/SkFontStyle.h similarity index 94% rename from gfx/skia/include/ports/SkFontStyle.h rename to gfx/skia/trunk/include/ports/SkFontStyle.h index 1279024b2ed3..9d9a912d7d74 100644 --- a/gfx/skia/include/ports/SkFontStyle.h +++ b/gfx/skia/trunk/include/ports/SkFontStyle.h @@ -10,7 +10,7 @@ #include "SkTypes.h" -class SkFontStyle { +class SK_API SkFontStyle { public: enum Weight { kThin_Weight = 100, @@ -50,6 +50,7 @@ public: int weight() const { return fUnion.fR.fWeight; } int width() const { return fUnion.fR.fWidth; } + Slant slant() const { return (Slant)fUnion.fR.fSlant; } bool isItalic() const { return kItalic_Slant == fUnion.fR.fSlant; diff --git a/gfx/skia/include/ports/SkHarfBuzzFont.h b/gfx/skia/trunk/include/ports/SkHarfBuzzFont.h similarity index 100% rename from gfx/skia/include/ports/SkHarfBuzzFont.h rename to gfx/skia/trunk/include/ports/SkHarfBuzzFont.h diff --git a/gfx/skia/trunk/include/ports/SkTypeface_android.h b/gfx/skia/trunk/include/ports/SkTypeface_android.h new file mode 100644 index 000000000000..2e04414f5ac0 --- /dev/null +++ b/gfx/skia/trunk/include/ports/SkTypeface_android.h @@ -0,0 +1,108 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkTypeface_android_DEFINED +#define SkTypeface_android_DEFINED + +#include "SkTypeface.h" + +#ifdef SK_BUILD_FOR_ANDROID + +class SkPaintOptionsAndroid; + +/** + * Get the family name of the font in the fallback font list containing + * the specified character using the system's default language. This function + * also assumes the only families with the elegant or default variants will be + * returned. + * + * @param uni The unicode character to use for the lookup. + * @param name The family name of the font file containing the unicode character + * in the default language + * @return true if a font is found and false otherwise + */ +SK_API bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name); + +/** + * Get the family name of the font in the fallback font list containing + * the specified character taking into account the provided language. This + * function also assumes the only families with the elegant or default variants + * will be returned. + * + * @param uni The unicode character to use for the lookup. + * @param lang The null terminated string representing the BCP 47 language + * identifier for the preferred language. If there is no unique + * fallback chain for that language the system's default language + * will be used. + * @param name The family name of the font file containing the unicode character + * in the preferred language + * @return true if a font is found and false otherwise + */ +SK_API bool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name); + +/** + * For test only. + * Load font config from given xml files, instead of those from Android system. + */ +SK_API void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, + const char* fontsdir); + +/** + * Given a "current" fontID, return a ref to the next logical typeface + * when searching fonts for a given unicode value. Typically the caller + * will query a given font, and if a unicode value is not supported, they + * will call this, and if 0 is not returned, will search that font, and so + * on. This process must be finite, and when the fonthost sees a + * font with no logical successor, it must return NULL. + * + * The original fontID is also provided. This is the initial font that was + * stored in the typeface of the caller. It is provided as an aid to choose + * the best next logical font. e.g. If the original font was bold or serif, + * but the 2nd in the logical chain was plain, then a subsequent call to + * get the 3rd can still inspect the original, and try to match its + * stylistic attributes. + */ +SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, + const SkPaintOptionsAndroid& options); + +/** + * Given a glyphID (built using fallback font chaining) and its origin typeface + * return the actual typeface within the fallback chain that this glyphID + * resolves to. If no suitable typeface is found then NULL is returned. However, + * if returned typeface is not NULL it is assumed to be globally cached so the + * caller need not ref it. + * + * Optionally, if lower/upper bound params are provided and the returned + * typeface is not NULL, then these params are populated with the range of + * glyphIDs that this typeface is capable of resolving. The lower bound is + * inclusive while the upper bound is exclusive. + */ +SkTypeface* SkGetTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface, + const SkPaintOptionsAndroid& options, + int* lowerBounds = NULL, int* upperBounds = NULL); + +#endif // #ifdef SK_BUILD_FOR_ANDROID +#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK + +#include "SkPaintOptionsAndroid.h" +#include "../harfbuzz_ng/src/hb.h" + +/** + * Return a new typeface for a fallback script. If the script is + * not valid, or can not map to a font, returns null. + * @param script The harfbuzz script id. + * @param style The font style, for example bold + * @param elegant true if we want the web friendly elegant version of the font + * @return reference to the matching typeface. Caller must call + * unref() when they are done. + */ +SK_API SkTypeface* SkCreateTypefaceForScript(hb_script_t script, SkTypeface::Style style, + SkPaintOptionsAndroid::FontVariant fontVariant = SkPaintOptionsAndroid::kDefault_Variant); + +#endif // #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK +#endif // #ifndef SkTypeface_android_DEFINED diff --git a/gfx/skia/include/ports/SkTypeface_cairo.h b/gfx/skia/trunk/include/ports/SkTypeface_cairo.h similarity index 100% rename from gfx/skia/include/ports/SkTypeface_cairo.h rename to gfx/skia/trunk/include/ports/SkTypeface_cairo.h diff --git a/gfx/skia/include/ports/SkTypeface_mac.h b/gfx/skia/trunk/include/ports/SkTypeface_mac.h similarity index 100% rename from gfx/skia/include/ports/SkTypeface_mac.h rename to gfx/skia/trunk/include/ports/SkTypeface_mac.h diff --git a/gfx/skia/include/ports/SkTypeface_win.h b/gfx/skia/trunk/include/ports/SkTypeface_win.h similarity index 90% rename from gfx/skia/include/ports/SkTypeface_win.h rename to gfx/skia/trunk/include/ports/SkTypeface_win.h index fea5f474a0fd..e7dd4ab50ae7 100644 --- a/gfx/skia/include/ports/SkTypeface_win.h +++ b/gfx/skia/trunk/include/ports/SkTypeface_win.h @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -6,8 +5,6 @@ * found in the LICENSE file. */ - - #ifndef SkTypeface_win_DEFINED #define SkTypeface_win_DEFINED @@ -36,4 +33,10 @@ SK_API void SkLOGFONTFromTypeface(const SkTypeface* typeface, LOGFONT* lf); */ SK_API void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*)(const LOGFONT&)); +// Experimental! +// +class SkFontMgr; +SK_API SkFontMgr* SkFontMgr_New_GDI(); +SK_API SkFontMgr* SkFontMgr_New_DirectWrite(); + #endif diff --git a/gfx/skia/include/svg/SkSVGAttribute.h b/gfx/skia/trunk/include/svg/SkSVGAttribute.h similarity index 100% rename from gfx/skia/include/svg/SkSVGAttribute.h rename to gfx/skia/trunk/include/svg/SkSVGAttribute.h diff --git a/gfx/skia/include/svg/SkSVGBase.h b/gfx/skia/trunk/include/svg/SkSVGBase.h similarity index 100% rename from gfx/skia/include/svg/SkSVGBase.h rename to gfx/skia/trunk/include/svg/SkSVGBase.h diff --git a/gfx/skia/include/svg/SkSVGPaintState.h b/gfx/skia/trunk/include/svg/SkSVGPaintState.h similarity index 100% rename from gfx/skia/include/svg/SkSVGPaintState.h rename to gfx/skia/trunk/include/svg/SkSVGPaintState.h diff --git a/gfx/skia/include/svg/SkSVGParser.h b/gfx/skia/trunk/include/svg/SkSVGParser.h similarity index 100% rename from gfx/skia/include/svg/SkSVGParser.h rename to gfx/skia/trunk/include/svg/SkSVGParser.h diff --git a/gfx/skia/include/svg/SkSVGTypes.h b/gfx/skia/trunk/include/svg/SkSVGTypes.h similarity index 100% rename from gfx/skia/include/svg/SkSVGTypes.h rename to gfx/skia/trunk/include/svg/SkSVGTypes.h diff --git a/gfx/skia/include/text/SkTextLayout.h b/gfx/skia/trunk/include/text/SkTextLayout.h similarity index 100% rename from gfx/skia/include/text/SkTextLayout.h rename to gfx/skia/trunk/include/text/SkTextLayout.h diff --git a/gfx/skia/include/utils/SkBoundaryPatch.h b/gfx/skia/trunk/include/utils/SkBoundaryPatch.h similarity index 100% rename from gfx/skia/include/utils/SkBoundaryPatch.h rename to gfx/skia/trunk/include/utils/SkBoundaryPatch.h diff --git a/gfx/skia/include/utils/SkCamera.h b/gfx/skia/trunk/include/utils/SkCamera.h similarity index 80% rename from gfx/skia/include/utils/SkCamera.h rename to gfx/skia/trunk/include/utils/SkCamera.h index eafacbcd7d49..b515be9c6cfe 100644 --- a/gfx/skia/include/utils/SkCamera.h +++ b/gfx/skia/trunk/include/utils/SkCamera.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,47 +5,29 @@ * found in the LICENSE file. */ - - - // Inspired by Rob Johnson's most excellent QuickDraw GX sample code #ifndef SkCamera_DEFINED #define SkCamera_DEFINED -#include "Sk64.h" #include "SkMatrix.h" class SkCanvas; -#ifdef SK_SCALAR_IS_FIXED - typedef SkFract SkUnitScalar; - #define SK_UnitScalar1 SK_Fract1 - #define SkUnitScalarMul(a, b) SkFractMul(a, b) - #define SkUnitScalarDiv(a, b) SkFractDiv(a, b) -#else - typedef float SkUnitScalar; - #define SK_UnitScalar1 SK_Scalar1 - #define SkUnitScalarMul(a, b) SkScalarMul(a, b) - #define SkUnitScalarDiv(a, b) SkScalarDiv(a, b) -#endif - struct SkUnit3D { - SkUnitScalar fX, fY, fZ; + SkScalar fX, fY, fZ; - void set(SkUnitScalar x, SkUnitScalar y, SkUnitScalar z) - { + void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; } - static SkUnitScalar Dot(const SkUnit3D&, const SkUnit3D&); + static SkScalar Dot(const SkUnit3D&, const SkUnit3D&); static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross); }; struct SkPoint3D { SkScalar fX, fY, fZ; - void set(SkScalar x, SkScalar y, SkScalar z) - { + void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; } SkScalar normalize(SkUnit3D*) const; @@ -58,8 +39,7 @@ struct SkMatrix3D { void reset(); - void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0) - { + void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0) { SkASSERT((unsigned)row < 3); fMat[row][0] = a; fMat[row][1] = b; @@ -81,12 +61,11 @@ struct SkMatrix3D { void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const; void mapVector(const SkVector3D& src, SkVector3D* dst) const; - void mapPoint(SkPoint3D* v) const - { + void mapPoint(SkPoint3D* v) const { this->mapPoint(*v, v); } - void mapVector(SkVector3D* v) const - { + + void mapVector(SkVector3D* v) const { this->mapVector(*v, v); } }; @@ -100,8 +79,7 @@ public: // dot a unit vector with the patch's normal SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const; - SkScalar dotWith(const SkVector3D& v) const - { + SkScalar dotWith(const SkVector3D& v) const { return this->dotWith(v.fX, v.fY, v.fZ); } diff --git a/gfx/skia/trunk/include/utils/SkCanvasStateUtils.h b/gfx/skia/trunk/include/utils/SkCanvasStateUtils.h new file mode 100644 index 000000000000..f8266c9b324c --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkCanvasStateUtils.h @@ -0,0 +1,76 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkCanvasStateUtils_DEFINED +#define SkCanvasStateUtils_DEFINED + +#include "SkCanvas.h" + +class SkCanvasState; + +/** + * A set of functions that are useful for copying an SkCanvas across a library + * boundary where the Skia libraries on either side of the boundary may not be + * version identical. The expected usage is outline below... + * + * Lib Boundary + * CaptureCanvasState(...) ||| + * SkCanvas --> SkCanvasState ||| + * ||| CreateFromCanvasState(...) + * ||| SkCanvasState --> SkCanvas` + * ||| Draw into SkCanvas` + * ||| Unref SkCanvas` + * ReleaseCanvasState(...) ||| + * + */ +namespace SkCanvasStateUtils { + /** + * Captures the current state of the canvas into an opaque ptr that is safe + * to pass between different instances of Skia (which may or may not be the + * same version). The function will return NULL in the event that one of the + * following conditions are true. + * 1) the canvas device type is not supported (currently only raster is supported) + * 2) the canvas clip type is not supported (currently only non-AA clips are supported) + * + * It is recommended that the original canvas also not be used until all + * canvases that have been created using its captured state have been dereferenced. + * + * Finally, it is important to note that any draw filters attached to the + * canvas are NOT currently captured. + * + * @param canvas The canvas you wish to capture the current state of. + * @return NULL or an opaque ptr that can be passed to CreateFromCanvasState + * to reconstruct the canvas. The caller is responsible for calling + * ReleaseCanvasState to free the memory associated with this state. + */ + SK_API SkCanvasState* CaptureCanvasState(SkCanvas* canvas); + + /** + * Create a new SkCanvas from the captured state of another SkCanvas. The + * function will return NULL in the event that one of the + * following conditions are true. + * 1) the captured state is in an unrecognized format + * 2) the captured canvas device type is not supported + * + * @param canvas The canvas you wish to capture the current state of. + * @return NULL or an SkCanvas* whose devices and matrix/clip state are + * identical to the captured canvas. The caller is responsible for + * calling unref on the SkCanvas. + */ + SK_API SkCanvas* CreateFromCanvasState(const SkCanvasState* state); + + /** + * Free the memory associated with the captured canvas state. The state + * should not be released until all SkCanvas objects created using that + * state have been dereferenced. + * + * @param state The captured state you wish to dispose of. + */ + SK_API void ReleaseCanvasState(SkCanvasState* state); +}; + +#endif diff --git a/gfx/skia/include/utils/SkCondVar.h b/gfx/skia/trunk/include/utils/SkCondVar.h similarity index 100% rename from gfx/skia/include/utils/SkCondVar.h rename to gfx/skia/trunk/include/utils/SkCondVar.h diff --git a/gfx/skia/include/utils/SkCountdown.h b/gfx/skia/trunk/include/utils/SkCountdown.h similarity index 100% rename from gfx/skia/include/utils/SkCountdown.h rename to gfx/skia/trunk/include/utils/SkCountdown.h diff --git a/gfx/skia/include/utils/SkCubicInterval.h b/gfx/skia/trunk/include/utils/SkCubicInterval.h similarity index 100% rename from gfx/skia/include/utils/SkCubicInterval.h rename to gfx/skia/trunk/include/utils/SkCubicInterval.h diff --git a/gfx/skia/include/utils/SkCullPoints.h b/gfx/skia/trunk/include/utils/SkCullPoints.h similarity index 100% rename from gfx/skia/include/utils/SkCullPoints.h rename to gfx/skia/trunk/include/utils/SkCullPoints.h diff --git a/gfx/skia/include/utils/SkDebugUtils.h b/gfx/skia/trunk/include/utils/SkDebugUtils.h similarity index 100% rename from gfx/skia/include/utils/SkDebugUtils.h rename to gfx/skia/trunk/include/utils/SkDebugUtils.h diff --git a/gfx/skia/include/utils/SkDeferredCanvas.h b/gfx/skia/trunk/include/utils/SkDeferredCanvas.h similarity index 87% rename from gfx/skia/include/utils/SkDeferredCanvas.h rename to gfx/skia/trunk/include/utils/SkDeferredCanvas.h index 53bea82d3ff2..b0435de9bd26 100644 --- a/gfx/skia/include/utils/SkDeferredCanvas.h +++ b/gfx/skia/trunk/include/utils/SkDeferredCanvas.h @@ -12,6 +12,8 @@ #include "SkPixelRef.h" class DeferredDevice; +class SkImage; +class SkSurface; /** \class SkDeferredCanvas Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred @@ -23,27 +25,27 @@ class DeferredDevice; */ class SK_API SkDeferredCanvas : public SkCanvas { public: - class NotificationClient; + class SK_API NotificationClient; - SkDeferredCanvas(); + /** Construct a canvas with the specified surface to draw into. + This factory must be used for newImageSnapshot to work. + @param surface Specifies a surface for the canvas to draw into. + */ + static SkDeferredCanvas* Create(SkSurface* surface); - /** Construct a canvas with the specified device to draw into. - Equivalent to calling default constructor, then setDevice. - @param device Specifies a device for the canvas to draw into. - */ - explicit SkDeferredCanvas(SkDevice* device); +// static SkDeferredCanvas* Create(SkBaseDevice* device); virtual ~SkDeferredCanvas(); /** - * Specify a device to be used by this canvas. Calling setDevice will - * release the previously set device, if any. Takes a reference on the - * device. + * Specify the surface to be used by this canvas. Calling setSurface will + * release the previously set surface or device. Takes a reference on the + * surface. * - * @param device The device that the canvas will raw into - * @return The device argument, for convenience. + * @param surface The surface that the canvas will raw into + * @return The surface argument, for convenience. */ - virtual SkDevice* setDevice(SkDevice* device); + SkSurface* setSurface(SkSurface* surface); /** * Specify a NotificationClient to be used by this canvas. Calling @@ -92,6 +94,15 @@ public: */ bool hasPendingCommands() const; + /** + * Flushes pending draw commands, if any, and returns an image of the + * current state of the surface pixels up to this point. Subsequent + * changes to the surface (by drawing into its canvas) will not be + * reflected in this image. Will return NULL if the deferred canvas + * was not constructed from an SkSurface. + */ + SkImage* newImageSnapshot(); + /** * Specify the maximum number of bytes to be allocated for the purpose * of recording draw commands to this canvas. The default limit, is @@ -159,8 +170,8 @@ public: SkScalar top, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) - SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) SK_OVERRIDE; @@ -227,6 +238,8 @@ protected: DeferredDevice* getDeferredDevice() const; private: + SkDeferredCanvas(DeferredDevice*); + void recordedDrawCommand(); SkCanvas* drawingCanvas() const; SkCanvas* immediateCanvas() const; diff --git a/gfx/skia/include/utils/SkDumpCanvas.h b/gfx/skia/trunk/include/utils/SkDumpCanvas.h similarity index 92% rename from gfx/skia/include/utils/SkDumpCanvas.h rename to gfx/skia/trunk/include/utils/SkDumpCanvas.h index 8d9c67d50dd6..96b45e7ba2bc 100644 --- a/gfx/skia/include/utils/SkDumpCanvas.h +++ b/gfx/skia/trunk/include/utils/SkDumpCanvas.h @@ -45,7 +45,11 @@ public: kDrawText_Verb, kDrawPicture_Verb, kDrawVertices_Verb, - kDrawData_Verb + kDrawData_Verb, + + kBeginCommentGroup_Verb, + kAddComment_Verb, + kEndCommentGroup_Verb }; /** Subclasses of this are installed on the DumpCanvas, and then called for @@ -95,7 +99,8 @@ public: virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) SK_OVERRIDE; virtual void drawSprite(const SkBitmap& bitmap, int left, int top, @@ -117,6 +122,9 @@ public: const uint16_t indices[], int indexCount, const SkPaint& paint) SK_OVERRIDE; virtual void drawData(const void*, size_t) SK_OVERRIDE; + virtual void beginCommentGroup(const char* description) SK_OVERRIDE; + virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; + virtual void endCommentGroup() SK_OVERRIDE; private: Dumper* fDumper; diff --git a/gfx/skia/trunk/include/utils/SkEventTracer.h b/gfx/skia/trunk/include/utils/SkEventTracer.h new file mode 100644 index 000000000000..8d9fd11f6479 --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkEventTracer.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014 Google Inc. All rights reserved. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkEventTracer_DEFINED +#define SkEventTracer_DEFINED + +// The class in this header defines the interface between Skia's internal +// tracing macros and an external entity (e.g., Chrome) that will consume them. +// Such an entity should subclass SkEventTracer and provide an instance of +// that event to SkEventTracer::SetInstance. + +// If you're looking for the tracing macros to instrument Skia itself, those +// live in src/core/SkTraceEvent.h + +#include "SkTypes.h" + +// This will mark the trace event as disabled by default. The user will need +// to explicitly enable the event. +#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name + +class SK_API SkEventTracer { +public: + + typedef uint64_t Handle; + + static SkEventTracer* GetInstance(); + + static void SetInstance(SkEventTracer* tracer) { + SkDELETE(SkEventTracer::gInstance); + SkEventTracer::gInstance = tracer; + } + + virtual ~SkEventTracer() { } + + // The pointer returned from GetCategoryGroupEnabled() points to a + // value with zero or more of the following bits. Used in this class only. + // The TRACE_EVENT macros should only use the value as a bool. + // These values must be in sync with macro values in trace_event.h in chromium. + enum CategoryGroupEnabledFlags { + // Category group enabled for the recording mode. + kEnabledForRecording_CategoryGroupEnabledFlags = 1 << 0, + // Category group enabled for the monitoring mode. + kEnabledForMonitoring_CategoryGroupEnabledFlags = 1 << 1, + // Category group enabled by SetEventCallbackEnabled(). + kEnabledForEventCallback_CategoryGroupEnabledFlags = 1 << 2, + }; + + virtual const uint8_t* getCategoryGroupEnabled(const char* name) = 0; + virtual const char* getCategoryGroupName( + const uint8_t* categoryEnabledFlag) = 0; + + virtual SkEventTracer::Handle + addTraceEvent(char phase, + const uint8_t* categoryEnabledFlag, + const char* name, + uint64_t id, + int32_t numArgs, + const char** argNames, + const uint8_t* argTypes, + const uint64_t* argValues, + uint8_t flags) = 0; + + virtual void + updateTraceEventDuration(const uint8_t* categoryEnabledFlag, + const char* name, + SkEventTracer::Handle handle) = 0; +private: + static SkEventTracer *gInstance; +}; + +#endif // SkEventTracer_DEFINED diff --git a/gfx/skia/trunk/include/utils/SkFrontBufferedStream.h b/gfx/skia/trunk/include/utils/SkFrontBufferedStream.h new file mode 100644 index 000000000000..68d9861557f6 --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkFrontBufferedStream.h @@ -0,0 +1,35 @@ +/* + * 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 "SkTypes.h" + +class SkStream; +class SkStreamRewindable; + +/** + * Specialized stream that buffers the first X bytes of a stream, + * where X is passed in by the user. Note that unlike some buffered + * stream APIs, once more bytes than can fit in the buffer are read, + * no more buffering is done. This stream is designed for a use case + * where the caller knows that rewind will only be called from within + * X bytes (inclusive), and the wrapped stream is not necessarily + * able to rewind at all. + */ +class SkFrontBufferedStream { +public: + /** + * Creates a new stream that wraps and buffers an SkStream. + * @param stream SkStream to buffer. If stream is NULL, NULL is + * returned. When this call succeeds (i.e. returns non NULL), + * SkFrontBufferedStream is expected to be the only owner of + * stream, so it should be unreffed and no longer used directly. + * @param minBufferSize Minimum size of buffer required. + * @return An SkStream that can buffer at least minBufferSize, or + * NULL on failure. + */ + static SkStreamRewindable* Create(SkStream* stream, size_t minBufferSize); +}; diff --git a/gfx/skia/include/utils/SkInterpolator.h b/gfx/skia/trunk/include/utils/SkInterpolator.h similarity index 100% rename from gfx/skia/include/utils/SkInterpolator.h rename to gfx/skia/trunk/include/utils/SkInterpolator.h diff --git a/gfx/skia/include/utils/SkJSON.h b/gfx/skia/trunk/include/utils/SkJSON.h similarity index 100% rename from gfx/skia/include/utils/SkJSON.h rename to gfx/skia/trunk/include/utils/SkJSON.h diff --git a/gfx/skia/trunk/include/utils/SkJSONCPP.h b/gfx/skia/trunk/include/utils/SkJSONCPP.h new file mode 100644 index 000000000000..8dbb40c91bed --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkJSONCPP.h @@ -0,0 +1,26 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * A common place to put the jsoncpp library includes, as opposed to littering + * the pragmas repeatedly through our code. + */ +#ifndef SkJSONCPP_DEFINED +#define SkJSONCPP_DEFINED + +#ifdef SK_BUILD_FOR_WIN + // json includes xlocale which generates warning 4530 because we're + // compiling without exceptions; + // see https://code.google.com/p/skia/issues/detail?id=1067 + #pragma warning(push) + #pragma warning(disable : 4530) +#endif +#include "json/reader.h" +#include "json/value.h" +#ifdef SK_BUILD_FOR_WIN + #pragma warning(pop) +#endif + +#endif diff --git a/gfx/skia/include/utils/SkLayer.h b/gfx/skia/trunk/include/utils/SkLayer.h similarity index 100% rename from gfx/skia/include/utils/SkLayer.h rename to gfx/skia/trunk/include/utils/SkLayer.h diff --git a/gfx/skia/trunk/include/utils/SkLua.h b/gfx/skia/trunk/include/utils/SkLua.h new file mode 100644 index 000000000000..c6097464ef3f --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkLua.h @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkLua_DEFINED +#define SkLua_DEFINED + +#include "SkColor.h" +#include "SkScalar.h" +#include "SkString.h" + +struct lua_State; + +class SkCanvas; +class SkMatrix; +class SkPaint; +class SkPath; +struct SkRect; +class SkRRect; + +#define SkScalarToLua(x) SkScalarToDouble(x) +#define SkLuaToScalar(x) SkDoubleToScalar(x) + +class SkLua { +public: + static void Load(lua_State*); + + SkLua(const char termCode[] = NULL); // creates a new L, will close it + SkLua(lua_State*); // uses L, will not close it + ~SkLua(); + + lua_State* get() const { return fL; } + lua_State* operator*() const { return fL; } + lua_State* operator->() const { return fL; } + + bool runCode(const char code[]); + bool runCode(const void* code, size_t size); + + void pushBool(bool, const char tableKey[] = NULL); + void pushString(const char[], const char tableKey[] = NULL); + void pushString(const char[], size_t len, const char tableKey[] = NULL); + void pushString(const SkString&, const char tableKey[] = NULL); + void pushArrayU16(const uint16_t[], int count, const char tableKey[] = NULL); + void pushColor(SkColor, const char tableKey[] = NULL); + void pushU32(uint32_t, const char tableKey[] = NULL); + void pushScalar(SkScalar, const char tableKey[] = NULL); + void pushRect(const SkRect&, const char tableKey[] = NULL); + void pushRRect(const SkRRect&, const char tableKey[] = NULL); + void pushMatrix(const SkMatrix&, const char tableKey[] = NULL); + void pushPaint(const SkPaint&, const char tableKey[] = NULL); + void pushPath(const SkPath&, const char tableKey[] = NULL); + void pushCanvas(SkCanvas*, const char tableKey[] = NULL); + +private: + lua_State* fL; + SkString fTermCode; + bool fWeOwnL; +}; + +#endif diff --git a/gfx/skia/trunk/include/utils/SkLuaCanvas.h b/gfx/skia/trunk/include/utils/SkLuaCanvas.h new file mode 100644 index 000000000000..c34d1344236d --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkLuaCanvas.h @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkLuaCanvas_DEFINED +#define SkLuaCanvas_DEFINED + +#include "SkCanvas.h" +#include "SkString.h" + +struct lua_State; + +class SkLuaCanvas : public SkCanvas { +public: + void pushThis(); + + SkLuaCanvas(int width, int height, lua_State*, const char function[]); + virtual ~SkLuaCanvas(); + + virtual int save(SaveFlags flags) SK_OVERRIDE; + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags) SK_OVERRIDE; + virtual void restore() SK_OVERRIDE; + + virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE; + virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE; + virtual bool rotate(SkScalar degrees) SK_OVERRIDE; + virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE; + virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE; + virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE; + + virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE; + virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE; + virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE; + virtual bool clipRegion(const SkRegion& deviceRgn, + SkRegion::Op) SK_OVERRIDE; + + virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; + virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint) SK_OVERRIDE; + virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE; + virtual void drawRect(const SkRect&, const SkPaint& paint) SK_OVERRIDE; + virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE; + virtual void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE; + virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, + const SkPaint* paint) SK_OVERRIDE; + virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; + virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, + const SkPaint* paint) SK_OVERRIDE; + virtual void drawSprite(const SkBitmap& bitmap, int left, int top, + const SkPaint* paint) SK_OVERRIDE; + virtual void drawText(const void* text, size_t byteLength, SkScalar x, + SkScalar y, const SkPaint& paint) SK_OVERRIDE; + virtual void drawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE; + virtual void drawPosTextH(const void* text, size_t byteLength, + const SkScalar xpos[], SkScalar constY, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawPicture(SkPicture&) SK_OVERRIDE; + virtual void drawVertices(VertexMode vmode, int vertexCount, + const SkPoint vertices[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint) SK_OVERRIDE; + virtual void drawData(const void* data, size_t length) SK_OVERRIDE; + +private: + lua_State* fL; + SkString fFunc; + + void sendverb(const char verb[]); + + typedef SkCanvas INHERITED; +}; + +#endif diff --git a/gfx/skia/include/utils/SkMatrix44.h b/gfx/skia/trunk/include/utils/SkMatrix44.h similarity index 93% rename from gfx/skia/include/utils/SkMatrix44.h rename to gfx/skia/trunk/include/utils/SkMatrix44.h index 9d9b6e01029e..26247a01e99c 100644 --- a/gfx/skia/include/utils/SkMatrix44.h +++ b/gfx/skia/trunk/include/utils/SkMatrix44.h @@ -112,7 +112,7 @@ public: SkMatrix44(Uninitialized_Constructor) { } SkMatrix44(Identity_Constructor) { this->setIdentity(); } - // DEPRECATED: use the constructors that take an enum + SK_ATTR_DEPRECATED("use the constructors that take an enum") SkMatrix44() { this->setIdentity(); } SkMatrix44(const SkMatrix44& src) { @@ -137,6 +137,14 @@ public: return !(other == *this); } + /* When converting from SkMatrix44 to SkMatrix, the third row and + * column is dropped. When converting from SkMatrix to SkMatrix44 + * the third row and column remain as identity: + * [ a b c ] [ a b 0 c ] + * [ d e f ] -> [ d e 0 f ] + * [ g h i ] [ 0 0 1 0 ] + * [ g h 0 i ] + */ SkMatrix44(const SkMatrix&); SkMatrix44& operator=(const SkMatrix& src); operator SkMatrix() const; @@ -224,6 +232,12 @@ public: inline void setDouble(int row, int col, double value) { this->set(row, col, SkDoubleToMScalar(value)); } + inline float getFloat(int row, int col) const { + return SkMScalarToFloat(this->get(row, col)); + } + inline void setFloat(int row, int col, float value) { + this->set(row, col, SkFloatToMScalar(value)); + } /** These methods allow one to efficiently read matrix entries into an * array. The given array must have room for exactly 16 entries. Whenever @@ -253,6 +267,8 @@ public: void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); } #endif + /* This sets the top-left of the matrix and clears the translation and + * perspective components (with [3][3] set to 1). */ void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, SkMScalar m10, SkMScalar m11, SkMScalar m12, SkMScalar m20, SkMScalar m21, SkMScalar m22); @@ -319,11 +335,12 @@ public: this->mapScalars(vec, vec); } - // DEPRECATED: call mapScalars() + SK_ATTR_DEPRECATED("use mapScalars") void map(const SkScalar src[4], SkScalar dst[4]) const { this->mapScalars(src, dst); } - // DEPRECATED: call mapScalars() + + SK_ATTR_DEPRECATED("use mapScalars") void map(SkScalar vec[4]) const { this->mapScalars(vec, vec); } @@ -341,7 +358,7 @@ public: friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) { SkVector4 dst; - m.map(src.fData, dst.fData); + m.mapScalars(src.fData, dst.fData); return dst; } diff --git a/gfx/skia/include/utils/SkMeshUtils.h b/gfx/skia/trunk/include/utils/SkMeshUtils.h similarity index 91% rename from gfx/skia/include/utils/SkMeshUtils.h rename to gfx/skia/trunk/include/utils/SkMeshUtils.h index 564df67a8ed6..7e0e8f4de260 100644 --- a/gfx/skia/include/utils/SkMeshUtils.h +++ b/gfx/skia/trunk/include/utils/SkMeshUtils.h @@ -27,14 +27,14 @@ public: bool init(SkPoint tex[], uint16_t indices[], int texW, int texH, int rows, int cols); - size_t indexCount() const { return fIndexCount; } + int indexCount() const { return fIndexCount; } const uint16_t* indices() const { return fIndices; } size_t texCount() const { return fTexCount; } const SkPoint* tex() const { return fTex; } private: - size_t fIndexCount, fTexCount; + int fIndexCount, fTexCount; SkPoint* fTex; uint16_t* fIndices; void* fStorage; // may be null diff --git a/gfx/skia/include/utils/SkNWayCanvas.h b/gfx/skia/trunk/include/utils/SkNWayCanvas.h similarity index 81% rename from gfx/skia/include/utils/SkNWayCanvas.h rename to gfx/skia/trunk/include/utils/SkNWayCanvas.h index d8334551cb7a..eae3bfc538d4 100644 --- a/gfx/skia/include/utils/SkNWayCanvas.h +++ b/gfx/skia/trunk/include/utils/SkNWayCanvas.h @@ -11,14 +11,14 @@ #include "SkCanvas.h" -class SkNWayCanvas : public SkCanvas { +class SK_API SkNWayCanvas : public SkCanvas { public: SkNWayCanvas(int width, int height); virtual ~SkNWayCanvas(); - void addCanvas(SkCanvas*); - void removeCanvas(SkCanvas*); - void removeAll(); + virtual void addCanvas(SkCanvas*); + virtual void removeCanvas(SkCanvas*); + virtual void removeAll(); /////////////////////////////////////////////////////////////////////////// // These are forwarded to the N canvases we're referencing @@ -38,20 +38,24 @@ public: virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE; virtual bool clipRegion(const SkRegion& deviceRgn, SkRegion::Op) SK_OVERRIDE; - + virtual void clear(SkColor) SK_OVERRIDE; virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE; virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint&) SK_OVERRIDE; - virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; virtual void drawRect(const SkRect&, const SkPaint&) SK_OVERRIDE; + virtual void drawOval(const SkRect&, const SkPaint&) SK_OVERRIDE; virtual void drawRRect(const SkRRect&, const SkPaint&) SK_OVERRIDE; virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE; virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint*) SK_OVERRIDE; virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint*) SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint*) SK_OVERRIDE; + virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, + const SkRect& dst, + const SkPaint* paint = NULL) SK_OVERRIDE; virtual void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint*) SK_OVERRIDE; virtual void drawText(const void* text, size_t byteLength, SkScalar x, @@ -70,15 +74,21 @@ public: const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint&) SK_OVERRIDE; + virtual void drawData(const void* data, size_t length) SK_OVERRIDE; virtual SkBounder* setBounder(SkBounder*) SK_OVERRIDE; virtual SkDrawFilter* setDrawFilter(SkDrawFilter*) SK_OVERRIDE; -private: + virtual void beginCommentGroup(const char* description) SK_OVERRIDE; + virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; + virtual void endCommentGroup() SK_OVERRIDE; + +protected: SkTDArray fList; class Iter; +private: typedef SkCanvas INHERITED; }; diff --git a/gfx/skia/include/utils/SkNinePatch.h b/gfx/skia/trunk/include/utils/SkNinePatch.h similarity index 100% rename from gfx/skia/include/utils/SkNinePatch.h rename to gfx/skia/trunk/include/utils/SkNinePatch.h diff --git a/gfx/skia/include/utils/SkNullCanvas.h b/gfx/skia/trunk/include/utils/SkNullCanvas.h similarity index 100% rename from gfx/skia/include/utils/SkNullCanvas.h rename to gfx/skia/trunk/include/utils/SkNullCanvas.h diff --git a/gfx/skia/include/utils/SkParse.h b/gfx/skia/trunk/include/utils/SkParse.h similarity index 100% rename from gfx/skia/include/utils/SkParse.h rename to gfx/skia/trunk/include/utils/SkParse.h diff --git a/gfx/skia/include/utils/SkParsePaint.h b/gfx/skia/trunk/include/utils/SkParsePaint.h similarity index 100% rename from gfx/skia/include/utils/SkParsePaint.h rename to gfx/skia/trunk/include/utils/SkParsePaint.h diff --git a/gfx/skia/include/utils/SkParsePath.h b/gfx/skia/trunk/include/utils/SkParsePath.h similarity index 100% rename from gfx/skia/include/utils/SkParsePath.h rename to gfx/skia/trunk/include/utils/SkParsePath.h diff --git a/gfx/skia/trunk/include/utils/SkPathUtils.h b/gfx/skia/trunk/include/utils/SkPathUtils.h new file mode 100644 index 000000000000..a27cbb8f0f3e --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkPathUtils.h @@ -0,0 +1,40 @@ +/* + * CAUTION: EXPERIMENTAL CODE + * + * This code is not to be used and will not be supported + * if it fails on you. DO NOT USE! + * + */ + +#ifndef SkPathUtils_DEFINED +#define SkPathUtils_DEFINED + +#include "SkPath.h" + +/* + * The following methods return the boundary path given a 1-bit bitmap, specified + * by width/height and stride. The bits are interpreted as 1 being "in" the path, + * and 0 being "out". The bits are interpreted as MSB on the left, and LSB on the right. + */ + +class SK_API SkPathUtils { +public: + /** + This variation iterates the binary data sequentially (as in scanline fashion) + and will add each run of 1's to the path as a rectangular path. Upon parsing + all binary data the path is simplified using the PathOps::Simplify() method. + */ + static void BitsToPath_Path(SkPath* path, const char* bitmap, + int w, int h, int rowBytes); + + /** + This variation utilizes the SkRegion class to generate paths, adding + each run of 1's to the SkRegion as an SkIRect. Upon parsing the entirety + of the binary the SkRegion is converted to a Path via getBoundaryPath(). + */ + static void BitsToPath_Region(SkPath* path, const char* bitmap, + int w, int h, int rowBytes); + +}; + +#endif diff --git a/gfx/skia/trunk/include/utils/SkPictureUtils.h b/gfx/skia/trunk/include/utils/SkPictureUtils.h new file mode 100644 index 000000000000..c35aca81e2ac --- /dev/null +++ b/gfx/skia/trunk/include/utils/SkPictureUtils.h @@ -0,0 +1,83 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPictureUtils_DEFINED +#define SkPictureUtils_DEFINED + +#include "SkPicture.h" +#include "SkTDArray.h" + +class SkData; +struct SkRect; + +class SK_API SkPictureUtils { +public: + /** + * Given a rectangular visible "window" into the picture, return an array + * of SkPixelRefs that might intersect that area. To keep the call fast, + * the returned list is not guaranteed to be exact, so it may miss some, + * and it may return false positives. + * + * The pixelrefs returned in the SkData are already owned by the picture, + * so the returned pointers are only valid while the picture is in scope + * and remains unchanged. + */ + static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area); + + /** + * SkPixelRefContainer provides a base class for more elaborate pixel ref + * query structures (e.g., rtrees, quad-trees, etc.) + */ + class SkPixelRefContainer : public SkRefCnt { + public: + virtual void add(SkPixelRef* pr, const SkRect& rect) = 0; + + // The returned array may contain duplicates + virtual void query(const SkRect& queryRect, SkTDArray *result) = 0; + + private: + typedef SkRefCnt INHERITED; + }; + + // Simple query structure that just stores a linked list of pixel refs + // and rects. + class SkPixelRefsAndRectsList : public SkPixelRefContainer { + public: + virtual void add(SkPixelRef* pr, const SkRect& rect) SK_OVERRIDE { + PixelRefAndRect *dst = fArray.append(); + + dst->fPixelRef = pr; + dst->fRect = rect; + } + + virtual void query(const SkRect& queryRect, SkTDArray *result) SK_OVERRIDE { + for (int i = 0; i < fArray.count(); ++i) { + if (SkRect::Intersects(fArray[i].fRect, queryRect)) { + *result->append() = fArray[i].fPixelRef; + } + } + } + + private: + struct PixelRefAndRect { + SkPixelRef* fPixelRef; + SkRect fRect; + }; + + SkTDArray fArray; + + typedef SkPixelRefContainer INHERITED; + }; + + /** + * Fill the provided pixel ref container with the picture's pixel ref + * and rect information. + */ + static void GatherPixelRefsAndRects(SkPicture* pict, SkPixelRefContainer* prCont); +}; + +#endif diff --git a/gfx/skia/include/utils/SkProxyCanvas.h b/gfx/skia/trunk/include/utils/SkProxyCanvas.h similarity index 91% rename from gfx/skia/include/utils/SkProxyCanvas.h rename to gfx/skia/trunk/include/utils/SkProxyCanvas.h index bd260c77d2dc..383e532fbfca 100644 --- a/gfx/skia/include/utils/SkProxyCanvas.h +++ b/gfx/skia/trunk/include/utils/SkProxyCanvas.h @@ -17,7 +17,7 @@ There must be a proxy installed before the proxycanvas can be used (i.e. before its virtual methods can be called). */ -class SkProxyCanvas : public SkCanvas { +class SK_API SkProxyCanvas : public SkCanvas { public: SkProxyCanvas() : fProxy(NULL) {} SkProxyCanvas(SkCanvas* proxy); @@ -54,7 +54,8 @@ public: virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint = NULL) SK_OVERRIDE; virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint = NULL) SK_OVERRIDE; virtual void drawSprite(const SkBitmap& bitmap, int left, int top, @@ -77,6 +78,10 @@ public: const SkPaint& paint) SK_OVERRIDE; virtual void drawData(const void* data, size_t length) SK_OVERRIDE; + virtual void beginCommentGroup(const char* description) SK_OVERRIDE; + virtual void addComment(const char* kywd, const char* value) SK_OVERRIDE; + virtual void endCommentGroup() SK_OVERRIDE; + virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE; virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE; diff --git a/gfx/skia/include/utils/SkRTConf.h b/gfx/skia/trunk/include/utils/SkRTConf.h similarity index 78% rename from gfx/skia/include/utils/SkRTConf.h rename to gfx/skia/trunk/include/utils/SkRTConf.h index c34dafb79660..4ba607011dd6 100644 --- a/gfx/skia/include/utils/SkRTConf.h +++ b/gfx/skia/trunk/include/utils/SkRTConf.h @@ -52,10 +52,17 @@ protected: #ifdef SK_DEVELOPER #define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static SkRTConf varName(confName, defaultValue, description) -#define SK_CONF_SET(confname, value) skRTConfRegistry().set(confname, value) +#define SK_CONF_SET(confname, value) \ + skRTConfRegistry().set(confname, value, true) +/* SK_CONF_TRY_SET() is like SK_CONF_SET(), but doesn't complain if + confname can't be found. This is useful if the SK_CONF_DECLARE is + inside a source file whose linkage is dependent on the system. */ +#define SK_CONF_TRY_SET(confname, value) \ + skRTConfRegistry().set(confname, value, false) #else -#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static const confType varName = defaultValue +#define SK_CONF_DECLARE(confType, varName, confName, defaultValue, description) static confType varName = defaultValue #define SK_CONF_SET(confname, value) (void) confname, (void) value +#define SK_CONF_TRY_SET(confname, value) (void) confname, (void) value #endif /** \class SkRTConfRegistry @@ -67,12 +74,19 @@ protected: class SkRTConfRegistry { public: SkRTConfRegistry(); + ~SkRTConfRegistry(); void printAll(const char *fname = NULL) const; + bool hasNonDefault() const; void printNonDefault(const char *fname = NULL) const; const char *configFileLocation() const; void possiblyDumpFile() const; void validate() const; - template void set(const char *confname, T value); + template void set(const char *confname, + T value, + bool warnIfNotFound = true); +#ifdef SK_SUPPORT_UNITTEST + static void UnitTest(); +#endif private: template friend class SkRTConf; @@ -82,6 +96,9 @@ private: SkTDArray fConfigFileKeys, fConfigFileValues; typedef SkTDict< SkTDArray * > ConfMap; ConfMap fConfs; +#ifdef SK_SUPPORT_UNITTEST + SkRTConfRegistry(bool); +#endif }; // our singleton registry @@ -105,14 +122,20 @@ SkRTConf::SkRTConf(const char *name, const T &defaultValue, const char *descr template void SkRTConf::print(SkWStream *o) const { char outline[200]; // should be ok because we specify a max. width for everything here. + char *outptr; + if (strlen(getName()) >= 30) { + o->writeText(getName()); + o->writeText(" "); + outptr = &(outline[0]); + } else { + sprintf(outline, "%-30.30s", getName()); + outptr = &(outline[30]); + } - sprintf(outline, "%-30.30s", getName()); - doPrint(&(outline[30])); - sprintf(&(outline[60]), " %.128s", fDescription.c_str()); - if (' ' == outline[strlen(outline)-1]) { - for (int i = strlen(outline)-1 ; ' ' == outline[i] ; i--) { - outline[i] = '\0'; - } + doPrint(outptr); + sprintf(outptr+30, " %.128s", fDescription.c_str()); + for (size_t i = strlen(outline); i --> 0 && ' ' == outline[i];) { + outline[i] = '\0'; } o->writeText(outline); } diff --git a/gfx/skia/include/utils/SkRandom.h b/gfx/skia/trunk/include/utils/SkRandom.h similarity index 91% rename from gfx/skia/include/utils/SkRandom.h rename to gfx/skia/trunk/include/utils/SkRandom.h index 3e2ef201ad42..d083fc6b2f35 100644 --- a/gfx/skia/include/utils/SkRandom.h +++ b/gfx/skia/trunk/include/utils/SkRandom.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,23 +5,21 @@ * found in the LICENSE file. */ - #ifndef SkRandom_DEFINED #define SkRandom_DEFINED -#include "Sk64.h" #include "SkScalar.h" -/** \class SkRandom +/** \class SkLCGRandom Utility class that implements pseudo random 32bit numbers using a fast linear equation. Unlike rand(), this class holds its own seed (initially set to 0), so that multiple instances can be used with no side-effects. */ -class SkRandom { +class SkLCGRandom { public: - SkRandom() : fSeed(0) {} - SkRandom(uint32_t seed) : fSeed(seed) {} + SkLCGRandom() : fSeed(0) {} + SkLCGRandom(uint32_t seed) : fSeed(seed) {} /** Return the next pseudo random number as an unsigned 32bit value. */ @@ -104,7 +101,7 @@ public: in the range [min..max). */ SkScalar nextRangeScalar(SkScalar min, SkScalar max) { - return SkScalarMul(this->nextUScalar1(), (max - min)) + min; + return this->nextUScalar1() * (max - min) + min; } /** Return the next pseudo random number expressed as a SkScalar @@ -123,11 +120,12 @@ public: return this->nextUScalar1() <= fractionTrue; } - /** Return the next pseudo random number as a signed 64bit value. - */ - void next64(Sk64* a) { - SkASSERT(a); - a->set(this->nextS(), this->nextU()); + /** + * Return the next pseudo random number as a signed 64bit value. + */ + int64_t next64() { + int64_t hi = this->nextS(); + return (hi << 32) | this->nextU(); } /** @@ -151,7 +149,7 @@ private: uint32_t fSeed; }; -/** \class SkMWCRandom +/** \class SkRandom Utility class that implements pseudo random 32bit numbers using Marsaglia's multiply-with-carry "mother of all" algorithm. Unlike rand(), this class holds @@ -159,13 +157,13 @@ private: Has a large period and all bits are well-randomized. */ -class SkMWCRandom { +class SkRandom { public: - SkMWCRandom() { init(0); } - SkMWCRandom(uint32_t seed) { init(seed); } - SkMWCRandom(const SkMWCRandom& rand) : fK(rand.fK), fJ(rand.fJ) {} + SkRandom() { init(0); } + SkRandom(uint32_t seed) { init(seed); } + SkRandom(const SkRandom& rand) : fK(rand.fK), fJ(rand.fJ) {} - SkMWCRandom& operator=(const SkMWCRandom& rand) { + SkRandom& operator=(const SkRandom& rand) { fK = rand.fK; fJ = rand.fJ; @@ -257,7 +255,7 @@ public: in the range [min..max). */ SkScalar nextRangeScalar(SkScalar min, SkScalar max) { - return SkScalarMul(this->nextUScalar1(), (max - min)) + min; + return this->nextUScalar1() * (max - min) + min; } /** Return the next pseudo random number expressed as a SkScalar @@ -276,11 +274,12 @@ public: return this->nextUScalar1() <= fractionTrue; } - /** Return the next pseudo random number as a signed 64bit value. + /** + * Return the next pseudo random number as a signed 64bit value. */ - void next64(Sk64* a) { - SkASSERT(a); - a->set(this->nextS(), this->nextU()); + int64_t next64() { + int64_t hi = this->nextS(); + return (hi << 32) | this->nextU(); } /** Reset the random object. diff --git a/gfx/skia/include/utils/SkRunnable.h b/gfx/skia/trunk/include/utils/SkRunnable.h similarity index 100% rename from gfx/skia/include/utils/SkRunnable.h rename to gfx/skia/trunk/include/utils/SkRunnable.h diff --git a/gfx/skia/include/utils/SkThreadPool.h b/gfx/skia/trunk/include/utils/SkThreadPool.h similarity index 50% rename from gfx/skia/include/utils/SkThreadPool.h rename to gfx/skia/trunk/include/utils/SkThreadPool.h index cc45fc2cd53f..0aa7c08ad53b 100644 --- a/gfx/skia/include/utils/SkThreadPool.h +++ b/gfx/skia/trunk/include/utils/SkThreadPool.h @@ -9,18 +9,19 @@ #define SkThreadPool_DEFINED #include "SkCondVar.h" +#include "SkRunnable.h" #include "SkTDArray.h" #include "SkTInternalLList.h" -class SkRunnable; class SkThread; class SkThreadPool { public: /** - * Create a threadpool with exactly count (>=0) threads. + * Create a threadpool with count threads, or one thread per core if kThreadPerCore. */ + static const int kThreadPerCore = -1; explicit SkThreadPool(int count); ~SkThreadPool(); @@ -30,6 +31,11 @@ public: */ void add(SkRunnable*); + /** + * Block until all added SkRunnables have completed. Once called, calling add() is undefined. + */ + void wait(); + private: struct LinkedRunnable { // Unowned pointer. @@ -39,10 +45,17 @@ public: SK_DECLARE_INTERNAL_LLIST_INTERFACE(LinkedRunnable); }; - SkTInternalLList fQueue; - SkCondVar fReady; - SkTDArray fThreads; - bool fDone; + enum State { + kRunning_State, // Normal case. We've been constructed and no one has called wait(). + kWaiting_State, // wait has been called, but there still might be work to do or being done. + kHalting_State, // There's no work to do and no thread is busy. All threads can shut down. + }; + + SkTInternalLList fQueue; + SkCondVar fReady; + SkTDArray fThreads; + State fState; + int fBusyThreads; static void Loop(void*); // Static because we pass in this. }; diff --git a/gfx/skia/include/utils/SkUnitMappers.h b/gfx/skia/trunk/include/utils/SkUnitMappers.h similarity index 83% rename from gfx/skia/include/utils/SkUnitMappers.h rename to gfx/skia/trunk/include/utils/SkUnitMappers.h index 64aab5ddee77..3833e69f9544 100644 --- a/gfx/skia/include/utils/SkUnitMappers.h +++ b/gfx/skia/trunk/include/utils/SkUnitMappers.h @@ -23,12 +23,12 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiscreteMapper) protected: - SkDiscreteMapper(SkFlattenableReadBuffer& ); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkDiscreteMapper(SkReadBuffer& ); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; private: int fSegments; - SkFract fScale; // computed from fSegments + int32_t fScale; // computed from fSegments typedef SkUnitMapper INHERITED; }; @@ -45,7 +45,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkCosineMapper) protected: - SkCosineMapper(SkFlattenableReadBuffer&); + SkCosineMapper(SkReadBuffer&); private: diff --git a/gfx/skia/include/utils/SkWGL.h b/gfx/skia/trunk/include/utils/SkWGL.h similarity index 96% rename from gfx/skia/include/utils/SkWGL.h rename to gfx/skia/trunk/include/utils/SkWGL.h index 3d941742bfaf..5f630a16892a 100644 --- a/gfx/skia/include/utils/SkWGL.h +++ b/gfx/skia/trunk/include/utils/SkWGL.h @@ -27,7 +27,7 @@ #define WIN32_LEAN_AND_MEAN #define SK_LOCAL_LEAN_AND_MEAN #endif -#include +#include #if defined(SK_LOCAL_LEAN_AND_MEAN) #undef WIN32_LEAN_AND_MEAN #undef SK_LOCAL_LEAN_AND_MEAN @@ -43,8 +43,6 @@ #define SK_WGL_FULL_ACCELERATION 0x2027 #define SK_WGL_SAMPLE_BUFFERS 0x2041 #define SK_WGL_SAMPLES 0x2042 -#define SK_WGL_COVERAGE_SAMPLES 0x2042 /* same as SAMPLES */ -#define SK_WGL_COLOR_SAMPLES 0x20B9 #define SK_WGL_CONTEXT_MAJOR_VERSION 0x2091 #define SK_WGL_CONTEXT_MINOR_VERSION 0x2092 #define SK_WGL_CONTEXT_LAYER_PLANE 0x2093 diff --git a/gfx/skia/include/utils/ios/SkStream_NSData.h b/gfx/skia/trunk/include/utils/ios/SkStream_NSData.h similarity index 100% rename from gfx/skia/include/utils/ios/SkStream_NSData.h rename to gfx/skia/trunk/include/utils/ios/SkStream_NSData.h diff --git a/gfx/skia/include/utils/mac/SkCGUtils.h b/gfx/skia/trunk/include/utils/mac/SkCGUtils.h similarity index 100% rename from gfx/skia/include/utils/mac/SkCGUtils.h rename to gfx/skia/trunk/include/utils/mac/SkCGUtils.h diff --git a/gfx/skia/include/utils/win/SkAutoCoInitialize.h b/gfx/skia/trunk/include/utils/win/SkAutoCoInitialize.h similarity index 96% rename from gfx/skia/include/utils/win/SkAutoCoInitialize.h rename to gfx/skia/trunk/include/utils/win/SkAutoCoInitialize.h index 709fa6bab93a..f671e682051e 100644 --- a/gfx/skia/include/utils/win/SkAutoCoInitialize.h +++ b/gfx/skia/trunk/include/utils/win/SkAutoCoInitialize.h @@ -11,7 +11,7 @@ #define SkAutoCo_DEFINED #define WIN32_LEAN_AND_MEAN -#include +#include #include "SkTemplates.h" /** diff --git a/gfx/skia/include/utils/win/SkHRESULT.h b/gfx/skia/trunk/include/utils/win/SkHRESULT.h similarity index 91% rename from gfx/skia/include/utils/win/SkHRESULT.h rename to gfx/skia/trunk/include/utils/win/SkHRESULT.h index 9738f74916b8..4f9d1bec796e 100644 --- a/gfx/skia/include/utils/win/SkHRESULT.h +++ b/gfx/skia/trunk/include/utils/win/SkHRESULT.h @@ -38,6 +38,7 @@ The HR variants will return the HRESULT when FAILED. The HRB variants will return false when FAILED. The HRN variants will return NULL when FAILED. The HRV variants will simply return when FAILED. +The HRZ variants will return 0 when FAILED. */ #define HR(ex) HR_GENERAL(ex, NULL, _hr) #define HRM(ex, msg) HR_GENERAL(ex, msg, _hr) @@ -50,5 +51,8 @@ The HRV variants will simply return when FAILED. #define HRV(ex) HR_GENERAL(ex, NULL, ) #define HRVM(ex, msg) HR_GENERAL(ex, msg, ) + +#define HRZ(ex) HR_GENERAL(ex, NULL, 0) +#define HRZM(ex, msg) HR_GENERAL(ex, msg, 0) //@} #endif diff --git a/gfx/skia/include/utils/win/SkIStream.h b/gfx/skia/trunk/include/utils/win/SkIStream.h similarity index 99% rename from gfx/skia/include/utils/win/SkIStream.h rename to gfx/skia/trunk/include/utils/win/SkIStream.h index e4e045c9888a..deb3f3b0047e 100644 --- a/gfx/skia/include/utils/win/SkIStream.h +++ b/gfx/skia/trunk/include/utils/win/SkIStream.h @@ -11,7 +11,7 @@ #define SkIStream_DEFINED #define WIN32_LEAN_AND_MEAN -#include +#include #include class SkStream; diff --git a/gfx/skia/include/utils/win/SkTScopedComPtr.h b/gfx/skia/trunk/include/utils/win/SkTScopedComPtr.h similarity index 85% rename from gfx/skia/include/utils/win/SkTScopedComPtr.h rename to gfx/skia/trunk/include/utils/win/SkTScopedComPtr.h index 85c314a97ae0..8f18a42481be 100644 --- a/gfx/skia/include/utils/win/SkTScopedComPtr.h +++ b/gfx/skia/trunk/include/utils/win/SkTScopedComPtr.h @@ -6,8 +6,8 @@ * found in the LICENSE file. */ -#ifndef SkSkTScopedPtr_DEFINED -#define SkSkTScopedPtr_DEFINED +#ifndef SkTScopedComPtr_DEFINED +#define SkTScopedComPtr_DEFINED #include "SkTypes.h" #include "SkTemplates.h" @@ -19,6 +19,18 @@ private: virtual ULONG STDMETHODCALLTYPE Release(void) = 0; }; +template T* SkRefComPtr(T* ptr) { + ptr->AddRef(); + return ptr; +} + +template T* SkSafeRefComPtr(T* ptr) { + if (ptr) { + ptr->AddRef(); + } + return ptr; +} + template class SkTScopedComPtr : SkNoncopyable { private: diff --git a/gfx/skia/include/views/SkApplication.h b/gfx/skia/trunk/include/views/SkApplication.h similarity index 100% rename from gfx/skia/include/views/SkApplication.h rename to gfx/skia/trunk/include/views/SkApplication.h diff --git a/gfx/skia/include/views/SkBGViewArtist.h b/gfx/skia/trunk/include/views/SkBGViewArtist.h similarity index 100% rename from gfx/skia/include/views/SkBGViewArtist.h rename to gfx/skia/trunk/include/views/SkBGViewArtist.h diff --git a/gfx/skia/include/views/SkEvent.h b/gfx/skia/trunk/include/views/SkEvent.h similarity index 100% rename from gfx/skia/include/views/SkEvent.h rename to gfx/skia/trunk/include/views/SkEvent.h diff --git a/gfx/skia/include/views/SkEventSink.h b/gfx/skia/trunk/include/views/SkEventSink.h similarity index 100% rename from gfx/skia/include/views/SkEventSink.h rename to gfx/skia/trunk/include/views/SkEventSink.h diff --git a/gfx/skia/include/views/SkKey.h b/gfx/skia/trunk/include/views/SkKey.h similarity index 100% rename from gfx/skia/include/views/SkKey.h rename to gfx/skia/trunk/include/views/SkKey.h diff --git a/gfx/skia/include/views/SkOSMenu.h b/gfx/skia/trunk/include/views/SkOSMenu.h similarity index 100% rename from gfx/skia/include/views/SkOSMenu.h rename to gfx/skia/trunk/include/views/SkOSMenu.h diff --git a/gfx/skia/include/views/SkOSWindow_Android.h b/gfx/skia/trunk/include/views/SkOSWindow_Android.h similarity index 76% rename from gfx/skia/include/views/SkOSWindow_Android.h rename to gfx/skia/trunk/include/views/SkOSWindow_Android.h index 77c156cd23d8..ae4e88003937 100644 --- a/gfx/skia/include/views/SkOSWindow_Android.h +++ b/gfx/skia/trunk/include/views/SkOSWindow_Android.h @@ -29,12 +29,7 @@ public: int fStencilBits; }; - bool attach(SkBackEndTypes /* attachType */, int /* msaaSampleCount */, AttachmentInfo* info) { - // These are the values requested in SkiaSampleView.java - info->fSampleCount = 0; - info->fStencilBits = 8; - return true; - } + bool attach(SkBackEndTypes attachType, int msaaSampleCount, AttachmentInfo* info); void detach() {} void present() {} diff --git a/gfx/skia/include/views/SkOSWindow_Mac.h b/gfx/skia/trunk/include/views/SkOSWindow_Mac.h similarity index 100% rename from gfx/skia/include/views/SkOSWindow_Mac.h rename to gfx/skia/trunk/include/views/SkOSWindow_Mac.h diff --git a/gfx/skia/include/views/SkOSWindow_NaCl.h b/gfx/skia/trunk/include/views/SkOSWindow_NaCl.h similarity index 100% rename from gfx/skia/include/views/SkOSWindow_NaCl.h rename to gfx/skia/trunk/include/views/SkOSWindow_NaCl.h diff --git a/gfx/skia/include/views/SkOSWindow_SDL.h b/gfx/skia/trunk/include/views/SkOSWindow_SDL.h similarity index 100% rename from gfx/skia/include/views/SkOSWindow_SDL.h rename to gfx/skia/trunk/include/views/SkOSWindow_SDL.h diff --git a/gfx/skia/include/views/SkOSWindow_Unix.h b/gfx/skia/trunk/include/views/SkOSWindow_Unix.h similarity index 84% rename from gfx/skia/include/views/SkOSWindow_Unix.h rename to gfx/skia/trunk/include/views/SkOSWindow_Unix.h index 89265a4367ab..8a55ef455ef1 100644 --- a/gfx/skia/include/views/SkOSWindow_Unix.h +++ b/gfx/skia/trunk/include/views/SkOSWindow_Unix.h @@ -32,7 +32,6 @@ public: void* getDisplay() const { return (void*)fUnixWindow.fDisplay; } void* getUnixWindow() const { return (void*)&fUnixWindow; } void loop(); - void post_linuxevent(); enum SkBackEndTypes { kNone_BackEndType, @@ -54,14 +53,16 @@ public: protected: // Overridden from from SkWindow: - virtual bool onEvent(const SkEvent&) SK_OVERRIDE; - virtual void onHandleInval(const SkIRect&) SK_OVERRIDE; - virtual bool onHandleChar(SkUnichar) SK_OVERRIDE; - virtual bool onHandleKey(SkKey) SK_OVERRIDE; - virtual bool onHandleKeyUp(SkKey) SK_OVERRIDE; virtual void onSetTitle(const char title[]) SK_OVERRIDE; private: + enum NextXEventResult { + kContinue_NextXEventResult, + kQuitRequest_NextXEventResult, + kPaintRequest_NextXEventResult + }; + + NextXEventResult nextXEvent(); void doPaint(); void mapWindowAndWait(); diff --git a/gfx/skia/include/views/SkOSWindow_Win.h b/gfx/skia/trunk/include/views/SkOSWindow_Win.h similarity index 100% rename from gfx/skia/include/views/SkOSWindow_Win.h rename to gfx/skia/trunk/include/views/SkOSWindow_Win.h diff --git a/gfx/skia/include/views/SkOSWindow_iOS.h b/gfx/skia/trunk/include/views/SkOSWindow_iOS.h similarity index 100% rename from gfx/skia/include/views/SkOSWindow_iOS.h rename to gfx/skia/trunk/include/views/SkOSWindow_iOS.h diff --git a/gfx/skia/include/views/SkStackViewLayout.h b/gfx/skia/trunk/include/views/SkStackViewLayout.h similarity index 100% rename from gfx/skia/include/views/SkStackViewLayout.h rename to gfx/skia/trunk/include/views/SkStackViewLayout.h diff --git a/gfx/skia/include/views/SkSystemEventTypes.h b/gfx/skia/trunk/include/views/SkSystemEventTypes.h similarity index 100% rename from gfx/skia/include/views/SkSystemEventTypes.h rename to gfx/skia/trunk/include/views/SkSystemEventTypes.h diff --git a/gfx/skia/include/views/SkTextBox.h b/gfx/skia/trunk/include/views/SkTextBox.h similarity index 100% rename from gfx/skia/include/views/SkTextBox.h rename to gfx/skia/trunk/include/views/SkTextBox.h diff --git a/gfx/skia/include/views/SkTouchGesture.h b/gfx/skia/trunk/include/views/SkTouchGesture.h similarity index 100% rename from gfx/skia/include/views/SkTouchGesture.h rename to gfx/skia/trunk/include/views/SkTouchGesture.h diff --git a/gfx/skia/include/views/SkView.h b/gfx/skia/trunk/include/views/SkView.h similarity index 99% rename from gfx/skia/include/views/SkView.h rename to gfx/skia/trunk/include/views/SkView.h index 786d36304147..d03c7415ebb2 100644 --- a/gfx/skia/include/views/SkView.h +++ b/gfx/skia/trunk/include/views/SkView.h @@ -365,8 +365,14 @@ protected: virtual void onPostInflate(const SkTDict&); public: +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif // default action is to inval the view virtual void onFocusChange(bool gainFocusP); + protected: // override these if you're acting as a layer/host diff --git a/gfx/skia/include/views/SkViewInflate.h b/gfx/skia/trunk/include/views/SkViewInflate.h similarity index 100% rename from gfx/skia/include/views/SkViewInflate.h rename to gfx/skia/trunk/include/views/SkViewInflate.h diff --git a/gfx/skia/include/views/SkWidget.h b/gfx/skia/trunk/include/views/SkWidget.h similarity index 100% rename from gfx/skia/include/views/SkWidget.h rename to gfx/skia/trunk/include/views/SkWidget.h diff --git a/gfx/skia/include/views/SkWindow.h b/gfx/skia/trunk/include/views/SkWindow.h similarity index 96% rename from gfx/skia/include/views/SkWindow.h rename to gfx/skia/trunk/include/views/SkWindow.h index ca68e75760c8..f8dffa3a0c23 100644 --- a/gfx/skia/include/views/SkWindow.h +++ b/gfx/skia/trunk/include/views/SkWindow.h @@ -34,8 +34,6 @@ public: void setConfig(SkBitmap::Config); void resize(int width, int height, SkBitmap::Config config = SkBitmap::kNo_Config); - void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b); - void eraseRGB(U8CPU r, U8CPU g, U8CPU b); bool isDirty() const { return !fDirtyRgn.isEmpty(); } bool update(SkIRect* updateArea); diff --git a/gfx/skia/include/views/android/AndroidKeyToSkKey.h b/gfx/skia/trunk/include/views/android/AndroidKeyToSkKey.h similarity index 100% rename from gfx/skia/include/views/android/AndroidKeyToSkKey.h rename to gfx/skia/trunk/include/views/android/AndroidKeyToSkKey.h diff --git a/gfx/skia/include/views/animated/SkBorderView.h b/gfx/skia/trunk/include/views/animated/SkBorderView.h similarity index 100% rename from gfx/skia/include/views/animated/SkBorderView.h rename to gfx/skia/trunk/include/views/animated/SkBorderView.h diff --git a/gfx/skia/include/views/animated/SkImageView.h b/gfx/skia/trunk/include/views/animated/SkImageView.h similarity index 100% rename from gfx/skia/include/views/animated/SkImageView.h rename to gfx/skia/trunk/include/views/animated/SkImageView.h diff --git a/gfx/skia/include/views/animated/SkProgressBarView.h b/gfx/skia/trunk/include/views/animated/SkProgressBarView.h similarity index 100% rename from gfx/skia/include/views/animated/SkProgressBarView.h rename to gfx/skia/trunk/include/views/animated/SkProgressBarView.h diff --git a/gfx/skia/include/views/animated/SkScrollBarView.h b/gfx/skia/trunk/include/views/animated/SkScrollBarView.h similarity index 100% rename from gfx/skia/include/views/animated/SkScrollBarView.h rename to gfx/skia/trunk/include/views/animated/SkScrollBarView.h diff --git a/gfx/skia/include/views/animated/SkWidgetViews.h b/gfx/skia/trunk/include/views/animated/SkWidgetViews.h similarity index 100% rename from gfx/skia/include/views/animated/SkWidgetViews.h rename to gfx/skia/trunk/include/views/animated/SkWidgetViews.h diff --git a/gfx/skia/include/views/unix/XkeysToSkKeys.h b/gfx/skia/trunk/include/views/unix/XkeysToSkKeys.h similarity index 100% rename from gfx/skia/include/views/unix/XkeysToSkKeys.h rename to gfx/skia/trunk/include/views/unix/XkeysToSkKeys.h diff --git a/gfx/skia/include/views/unix/keysym2ucs.h b/gfx/skia/trunk/include/views/unix/keysym2ucs.h similarity index 100% rename from gfx/skia/include/views/unix/keysym2ucs.h rename to gfx/skia/trunk/include/views/unix/keysym2ucs.h diff --git a/gfx/skia/include/xml/SkBML_WXMLParser.h b/gfx/skia/trunk/include/xml/SkBML_WXMLParser.h similarity index 100% rename from gfx/skia/include/xml/SkBML_WXMLParser.h rename to gfx/skia/trunk/include/xml/SkBML_WXMLParser.h diff --git a/gfx/skia/include/xml/SkBML_XMLParser.h b/gfx/skia/trunk/include/xml/SkBML_XMLParser.h similarity index 100% rename from gfx/skia/include/xml/SkBML_XMLParser.h rename to gfx/skia/trunk/include/xml/SkBML_XMLParser.h diff --git a/gfx/skia/include/xml/SkDOM.h b/gfx/skia/trunk/include/xml/SkDOM.h similarity index 100% rename from gfx/skia/include/xml/SkDOM.h rename to gfx/skia/trunk/include/xml/SkDOM.h diff --git a/gfx/skia/include/xml/SkJS.h b/gfx/skia/trunk/include/xml/SkJS.h similarity index 100% rename from gfx/skia/include/xml/SkJS.h rename to gfx/skia/trunk/include/xml/SkJS.h diff --git a/gfx/skia/include/xml/SkXMLParser.h b/gfx/skia/trunk/include/xml/SkXMLParser.h similarity index 100% rename from gfx/skia/include/xml/SkXMLParser.h rename to gfx/skia/trunk/include/xml/SkXMLParser.h diff --git a/gfx/skia/include/xml/SkXMLWriter.h b/gfx/skia/trunk/include/xml/SkXMLWriter.h similarity index 100% rename from gfx/skia/include/xml/SkXMLWriter.h rename to gfx/skia/trunk/include/xml/SkXMLWriter.h diff --git a/gfx/skia/src/animator/SkAnimate.h b/gfx/skia/trunk/src/animator/SkAnimate.h similarity index 100% rename from gfx/skia/src/animator/SkAnimate.h rename to gfx/skia/trunk/src/animator/SkAnimate.h diff --git a/gfx/skia/src/animator/SkAnimate3DSchema.xsd b/gfx/skia/trunk/src/animator/SkAnimate3DSchema.xsd similarity index 100% rename from gfx/skia/src/animator/SkAnimate3DSchema.xsd rename to gfx/skia/trunk/src/animator/SkAnimate3DSchema.xsd diff --git a/gfx/skia/src/animator/SkAnimate3DSchema.xsx b/gfx/skia/trunk/src/animator/SkAnimate3DSchema.xsx similarity index 100% rename from gfx/skia/src/animator/SkAnimate3DSchema.xsx rename to gfx/skia/trunk/src/animator/SkAnimate3DSchema.xsx diff --git a/gfx/skia/src/animator/SkAnimateActive.cpp b/gfx/skia/trunk/src/animator/SkAnimateActive.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimateActive.cpp rename to gfx/skia/trunk/src/animator/SkAnimateActive.cpp diff --git a/gfx/skia/src/animator/SkAnimateActive.h b/gfx/skia/trunk/src/animator/SkAnimateActive.h similarity index 100% rename from gfx/skia/src/animator/SkAnimateActive.h rename to gfx/skia/trunk/src/animator/SkAnimateActive.h diff --git a/gfx/skia/src/animator/SkAnimateBase.cpp b/gfx/skia/trunk/src/animator/SkAnimateBase.cpp similarity index 96% rename from gfx/skia/src/animator/SkAnimateBase.cpp rename to gfx/skia/trunk/src/animator/SkAnimateBase.cpp index 3d50144abcd4..8467ce6f3582 100644 --- a/gfx/skia/src/animator/SkAnimateBase.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/animator/SkAnimateBase.h b/gfx/skia/trunk/src/animator/SkAnimateBase.h similarity index 100% rename from gfx/skia/src/animator/SkAnimateBase.h rename to gfx/skia/trunk/src/animator/SkAnimateBase.h diff --git a/gfx/skia/src/animator/SkAnimateField.cpp b/gfx/skia/trunk/src/animator/SkAnimateField.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimateField.cpp rename to gfx/skia/trunk/src/animator/SkAnimateField.cpp diff --git a/gfx/skia/src/animator/SkAnimateMaker.cpp b/gfx/skia/trunk/src/animator/SkAnimateMaker.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimateMaker.cpp rename to gfx/skia/trunk/src/animator/SkAnimateMaker.cpp diff --git a/gfx/skia/src/animator/SkAnimateMaker.h b/gfx/skia/trunk/src/animator/SkAnimateMaker.h similarity index 100% rename from gfx/skia/src/animator/SkAnimateMaker.h rename to gfx/skia/trunk/src/animator/SkAnimateMaker.h diff --git a/gfx/skia/src/animator/SkAnimateProperties.h b/gfx/skia/trunk/src/animator/SkAnimateProperties.h similarity index 100% rename from gfx/skia/src/animator/SkAnimateProperties.h rename to gfx/skia/trunk/src/animator/SkAnimateProperties.h diff --git a/gfx/skia/src/animator/SkAnimateSchema.xsd b/gfx/skia/trunk/src/animator/SkAnimateSchema.xsd similarity index 100% rename from gfx/skia/src/animator/SkAnimateSchema.xsd rename to gfx/skia/trunk/src/animator/SkAnimateSchema.xsd diff --git a/gfx/skia/src/animator/SkAnimateSchema.xsx b/gfx/skia/trunk/src/animator/SkAnimateSchema.xsx similarity index 100% rename from gfx/skia/src/animator/SkAnimateSchema.xsx rename to gfx/skia/trunk/src/animator/SkAnimateSchema.xsx diff --git a/gfx/skia/src/animator/SkAnimateSet.cpp b/gfx/skia/trunk/src/animator/SkAnimateSet.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimateSet.cpp rename to gfx/skia/trunk/src/animator/SkAnimateSet.cpp diff --git a/gfx/skia/src/animator/SkAnimateSet.h b/gfx/skia/trunk/src/animator/SkAnimateSet.h similarity index 100% rename from gfx/skia/src/animator/SkAnimateSet.h rename to gfx/skia/trunk/src/animator/SkAnimateSet.h diff --git a/gfx/skia/src/animator/SkAnimator.cpp b/gfx/skia/trunk/src/animator/SkAnimator.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimator.cpp rename to gfx/skia/trunk/src/animator/SkAnimator.cpp diff --git a/gfx/skia/src/animator/SkAnimatorScript.cpp b/gfx/skia/trunk/src/animator/SkAnimatorScript.cpp similarity index 99% rename from gfx/skia/src/animator/SkAnimatorScript.cpp rename to gfx/skia/trunk/src/animator/SkAnimatorScript.cpp index 67c53c765492..df2e5637a23d 100644 --- a/gfx/skia/src/animator/SkAnimatorScript.cpp +++ b/gfx/skia/trunk/src/animator/SkAnimatorScript.cpp @@ -165,7 +165,7 @@ bool SkAnimatorScript::EvalID(const char* token, size_t len, void* user, SkScrip displayable = engine->fWorking; if (SK_LITERAL_STR_EQUAL("parent", token, len)) { SkDisplayable* parent = displayable->getParent(); - if (parent == false) + if (parent == NULL) parent = engine->fParent; if (parent) { value->fOperand.fDisplayable = parent; diff --git a/gfx/skia/src/animator/SkAnimatorScript.h b/gfx/skia/trunk/src/animator/SkAnimatorScript.h similarity index 100% rename from gfx/skia/src/animator/SkAnimatorScript.h rename to gfx/skia/trunk/src/animator/SkAnimatorScript.h diff --git a/gfx/skia/src/animator/SkAnimatorScript2.cpp b/gfx/skia/trunk/src/animator/SkAnimatorScript2.cpp similarity index 100% rename from gfx/skia/src/animator/SkAnimatorScript2.cpp rename to gfx/skia/trunk/src/animator/SkAnimatorScript2.cpp diff --git a/gfx/skia/src/animator/SkAnimatorScript2.h b/gfx/skia/trunk/src/animator/SkAnimatorScript2.h similarity index 100% rename from gfx/skia/src/animator/SkAnimatorScript2.h rename to gfx/skia/trunk/src/animator/SkAnimatorScript2.h diff --git a/gfx/skia/src/animator/SkBoundable.cpp b/gfx/skia/trunk/src/animator/SkBoundable.cpp similarity index 100% rename from gfx/skia/src/animator/SkBoundable.cpp rename to gfx/skia/trunk/src/animator/SkBoundable.cpp diff --git a/gfx/skia/src/animator/SkBoundable.h b/gfx/skia/trunk/src/animator/SkBoundable.h similarity index 100% rename from gfx/skia/src/animator/SkBoundable.h rename to gfx/skia/trunk/src/animator/SkBoundable.h diff --git a/gfx/skia/src/animator/SkBuildCondensedInfo.cpp b/gfx/skia/trunk/src/animator/SkBuildCondensedInfo.cpp similarity index 100% rename from gfx/skia/src/animator/SkBuildCondensedInfo.cpp rename to gfx/skia/trunk/src/animator/SkBuildCondensedInfo.cpp diff --git a/gfx/skia/src/animator/SkCondensedDebug.cpp b/gfx/skia/trunk/src/animator/SkCondensedDebug.cpp similarity index 100% rename from gfx/skia/src/animator/SkCondensedDebug.cpp rename to gfx/skia/trunk/src/animator/SkCondensedDebug.cpp diff --git a/gfx/skia/src/animator/SkCondensedRelease.cpp b/gfx/skia/trunk/src/animator/SkCondensedRelease.cpp similarity index 100% rename from gfx/skia/src/animator/SkCondensedRelease.cpp rename to gfx/skia/trunk/src/animator/SkCondensedRelease.cpp diff --git a/gfx/skia/src/animator/SkDisplayAdd.cpp b/gfx/skia/trunk/src/animator/SkDisplayAdd.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayAdd.cpp rename to gfx/skia/trunk/src/animator/SkDisplayAdd.cpp diff --git a/gfx/skia/src/animator/SkDisplayAdd.h b/gfx/skia/trunk/src/animator/SkDisplayAdd.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayAdd.h rename to gfx/skia/trunk/src/animator/SkDisplayAdd.h diff --git a/gfx/skia/src/animator/SkDisplayApply.cpp b/gfx/skia/trunk/src/animator/SkDisplayApply.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayApply.cpp rename to gfx/skia/trunk/src/animator/SkDisplayApply.cpp diff --git a/gfx/skia/src/animator/SkDisplayApply.h b/gfx/skia/trunk/src/animator/SkDisplayApply.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayApply.h rename to gfx/skia/trunk/src/animator/SkDisplayApply.h diff --git a/gfx/skia/src/animator/SkDisplayBounds.cpp b/gfx/skia/trunk/src/animator/SkDisplayBounds.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayBounds.cpp rename to gfx/skia/trunk/src/animator/SkDisplayBounds.cpp diff --git a/gfx/skia/src/animator/SkDisplayBounds.h b/gfx/skia/trunk/src/animator/SkDisplayBounds.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayBounds.h rename to gfx/skia/trunk/src/animator/SkDisplayBounds.h diff --git a/gfx/skia/src/animator/SkDisplayEvent.cpp b/gfx/skia/trunk/src/animator/SkDisplayEvent.cpp similarity index 69% rename from gfx/skia/src/animator/SkDisplayEvent.cpp rename to gfx/skia/trunk/src/animator/SkDisplayEvent.cpp index c926a8aea02a..a0cfcb107356 100644 --- a/gfx/skia/src/animator/SkDisplayEvent.cpp +++ b/gfx/skia/trunk/src/animator/SkDisplayEvent.cpp @@ -250,77 +250,3 @@ bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) { } return true; } - -#ifdef SK_BUILD_FOR_ANDROID - -#include "SkMetaData.h" -#include "SkParse.h" -#include "SkTextBox.h" -#include "SkXMLWriter.h" - -void SkMetaData::setPtr(char const*, void*, PtrProc ) {} -void SkMetaData::setS32(char const*, int ) {} -bool SkEventSink::doEvent(SkEvent const& ) { return false; } -bool SkXMLParser::parse(SkStream& ) { return false; } -SkXMLParserError::SkXMLParserError( ) {} -void SkEvent::setType(char const*, size_t ) {} -void SkEvent::postTime(SkMSec) {} -SkEvent::SkEvent(char const*, SkEventSinkID) {} -SkEvent::SkEvent(SkEvent const&) {} -SkEvent::SkEvent( ) {} -SkEvent::~SkEvent( ) {} -bool SkEventSink::onQuery(SkEvent* ) { return false; } -SkEventSink::SkEventSink( ) {} -SkEventSink::~SkEventSink( ) {} -bool SkXMLParser::parse(char const*, size_t ) { return false; } -bool SkXMLParser::parse(SkDOM const&, SkDOMNode const* ) { return false; } -//void SkParse::UnitTest( ) {} -const char* SkMetaData::findString(char const* ) const {return 0;} -bool SkMetaData::findPtr(char const*, void**, PtrProc* ) const {return false;} -bool SkMetaData::findS32(char const*, int* ) const {return false;} -bool SkEvent::isType(char const*, size_t ) const { return false; } -void SkMetaData::setString(char const*, char const* ) {} -const char* SkParse::FindNamedColor(char const*, size_t, SkColor* ) {return false; } -const char* SkMetaData::Iter::next(SkMetaData::Type*, int* ) { return false; } -SkMetaData::Iter::Iter(SkMetaData const& ) {} -bool SkMetaData::findScalar(char const*, SkScalar* ) const {return false;} -void SkMetaData::reset( ) {} -void SkEvent::setType(SkString const& ) {} -bool SkMetaData::findBool(char const*, bool* ) const {return false;} -void SkEvent::getType(SkString*) const {} -bool SkXMLParser::endElement(char const* ) { return false; } -bool SkXMLParser::addAttribute(char const*, char const* ) { return false;} -bool SkXMLParser::startElement(char const* ) { return false;} -bool SkXMLParser::text(char const*, int ) { return false;} -bool SkXMLParser::onText(char const*, int ) { return false;} -SkXMLParser::SkXMLParser(SkXMLParserError* ) {} -SkXMLParser::~SkXMLParser( ) {} -SkXMLParserError::~SkXMLParserError( ) {} -void SkXMLParserError::getErrorString(SkString*) const {} -void SkTextBox::setSpacing(SkScalar, SkScalar ) {} -void SkTextBox::setSpacingAlign(SkTextBox::SpacingAlign ) {} -void SkTextBox::draw(SkCanvas*, char const*, size_t, SkPaint const& ) {} -void SkTextBox::setBox(SkRect const& ) {} -void SkTextBox::setMode(SkTextBox::Mode ) {} -SkTextBox::SkTextBox( ) {} -void SkMetaData::setScalar(char const*, SkScalar ) {} -const char* SkParse::FindScalar(char const*, SkScalar* ) {return 0; } -const char* SkParse::FindScalars(char const*, SkScalar*, int ) {return 0; } -const char* SkParse::FindHex(char const*, unsigned int* ) {return 0; } -const char* SkParse::FindS32(char const*, int* ) {return 0; } -void SkXMLWriter::addAttribute(char const*, char const* ) {} -void SkXMLWriter::startElement(char const* ) {} -void SkXMLWriter::doEnd(SkXMLWriter::Elem* ) {} -SkXMLWriter::Elem* SkXMLWriter::getEnd( ) { return 0; } -bool SkXMLWriter::doStart(char const*, size_t ) { return false; } -SkXMLWriter::SkXMLWriter(bool ) {} -SkXMLWriter::~SkXMLWriter( ) {} -SkMetaData::SkMetaData() {} -SkMetaData::~SkMetaData() {} -bool SkEventSink::onEvent(SkEvent const&) {return false;} -bool SkXMLParser::onEndElement(char const*) {return false;} -bool SkXMLParser::onAddAttribute(char const*, char const*) {return false;} -bool SkXMLParser::onStartElement(char const*) {return false;} -void SkXMLWriter::writeHeader() {} - -#endif diff --git a/gfx/skia/src/animator/SkDisplayEvent.h b/gfx/skia/trunk/src/animator/SkDisplayEvent.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayEvent.h rename to gfx/skia/trunk/src/animator/SkDisplayEvent.h diff --git a/gfx/skia/src/animator/SkDisplayEvents.cpp b/gfx/skia/trunk/src/animator/SkDisplayEvents.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayEvents.cpp rename to gfx/skia/trunk/src/animator/SkDisplayEvents.cpp diff --git a/gfx/skia/src/animator/SkDisplayEvents.h b/gfx/skia/trunk/src/animator/SkDisplayEvents.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayEvents.h rename to gfx/skia/trunk/src/animator/SkDisplayEvents.h diff --git a/gfx/skia/src/animator/SkDisplayInclude.cpp b/gfx/skia/trunk/src/animator/SkDisplayInclude.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayInclude.cpp rename to gfx/skia/trunk/src/animator/SkDisplayInclude.cpp diff --git a/gfx/skia/src/animator/SkDisplayInclude.h b/gfx/skia/trunk/src/animator/SkDisplayInclude.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayInclude.h rename to gfx/skia/trunk/src/animator/SkDisplayInclude.h diff --git a/gfx/skia/src/animator/SkDisplayInput.cpp b/gfx/skia/trunk/src/animator/SkDisplayInput.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayInput.cpp rename to gfx/skia/trunk/src/animator/SkDisplayInput.cpp diff --git a/gfx/skia/src/animator/SkDisplayInput.h b/gfx/skia/trunk/src/animator/SkDisplayInput.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayInput.h rename to gfx/skia/trunk/src/animator/SkDisplayInput.h diff --git a/gfx/skia/src/animator/SkDisplayList.cpp b/gfx/skia/trunk/src/animator/SkDisplayList.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayList.cpp rename to gfx/skia/trunk/src/animator/SkDisplayList.cpp diff --git a/gfx/skia/src/animator/SkDisplayList.h b/gfx/skia/trunk/src/animator/SkDisplayList.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayList.h rename to gfx/skia/trunk/src/animator/SkDisplayList.h diff --git a/gfx/skia/src/animator/SkDisplayMath.cpp b/gfx/skia/trunk/src/animator/SkDisplayMath.cpp similarity index 94% rename from gfx/skia/src/animator/SkDisplayMath.cpp rename to gfx/skia/trunk/src/animator/SkDisplayMath.cpp index bdf377b30268..7f406c1f655e 100644 --- a/gfx/skia/src/animator/SkDisplayMath.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/animator/SkDisplayMath.h b/gfx/skia/trunk/src/animator/SkDisplayMath.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayMath.h rename to gfx/skia/trunk/src/animator/SkDisplayMath.h diff --git a/gfx/skia/src/animator/SkDisplayMovie.cpp b/gfx/skia/trunk/src/animator/SkDisplayMovie.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayMovie.cpp rename to gfx/skia/trunk/src/animator/SkDisplayMovie.cpp diff --git a/gfx/skia/src/animator/SkDisplayMovie.h b/gfx/skia/trunk/src/animator/SkDisplayMovie.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayMovie.h rename to gfx/skia/trunk/src/animator/SkDisplayMovie.h diff --git a/gfx/skia/src/animator/SkDisplayNumber.cpp b/gfx/skia/trunk/src/animator/SkDisplayNumber.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayNumber.cpp rename to gfx/skia/trunk/src/animator/SkDisplayNumber.cpp diff --git a/gfx/skia/src/animator/SkDisplayNumber.h b/gfx/skia/trunk/src/animator/SkDisplayNumber.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayNumber.h rename to gfx/skia/trunk/src/animator/SkDisplayNumber.h diff --git a/gfx/skia/src/animator/SkDisplayPost.cpp b/gfx/skia/trunk/src/animator/SkDisplayPost.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayPost.cpp rename to gfx/skia/trunk/src/animator/SkDisplayPost.cpp diff --git a/gfx/skia/src/animator/SkDisplayPost.h b/gfx/skia/trunk/src/animator/SkDisplayPost.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayPost.h rename to gfx/skia/trunk/src/animator/SkDisplayPost.h diff --git a/gfx/skia/src/animator/SkDisplayRandom.cpp b/gfx/skia/trunk/src/animator/SkDisplayRandom.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayRandom.cpp rename to gfx/skia/trunk/src/animator/SkDisplayRandom.cpp diff --git a/gfx/skia/src/animator/SkDisplayRandom.h b/gfx/skia/trunk/src/animator/SkDisplayRandom.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayRandom.h rename to gfx/skia/trunk/src/animator/SkDisplayRandom.h diff --git a/gfx/skia/src/animator/SkDisplayScreenplay.cpp b/gfx/skia/trunk/src/animator/SkDisplayScreenplay.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayScreenplay.cpp rename to gfx/skia/trunk/src/animator/SkDisplayScreenplay.cpp diff --git a/gfx/skia/src/animator/SkDisplayScreenplay.h b/gfx/skia/trunk/src/animator/SkDisplayScreenplay.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayScreenplay.h rename to gfx/skia/trunk/src/animator/SkDisplayScreenplay.h diff --git a/gfx/skia/src/animator/SkDisplayType.cpp b/gfx/skia/trunk/src/animator/SkDisplayType.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayType.cpp rename to gfx/skia/trunk/src/animator/SkDisplayType.cpp diff --git a/gfx/skia/src/animator/SkDisplayType.h b/gfx/skia/trunk/src/animator/SkDisplayType.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayType.h rename to gfx/skia/trunk/src/animator/SkDisplayType.h diff --git a/gfx/skia/src/animator/SkDisplayTypes.cpp b/gfx/skia/trunk/src/animator/SkDisplayTypes.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayTypes.cpp rename to gfx/skia/trunk/src/animator/SkDisplayTypes.cpp diff --git a/gfx/skia/src/animator/SkDisplayTypes.h b/gfx/skia/trunk/src/animator/SkDisplayTypes.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayTypes.h rename to gfx/skia/trunk/src/animator/SkDisplayTypes.h diff --git a/gfx/skia/src/animator/SkDisplayXMLParser.cpp b/gfx/skia/trunk/src/animator/SkDisplayXMLParser.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayXMLParser.cpp rename to gfx/skia/trunk/src/animator/SkDisplayXMLParser.cpp diff --git a/gfx/skia/src/animator/SkDisplayXMLParser.h b/gfx/skia/trunk/src/animator/SkDisplayXMLParser.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayXMLParser.h rename to gfx/skia/trunk/src/animator/SkDisplayXMLParser.h diff --git a/gfx/skia/src/animator/SkDisplayable.cpp b/gfx/skia/trunk/src/animator/SkDisplayable.cpp similarity index 100% rename from gfx/skia/src/animator/SkDisplayable.cpp rename to gfx/skia/trunk/src/animator/SkDisplayable.cpp diff --git a/gfx/skia/src/animator/SkDisplayable.h b/gfx/skia/trunk/src/animator/SkDisplayable.h similarity index 100% rename from gfx/skia/src/animator/SkDisplayable.h rename to gfx/skia/trunk/src/animator/SkDisplayable.h diff --git a/gfx/skia/src/animator/SkDraw3D.cpp b/gfx/skia/trunk/src/animator/SkDraw3D.cpp similarity index 100% rename from gfx/skia/src/animator/SkDraw3D.cpp rename to gfx/skia/trunk/src/animator/SkDraw3D.cpp diff --git a/gfx/skia/src/animator/SkDraw3D.h b/gfx/skia/trunk/src/animator/SkDraw3D.h similarity index 100% rename from gfx/skia/src/animator/SkDraw3D.h rename to gfx/skia/trunk/src/animator/SkDraw3D.h diff --git a/gfx/skia/src/animator/SkDrawBitmap.cpp b/gfx/skia/trunk/src/animator/SkDrawBitmap.cpp similarity index 93% rename from gfx/skia/src/animator/SkDrawBitmap.cpp rename to gfx/skia/trunk/src/animator/SkDrawBitmap.cpp index 9f657ab2aed5..327e81365af4 100644 --- a/gfx/skia/src/animator/SkDrawBitmap.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawBitmap.cpp @@ -75,11 +75,10 @@ void SkDrawBitmap::dump(SkAnimateMaker* maker) { const char* formatName; switch (format) { case 0: formatName = "none"; break; - case 1: formatName = "A1"; break; - case 2: formatName = "A8"; break; - case 3: formatName = "Index8"; break; - case 4: formatName = "RGB16"; break; - case 5: formatName = "RGB32"; break; + case 1: formatName = "A8"; break; + case 2: formatName = "Index8"; break; + case 3: formatName = "RGB16"; break; + case 4: formatName = "RGB32"; break; } SkDebugf("format=\"%s\" />\n", formatName); } @@ -189,7 +188,7 @@ void SkImageBaseBitmap::resolve() { fBitmap.reset(); //SkStream* stream = SkStream::GetURIStream(fUriBase, src.c_str()); - SkAutoTUnref stream(SkStream::NewFromFile(src.c_str())); + SkAutoTUnref stream(SkStream::NewFromFile(src.c_str())); if (stream.get()) { SkImageDecoder::DecodeStream(stream, &fBitmap); } diff --git a/gfx/skia/src/animator/SkDrawBitmap.h b/gfx/skia/trunk/src/animator/SkDrawBitmap.h similarity index 100% rename from gfx/skia/src/animator/SkDrawBitmap.h rename to gfx/skia/trunk/src/animator/SkDrawBitmap.h diff --git a/gfx/skia/src/animator/SkDrawBlur.cpp b/gfx/skia/trunk/src/animator/SkDrawBlur.cpp similarity index 57% rename from gfx/skia/src/animator/SkDrawBlur.cpp rename to gfx/skia/trunk/src/animator/SkDrawBlur.cpp index d66fc5640f71..5f388c9310f6 100644 --- a/gfx/skia/src/animator/SkDrawBlur.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawBlur.cpp @@ -12,20 +12,21 @@ #if SK_USE_CONDENSED_INFO == 0 const SkMemberInfo SkDrawBlur::fInfo[] = { - SK_MEMBER(blurStyle, MaskFilterBlurStyle), - SK_MEMBER(radius, Float) + SK_MEMBER(fBlurStyle, MaskFilterBlurStyle), + SK_MEMBER(fSigma, Float) }; #endif DEFINE_GET_MEMBER(SkDrawBlur); -SkDrawBlur::SkDrawBlur() : radius(-1), - blurStyle(SkBlurMaskFilter::kNormal_BlurStyle) { +SkDrawBlur::SkDrawBlur() + : fSigma(-1) + , fBlurStyle(SkBlurMaskFilter::kNormal_BlurStyle) { } SkMaskFilter* SkDrawBlur::getMaskFilter() { - if (radius < 0) + if (fSigma < 0) return NULL; - return SkBlurMaskFilter::Create(radius, (SkBlurMaskFilter::BlurStyle) blurStyle); + return SkBlurMaskFilter::Create((SkBlurMaskFilter::BlurStyle) fBlurStyle, fSigma); } diff --git a/gfx/skia/src/animator/SkDrawBlur.h b/gfx/skia/trunk/src/animator/SkDrawBlur.h similarity index 71% rename from gfx/skia/src/animator/SkDrawBlur.h rename to gfx/skia/trunk/src/animator/SkDrawBlur.h index 24cb4aea4e21..0c916a382f70 100644 --- a/gfx/skia/src/animator/SkDrawBlur.h +++ b/gfx/skia/trunk/src/animator/SkDrawBlur.h @@ -16,10 +16,12 @@ class SkDrawBlur : public SkDrawMaskFilter { DECLARE_DRAW_MEMBER_INFO(Blur); SkDrawBlur(); - virtual SkMaskFilter* getMaskFilter(); + virtual SkMaskFilter* getMaskFilter() SK_OVERRIDE; protected: - SkScalar radius; - int /*SkBlurMaskFilter::BlurStyle*/ blurStyle; + SkScalar fSigma; + int /*SkBlurMaskFilter::BlurStyle*/ fBlurStyle; + + typedef SkDrawMaskFilter INHERITED; }; #endif // SkDrawBlur_DEFINED diff --git a/gfx/skia/src/animator/SkDrawClip.cpp b/gfx/skia/trunk/src/animator/SkDrawClip.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawClip.cpp rename to gfx/skia/trunk/src/animator/SkDrawClip.cpp diff --git a/gfx/skia/src/animator/SkDrawClip.h b/gfx/skia/trunk/src/animator/SkDrawClip.h similarity index 100% rename from gfx/skia/src/animator/SkDrawClip.h rename to gfx/skia/trunk/src/animator/SkDrawClip.h diff --git a/gfx/skia/src/animator/SkDrawColor.cpp b/gfx/skia/trunk/src/animator/SkDrawColor.cpp similarity index 96% rename from gfx/skia/src/animator/SkDrawColor.cpp rename to gfx/skia/trunk/src/animator/SkDrawColor.cpp index b6bc261d7181..eb57d9dad49e 100644 --- a/gfx/skia/src/animator/SkDrawColor.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/animator/SkDrawColor.h b/gfx/skia/trunk/src/animator/SkDrawColor.h similarity index 100% rename from gfx/skia/src/animator/SkDrawColor.h rename to gfx/skia/trunk/src/animator/SkDrawColor.h diff --git a/gfx/skia/src/animator/SkDrawDash.cpp b/gfx/skia/trunk/src/animator/SkDrawDash.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawDash.cpp rename to gfx/skia/trunk/src/animator/SkDrawDash.cpp diff --git a/gfx/skia/src/animator/SkDrawDash.h b/gfx/skia/trunk/src/animator/SkDrawDash.h similarity index 100% rename from gfx/skia/src/animator/SkDrawDash.h rename to gfx/skia/trunk/src/animator/SkDrawDash.h diff --git a/gfx/skia/src/animator/SkDrawDiscrete.cpp b/gfx/skia/trunk/src/animator/SkDrawDiscrete.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawDiscrete.cpp rename to gfx/skia/trunk/src/animator/SkDrawDiscrete.cpp diff --git a/gfx/skia/src/animator/SkDrawDiscrete.h b/gfx/skia/trunk/src/animator/SkDrawDiscrete.h similarity index 100% rename from gfx/skia/src/animator/SkDrawDiscrete.h rename to gfx/skia/trunk/src/animator/SkDrawDiscrete.h diff --git a/gfx/skia/src/animator/SkDrawEmboss.cpp b/gfx/skia/trunk/src/animator/SkDrawEmboss.cpp similarity index 50% rename from gfx/skia/src/animator/SkDrawEmboss.cpp rename to gfx/skia/trunk/src/animator/SkDrawEmboss.cpp index 5eed370a5dfb..70a2826d3eb3 100644 --- a/gfx/skia/src/animator/SkDrawEmboss.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawEmboss.cpp @@ -12,22 +12,23 @@ #if SK_USE_CONDENSED_INFO == 0 const SkMemberInfo SkDrawEmboss::fInfo[] = { - SK_MEMBER(ambient, Float), - SK_MEMBER_ARRAY(direction, Float), - SK_MEMBER(radius, Float), - SK_MEMBER(specular, Float) + SK_MEMBER(fAmbient, Float), + SK_MEMBER_ARRAY(fDirection, Float), + SK_MEMBER(fSigma, Float), + SK_MEMBER(fSpecular, Float) }; #endif DEFINE_GET_MEMBER(SkDrawEmboss); -SkDrawEmboss::SkDrawEmboss() : radius(-1) { - direction.setCount(3); +SkDrawEmboss::SkDrawEmboss() : fSigma(-1) { + fDirection.setCount(3); } SkMaskFilter* SkDrawEmboss::getMaskFilter() { - if (radius < 0 || direction.count() !=3) + if (fSigma < 0 || fDirection.count() !=3) return NULL; - return SkBlurMaskFilter::CreateEmboss(direction.begin(), ambient, specular, radius); + return SkBlurMaskFilter::CreateEmboss(fSigma, fDirection.begin(), + fAmbient, fSpecular); } diff --git a/gfx/skia/src/animator/SkDrawEmboss.h b/gfx/skia/trunk/src/animator/SkDrawEmboss.h similarity index 64% rename from gfx/skia/src/animator/SkDrawEmboss.h rename to gfx/skia/trunk/src/animator/SkDrawEmboss.h index 6e6199753cce..7ffd3ef8419d 100644 --- a/gfx/skia/src/animator/SkDrawEmboss.h +++ b/gfx/skia/trunk/src/animator/SkDrawEmboss.h @@ -15,10 +15,14 @@ class SkDrawEmboss : public SkDrawMaskFilter { DECLARE_DRAW_MEMBER_INFO(Emboss); SkDrawEmboss(); - virtual SkMaskFilter* getMaskFilter(); + virtual SkMaskFilter* getMaskFilter() SK_OVERRIDE; protected: - SkTDScalarArray direction; - SkScalar radius, ambient, specular; + SkTDScalarArray fDirection; + SkScalar fSigma; + SkScalar fAmbient; + SkScalar fSpecular; + + typedef SkDrawMaskFilter INHERITED; }; #endif // SkDrawEmboss_DEFINED diff --git a/gfx/skia/src/animator/SkDrawExtraPathEffect.cpp b/gfx/skia/trunk/src/animator/SkDrawExtraPathEffect.cpp similarity index 99% rename from gfx/skia/src/animator/SkDrawExtraPathEffect.cpp rename to gfx/skia/trunk/src/animator/SkDrawExtraPathEffect.cpp index e973dbf7955c..7b991d251ef0 100644 --- a/gfx/skia/src/animator/SkDrawExtraPathEffect.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawExtraPathEffect.cpp @@ -112,7 +112,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 +125,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) { diff --git a/gfx/skia/src/animator/SkDrawFull.cpp b/gfx/skia/trunk/src/animator/SkDrawFull.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawFull.cpp rename to gfx/skia/trunk/src/animator/SkDrawFull.cpp diff --git a/gfx/skia/src/animator/SkDrawFull.h b/gfx/skia/trunk/src/animator/SkDrawFull.h similarity index 100% rename from gfx/skia/src/animator/SkDrawFull.h rename to gfx/skia/trunk/src/animator/SkDrawFull.h diff --git a/gfx/skia/src/animator/SkDrawGradient.cpp b/gfx/skia/trunk/src/animator/SkDrawGradient.cpp similarity index 97% rename from gfx/skia/src/animator/SkDrawGradient.cpp rename to gfx/skia/trunk/src/animator/SkDrawGradient.cpp index 44086e4269d9..1b158f23c108 100644 --- a/gfx/skia/src/animator/SkDrawGradient.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawGradient.cpp @@ -14,20 +14,12 @@ #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 { diff --git a/gfx/skia/src/animator/SkDrawGradient.h b/gfx/skia/trunk/src/animator/SkDrawGradient.h similarity index 100% rename from gfx/skia/src/animator/SkDrawGradient.h rename to gfx/skia/trunk/src/animator/SkDrawGradient.h diff --git a/gfx/skia/src/animator/SkDrawGroup.cpp b/gfx/skia/trunk/src/animator/SkDrawGroup.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawGroup.cpp rename to gfx/skia/trunk/src/animator/SkDrawGroup.cpp diff --git a/gfx/skia/src/animator/SkDrawGroup.h b/gfx/skia/trunk/src/animator/SkDrawGroup.h similarity index 100% rename from gfx/skia/src/animator/SkDrawGroup.h rename to gfx/skia/trunk/src/animator/SkDrawGroup.h diff --git a/gfx/skia/src/animator/SkDrawLine.cpp b/gfx/skia/trunk/src/animator/SkDrawLine.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawLine.cpp rename to gfx/skia/trunk/src/animator/SkDrawLine.cpp diff --git a/gfx/skia/src/animator/SkDrawLine.h b/gfx/skia/trunk/src/animator/SkDrawLine.h similarity index 100% rename from gfx/skia/src/animator/SkDrawLine.h rename to gfx/skia/trunk/src/animator/SkDrawLine.h diff --git a/gfx/skia/src/animator/SkDrawMatrix.cpp b/gfx/skia/trunk/src/animator/SkDrawMatrix.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawMatrix.cpp rename to gfx/skia/trunk/src/animator/SkDrawMatrix.cpp diff --git a/gfx/skia/src/animator/SkDrawMatrix.h b/gfx/skia/trunk/src/animator/SkDrawMatrix.h similarity index 100% rename from gfx/skia/src/animator/SkDrawMatrix.h rename to gfx/skia/trunk/src/animator/SkDrawMatrix.h diff --git a/gfx/skia/src/animator/SkDrawOval.cpp b/gfx/skia/trunk/src/animator/SkDrawOval.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawOval.cpp rename to gfx/skia/trunk/src/animator/SkDrawOval.cpp diff --git a/gfx/skia/src/animator/SkDrawOval.h b/gfx/skia/trunk/src/animator/SkDrawOval.h similarity index 100% rename from gfx/skia/src/animator/SkDrawOval.h rename to gfx/skia/trunk/src/animator/SkDrawOval.h diff --git a/gfx/skia/src/animator/SkDrawPaint.cpp b/gfx/skia/trunk/src/animator/SkDrawPaint.cpp similarity index 98% rename from gfx/skia/src/animator/SkDrawPaint.cpp rename to gfx/skia/trunk/src/animator/SkDrawPaint.cpp index 22d99e4f21cd..825d0486a7a9 100644 --- a/gfx/skia/src/animator/SkDrawPaint.cpp +++ b/gfx/skia/trunk/src/animator/SkDrawPaint.cpp @@ -220,7 +220,7 @@ void SkDrawPaint::setupPaint(SkPaint* paint) const { if (fakeBold != -1) paint->setFakeBoldText(SkToBool(fakeBold)); if (filterBitmap != -1) - paint->setFilterBitmap(SkToBool(filterBitmap)); + paint->setFilterLevel(filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel); // stroke is legacy; style setting if present overrides stroke if (stroke != -1) paint->setStyle(SkToBool(stroke) ? SkPaint::kStroke_Style : SkPaint::kFill_Style); diff --git a/gfx/skia/src/animator/SkDrawPaint.h b/gfx/skia/trunk/src/animator/SkDrawPaint.h similarity index 100% rename from gfx/skia/src/animator/SkDrawPaint.h rename to gfx/skia/trunk/src/animator/SkDrawPaint.h diff --git a/gfx/skia/src/animator/SkDrawPath.cpp b/gfx/skia/trunk/src/animator/SkDrawPath.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawPath.cpp rename to gfx/skia/trunk/src/animator/SkDrawPath.cpp diff --git a/gfx/skia/src/animator/SkDrawPath.h b/gfx/skia/trunk/src/animator/SkDrawPath.h similarity index 100% rename from gfx/skia/src/animator/SkDrawPath.h rename to gfx/skia/trunk/src/animator/SkDrawPath.h diff --git a/gfx/skia/src/animator/SkDrawPoint.cpp b/gfx/skia/trunk/src/animator/SkDrawPoint.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawPoint.cpp rename to gfx/skia/trunk/src/animator/SkDrawPoint.cpp diff --git a/gfx/skia/src/animator/SkDrawPoint.h b/gfx/skia/trunk/src/animator/SkDrawPoint.h similarity index 100% rename from gfx/skia/src/animator/SkDrawPoint.h rename to gfx/skia/trunk/src/animator/SkDrawPoint.h diff --git a/gfx/skia/src/animator/SkDrawRectangle.cpp b/gfx/skia/trunk/src/animator/SkDrawRectangle.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawRectangle.cpp rename to gfx/skia/trunk/src/animator/SkDrawRectangle.cpp diff --git a/gfx/skia/src/animator/SkDrawRectangle.h b/gfx/skia/trunk/src/animator/SkDrawRectangle.h similarity index 100% rename from gfx/skia/src/animator/SkDrawRectangle.h rename to gfx/skia/trunk/src/animator/SkDrawRectangle.h diff --git a/gfx/skia/src/animator/SkDrawSaveLayer.cpp b/gfx/skia/trunk/src/animator/SkDrawSaveLayer.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawSaveLayer.cpp rename to gfx/skia/trunk/src/animator/SkDrawSaveLayer.cpp diff --git a/gfx/skia/src/animator/SkDrawSaveLayer.h b/gfx/skia/trunk/src/animator/SkDrawSaveLayer.h similarity index 100% rename from gfx/skia/src/animator/SkDrawSaveLayer.h rename to gfx/skia/trunk/src/animator/SkDrawSaveLayer.h diff --git a/gfx/skia/src/animator/SkDrawShader.cpp b/gfx/skia/trunk/src/animator/SkDrawShader.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawShader.cpp rename to gfx/skia/trunk/src/animator/SkDrawShader.cpp diff --git a/gfx/skia/src/animator/SkDrawShader.h b/gfx/skia/trunk/src/animator/SkDrawShader.h similarity index 100% rename from gfx/skia/src/animator/SkDrawShader.h rename to gfx/skia/trunk/src/animator/SkDrawShader.h diff --git a/gfx/skia/src/animator/SkDrawText.cpp b/gfx/skia/trunk/src/animator/SkDrawText.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawText.cpp rename to gfx/skia/trunk/src/animator/SkDrawText.cpp diff --git a/gfx/skia/src/animator/SkDrawText.h b/gfx/skia/trunk/src/animator/SkDrawText.h similarity index 100% rename from gfx/skia/src/animator/SkDrawText.h rename to gfx/skia/trunk/src/animator/SkDrawText.h diff --git a/gfx/skia/src/animator/SkDrawTextBox.cpp b/gfx/skia/trunk/src/animator/SkDrawTextBox.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawTextBox.cpp rename to gfx/skia/trunk/src/animator/SkDrawTextBox.cpp diff --git a/gfx/skia/src/animator/SkDrawTextBox.h b/gfx/skia/trunk/src/animator/SkDrawTextBox.h similarity index 100% rename from gfx/skia/src/animator/SkDrawTextBox.h rename to gfx/skia/trunk/src/animator/SkDrawTextBox.h diff --git a/gfx/skia/src/animator/SkDrawTo.cpp b/gfx/skia/trunk/src/animator/SkDrawTo.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawTo.cpp rename to gfx/skia/trunk/src/animator/SkDrawTo.cpp diff --git a/gfx/skia/src/animator/SkDrawTo.h b/gfx/skia/trunk/src/animator/SkDrawTo.h similarity index 100% rename from gfx/skia/src/animator/SkDrawTo.h rename to gfx/skia/trunk/src/animator/SkDrawTo.h diff --git a/gfx/skia/src/animator/SkDrawTransparentShader.cpp b/gfx/skia/trunk/src/animator/SkDrawTransparentShader.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawTransparentShader.cpp rename to gfx/skia/trunk/src/animator/SkDrawTransparentShader.cpp diff --git a/gfx/skia/src/animator/SkDrawTransparentShader.h b/gfx/skia/trunk/src/animator/SkDrawTransparentShader.h similarity index 100% rename from gfx/skia/src/animator/SkDrawTransparentShader.h rename to gfx/skia/trunk/src/animator/SkDrawTransparentShader.h diff --git a/gfx/skia/src/animator/SkDrawable.cpp b/gfx/skia/trunk/src/animator/SkDrawable.cpp similarity index 100% rename from gfx/skia/src/animator/SkDrawable.cpp rename to gfx/skia/trunk/src/animator/SkDrawable.cpp diff --git a/gfx/skia/src/animator/SkDrawable.h b/gfx/skia/trunk/src/animator/SkDrawable.h similarity index 100% rename from gfx/skia/src/animator/SkDrawable.h rename to gfx/skia/trunk/src/animator/SkDrawable.h diff --git a/gfx/skia/src/animator/SkDump.cpp b/gfx/skia/trunk/src/animator/SkDump.cpp similarity index 100% rename from gfx/skia/src/animator/SkDump.cpp rename to gfx/skia/trunk/src/animator/SkDump.cpp diff --git a/gfx/skia/src/animator/SkDump.h b/gfx/skia/trunk/src/animator/SkDump.h similarity index 100% rename from gfx/skia/src/animator/SkDump.h rename to gfx/skia/trunk/src/animator/SkDump.h diff --git a/gfx/skia/src/animator/SkExtraPathEffects.xsd b/gfx/skia/trunk/src/animator/SkExtraPathEffects.xsd similarity index 100% rename from gfx/skia/src/animator/SkExtraPathEffects.xsd rename to gfx/skia/trunk/src/animator/SkExtraPathEffects.xsd diff --git a/gfx/skia/src/animator/SkExtras.h b/gfx/skia/trunk/src/animator/SkExtras.h similarity index 100% rename from gfx/skia/src/animator/SkExtras.h rename to gfx/skia/trunk/src/animator/SkExtras.h diff --git a/gfx/skia/src/animator/SkGetCondensedInfo.cpp b/gfx/skia/trunk/src/animator/SkGetCondensedInfo.cpp similarity index 100% rename from gfx/skia/src/animator/SkGetCondensedInfo.cpp rename to gfx/skia/trunk/src/animator/SkGetCondensedInfo.cpp diff --git a/gfx/skia/src/animator/SkHitClear.cpp b/gfx/skia/trunk/src/animator/SkHitClear.cpp similarity index 100% rename from gfx/skia/src/animator/SkHitClear.cpp rename to gfx/skia/trunk/src/animator/SkHitClear.cpp diff --git a/gfx/skia/src/animator/SkHitClear.h b/gfx/skia/trunk/src/animator/SkHitClear.h similarity index 100% rename from gfx/skia/src/animator/SkHitClear.h rename to gfx/skia/trunk/src/animator/SkHitClear.h diff --git a/gfx/skia/src/animator/SkHitTest.cpp b/gfx/skia/trunk/src/animator/SkHitTest.cpp similarity index 100% rename from gfx/skia/src/animator/SkHitTest.cpp rename to gfx/skia/trunk/src/animator/SkHitTest.cpp diff --git a/gfx/skia/src/animator/SkHitTest.h b/gfx/skia/trunk/src/animator/SkHitTest.h similarity index 100% rename from gfx/skia/src/animator/SkHitTest.h rename to gfx/skia/trunk/src/animator/SkHitTest.h diff --git a/gfx/skia/src/animator/SkIntArray.h b/gfx/skia/trunk/src/animator/SkIntArray.h similarity index 100% rename from gfx/skia/src/animator/SkIntArray.h rename to gfx/skia/trunk/src/animator/SkIntArray.h diff --git a/gfx/skia/src/animator/SkMatrixParts.cpp b/gfx/skia/trunk/src/animator/SkMatrixParts.cpp similarity index 100% rename from gfx/skia/src/animator/SkMatrixParts.cpp rename to gfx/skia/trunk/src/animator/SkMatrixParts.cpp diff --git a/gfx/skia/src/animator/SkMatrixParts.h b/gfx/skia/trunk/src/animator/SkMatrixParts.h similarity index 100% rename from gfx/skia/src/animator/SkMatrixParts.h rename to gfx/skia/trunk/src/animator/SkMatrixParts.h diff --git a/gfx/skia/src/animator/SkMemberInfo.cpp b/gfx/skia/trunk/src/animator/SkMemberInfo.cpp similarity index 99% rename from gfx/skia/src/animator/SkMemberInfo.cpp rename to gfx/skia/trunk/src/animator/SkMemberInfo.cpp index 5e54b53aed7d..5cdc8d0de665 100644 --- a/gfx/skia/src/animator/SkMemberInfo.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/animator/SkMemberInfo.h b/gfx/skia/trunk/src/animator/SkMemberInfo.h similarity index 100% rename from gfx/skia/src/animator/SkMemberInfo.h rename to gfx/skia/trunk/src/animator/SkMemberInfo.h diff --git a/gfx/skia/src/animator/SkOpArray.cpp b/gfx/skia/trunk/src/animator/SkOpArray.cpp similarity index 100% rename from gfx/skia/src/animator/SkOpArray.cpp rename to gfx/skia/trunk/src/animator/SkOpArray.cpp diff --git a/gfx/skia/src/animator/SkOpArray.h b/gfx/skia/trunk/src/animator/SkOpArray.h similarity index 100% rename from gfx/skia/src/animator/SkOpArray.h rename to gfx/skia/trunk/src/animator/SkOpArray.h diff --git a/gfx/skia/src/animator/SkOperand.h b/gfx/skia/trunk/src/animator/SkOperand.h similarity index 100% rename from gfx/skia/src/animator/SkOperand.h rename to gfx/skia/trunk/src/animator/SkOperand.h diff --git a/gfx/skia/src/animator/SkOperand2.h b/gfx/skia/trunk/src/animator/SkOperand2.h similarity index 100% rename from gfx/skia/src/animator/SkOperand2.h rename to gfx/skia/trunk/src/animator/SkOperand2.h diff --git a/gfx/skia/src/animator/SkOperandInterpolator.h b/gfx/skia/trunk/src/animator/SkOperandInterpolator.h similarity index 100% rename from gfx/skia/src/animator/SkOperandInterpolator.h rename to gfx/skia/trunk/src/animator/SkOperandInterpolator.h diff --git a/gfx/skia/src/animator/SkOperandIterpolator.cpp b/gfx/skia/trunk/src/animator/SkOperandIterpolator.cpp similarity index 98% rename from gfx/skia/src/animator/SkOperandIterpolator.cpp rename to gfx/skia/trunk/src/animator/SkOperandIterpolator.cpp index 7822ee286e94..84b32823e1d0 100644 --- a/gfx/skia/src/animator/SkOperandIterpolator.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/animator/SkPaintParts.cpp b/gfx/skia/trunk/src/animator/SkPaintParts.cpp similarity index 100% rename from gfx/skia/src/animator/SkPaintParts.cpp rename to gfx/skia/trunk/src/animator/SkPaintParts.cpp diff --git a/gfx/skia/src/animator/SkPaintParts.h b/gfx/skia/trunk/src/animator/SkPaintParts.h similarity index 100% rename from gfx/skia/src/animator/SkPaintParts.h rename to gfx/skia/trunk/src/animator/SkPaintParts.h diff --git a/gfx/skia/src/animator/SkParseSVGPath.cpp b/gfx/skia/trunk/src/animator/SkParseSVGPath.cpp similarity index 100% rename from gfx/skia/src/animator/SkParseSVGPath.cpp rename to gfx/skia/trunk/src/animator/SkParseSVGPath.cpp diff --git a/gfx/skia/src/animator/SkPathParts.cpp b/gfx/skia/trunk/src/animator/SkPathParts.cpp similarity index 100% rename from gfx/skia/src/animator/SkPathParts.cpp rename to gfx/skia/trunk/src/animator/SkPathParts.cpp diff --git a/gfx/skia/src/animator/SkPathParts.h b/gfx/skia/trunk/src/animator/SkPathParts.h similarity index 100% rename from gfx/skia/src/animator/SkPathParts.h rename to gfx/skia/trunk/src/animator/SkPathParts.h diff --git a/gfx/skia/src/animator/SkPostParts.cpp b/gfx/skia/trunk/src/animator/SkPostParts.cpp similarity index 100% rename from gfx/skia/src/animator/SkPostParts.cpp rename to gfx/skia/trunk/src/animator/SkPostParts.cpp diff --git a/gfx/skia/src/animator/SkPostParts.h b/gfx/skia/trunk/src/animator/SkPostParts.h similarity index 100% rename from gfx/skia/src/animator/SkPostParts.h rename to gfx/skia/trunk/src/animator/SkPostParts.h diff --git a/gfx/skia/src/animator/SkScript.cpp b/gfx/skia/trunk/src/animator/SkScript.cpp similarity index 98% rename from gfx/skia/src/animator/SkScript.cpp rename to gfx/skia/trunk/src/animator/SkScript.cpp index 14ca6259254d..1d04d1b27630 100644 --- a/gfx/skia/src/animator/SkScript.cpp +++ b/gfx/skia/trunk/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; @@ -1532,11 +1532,11 @@ bool SkScriptEngine::ConvertTo(SkScriptEngine* engine, SkDisplayTypes toType, Sk SkString* strPtr = new SkString(); SkASSERT(engine); engine->track(strPtr); - if (type == SkType_Int) + if (type == SkType_Int) { strPtr->appendS32(operand.fS32); - else if (type == SkType_Displayable) + } else if (type == SkType_Displayable) { SkASSERT(0); // must call through instance version instead of static version - else { + } else { if (type != SkType_Float) { success = false; break; @@ -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 } @@ -1840,12 +1835,12 @@ static const SkScriptNAnswer scriptTests[] = { // logic testInt(1?2:3), testInt(0?2:3), - testInt(1&&2||3), - testInt(1&&0||3), - testInt(1&&0||0), - testInt(1||0&&3), - testInt(0||0&&3), - testInt(0||1&&3), + testInt((1&&2)||3), + testInt((1&&0)||3), + testInt((1&&0)||0), + testInt(1||(0&&3)), + testInt(0||(0&&3)), + testInt(0||(1&&3)), testInt(1?(2?3:4):5), testInt(0?(2?3:4):5), testInt(1?(0?3:4):5), diff --git a/gfx/skia/src/animator/SkScript.h b/gfx/skia/trunk/src/animator/SkScript.h similarity index 100% rename from gfx/skia/src/animator/SkScript.h rename to gfx/skia/trunk/src/animator/SkScript.h diff --git a/gfx/skia/src/animator/SkScript2.h b/gfx/skia/trunk/src/animator/SkScript2.h similarity index 100% rename from gfx/skia/src/animator/SkScript2.h rename to gfx/skia/trunk/src/animator/SkScript2.h diff --git a/gfx/skia/src/animator/SkScriptCallBack.h b/gfx/skia/trunk/src/animator/SkScriptCallBack.h similarity index 98% rename from gfx/skia/src/animator/SkScriptCallBack.h rename to gfx/skia/trunk/src/animator/SkScriptCallBack.h index dcbaf11886dd..fefc482f6166 100644 --- a/gfx/skia/src/animator/SkScriptCallBack.h +++ b/gfx/skia/trunk/src/animator/SkScriptCallBack.h @@ -13,6 +13,8 @@ class SkScriptCallBack { public: + virtual ~SkScriptCallBack() { } + enum Type { kBox, kFunction, diff --git a/gfx/skia/src/animator/SkScriptDecompile.cpp b/gfx/skia/trunk/src/animator/SkScriptDecompile.cpp similarity index 100% rename from gfx/skia/src/animator/SkScriptDecompile.cpp rename to gfx/skia/trunk/src/animator/SkScriptDecompile.cpp diff --git a/gfx/skia/src/animator/SkScriptRuntime.cpp b/gfx/skia/trunk/src/animator/SkScriptRuntime.cpp similarity index 99% rename from gfx/skia/src/animator/SkScriptRuntime.cpp rename to gfx/skia/trunk/src/animator/SkScriptRuntime.cpp index f28785010fa1..78d9d5c2081b 100644 --- a/gfx/skia/src/animator/SkScriptRuntime.cpp +++ b/gfx/skia/trunk/src/animator/SkScriptRuntime.cpp @@ -200,17 +200,17 @@ bool SkScriptRuntime::executeTokens(unsigned char* opCode) { operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); break; case SkScriptEngine2::kStringToInt: - if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == false) + if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == NULL) return false; break; case SkScriptEngine2::kStringToScalar: case SkScriptEngine2::kStringToScalar2: if (SkParse::FindScalar(operand[0].fString->c_str(), - &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == false) + &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == NULL) 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/gfx/skia/src/animator/SkScriptRuntime.h b/gfx/skia/trunk/src/animator/SkScriptRuntime.h similarity index 100% rename from gfx/skia/src/animator/SkScriptRuntime.h rename to gfx/skia/trunk/src/animator/SkScriptRuntime.h diff --git a/gfx/skia/src/animator/SkScriptTokenizer.cpp b/gfx/skia/trunk/src/animator/SkScriptTokenizer.cpp similarity index 99% rename from gfx/skia/src/animator/SkScriptTokenizer.cpp rename to gfx/skia/trunk/src/animator/SkScriptTokenizer.cpp index f789d388a79a..8fc5d802cb1b 100644 --- a/gfx/skia/src/animator/SkScriptTokenizer.cpp +++ b/gfx/skia/trunk/src/animator/SkScriptTokenizer.cpp @@ -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); @@ -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 } @@ -1479,7 +1474,7 @@ static const SkScriptNAnswer2 scriptTests[] = { void SkScriptEngine2::UnitTest() { #if defined(SK_SUPPORT_UNITTEST) ValidateDecompileTable(); - for (int index = 0; index < SkScriptNAnswer_testCount; index++) { + for (size_t index = 0; index < SkScriptNAnswer_testCount; index++) { SkScriptEngine2 engine(scriptTests[index].fType); SkScriptValue2 value; const char* script = scriptTests[index].fScript; diff --git a/gfx/skia/src/animator/SkSnapshot.cpp b/gfx/skia/trunk/src/animator/SkSnapshot.cpp similarity index 91% rename from gfx/skia/src/animator/SkSnapshot.cpp rename to gfx/skia/trunk/src/animator/SkSnapshot.cpp index a253d8e25991..6f818a627d7e 100644 --- a/gfx/skia/src/animator/SkSnapshot.cpp +++ b/gfx/skia/trunk/src/animator/SkSnapshot.cpp @@ -41,6 +41,10 @@ bool SkSnapshot::draw(SkAnimateMaker& maker) { SkASSERT(type >= 0); SkASSERT(filename.size() > 0); SkImageEncoder* encoder = SkImageEncoder::Create((SkImageEncoder::Type) type); + if (!encoder) { + return false; + } + SkAutoTDelete ad(encoder); SkString name(filename); if (sequence) { @@ -58,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/gfx/skia/src/animator/SkSnapshot.h b/gfx/skia/trunk/src/animator/SkSnapshot.h similarity index 100% rename from gfx/skia/src/animator/SkSnapshot.h rename to gfx/skia/trunk/src/animator/SkSnapshot.h diff --git a/gfx/skia/src/animator/SkTDArray_Experimental.h b/gfx/skia/trunk/src/animator/SkTDArray_Experimental.h similarity index 100% rename from gfx/skia/src/animator/SkTDArray_Experimental.h rename to gfx/skia/trunk/src/animator/SkTDArray_Experimental.h diff --git a/gfx/skia/src/animator/SkTextOnPath.cpp b/gfx/skia/trunk/src/animator/SkTextOnPath.cpp similarity index 100% rename from gfx/skia/src/animator/SkTextOnPath.cpp rename to gfx/skia/trunk/src/animator/SkTextOnPath.cpp diff --git a/gfx/skia/src/animator/SkTextOnPath.h b/gfx/skia/trunk/src/animator/SkTextOnPath.h similarity index 100% rename from gfx/skia/src/animator/SkTextOnPath.h rename to gfx/skia/trunk/src/animator/SkTextOnPath.h diff --git a/gfx/skia/src/animator/SkTextToPath.cpp b/gfx/skia/trunk/src/animator/SkTextToPath.cpp similarity index 100% rename from gfx/skia/src/animator/SkTextToPath.cpp rename to gfx/skia/trunk/src/animator/SkTextToPath.cpp diff --git a/gfx/skia/src/animator/SkTextToPath.h b/gfx/skia/trunk/src/animator/SkTextToPath.h similarity index 100% rename from gfx/skia/src/animator/SkTextToPath.h rename to gfx/skia/trunk/src/animator/SkTextToPath.h diff --git a/gfx/skia/src/animator/SkTime.cpp b/gfx/skia/trunk/src/animator/SkTime.cpp similarity index 79% rename from gfx/skia/src/animator/SkTime.cpp rename to gfx/skia/trunk/src/animator/SkTime.cpp index ffd6f38d571d..a4e035bd1e2e 100644 --- a/gfx/skia/src/animator/SkTime.cpp +++ b/gfx/skia/trunk/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 -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/gfx/skia/src/animator/SkTypedArray.cpp b/gfx/skia/trunk/src/animator/SkTypedArray.cpp similarity index 100% rename from gfx/skia/src/animator/SkTypedArray.cpp rename to gfx/skia/trunk/src/animator/SkTypedArray.cpp diff --git a/gfx/skia/src/animator/SkTypedArray.h b/gfx/skia/trunk/src/animator/SkTypedArray.h similarity index 100% rename from gfx/skia/src/animator/SkTypedArray.h rename to gfx/skia/trunk/src/animator/SkTypedArray.h diff --git a/gfx/skia/src/animator/SkXMLAnimatorWriter.cpp b/gfx/skia/trunk/src/animator/SkXMLAnimatorWriter.cpp similarity index 100% rename from gfx/skia/src/animator/SkXMLAnimatorWriter.cpp rename to gfx/skia/trunk/src/animator/SkXMLAnimatorWriter.cpp diff --git a/gfx/skia/src/animator/SkXMLAnimatorWriter.h b/gfx/skia/trunk/src/animator/SkXMLAnimatorWriter.h similarity index 100% rename from gfx/skia/src/animator/SkXMLAnimatorWriter.h rename to gfx/skia/trunk/src/animator/SkXMLAnimatorWriter.h diff --git a/gfx/skia/src/animator/thingstodo.txt b/gfx/skia/trunk/src/animator/thingstodo.txt similarity index 100% rename from gfx/skia/src/animator/thingstodo.txt rename to gfx/skia/trunk/src/animator/thingstodo.txt diff --git a/gfx/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h b/gfx/skia/trunk/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h similarity index 100% rename from gfx/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h rename to gfx/skia/trunk/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h diff --git a/gfx/skia/src/core/Sk64.cpp b/gfx/skia/trunk/src/core/Sk64.cpp similarity index 94% rename from gfx/skia/src/core/Sk64.cpp rename to gfx/skia/trunk/src/core/Sk64.cpp index c530ed866fb0..54b30221c906 100644 --- a/gfx/skia/src/core/Sk64.cpp +++ b/gfx/skia/trunk/src/core/Sk64.cpp @@ -133,15 +133,6 @@ void Sk64::abs() } } -//////////////////////////////////////////////////////////////// - -static inline int32_t round_right_16(int32_t hi, uint32_t lo) -{ - uint32_t sum = lo + (1 << 15); - hi += (sum < lo); - return (hi << 16) | (sum >> 16); -} - SkBool Sk64::isFixed() const { Sk64 tmp = *this; @@ -253,17 +244,11 @@ void Sk64::div(int32_t denom, DivOptions option) do { shift_left(rhi, rlo); -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR if ((uint32_t)denom <= (uint32_t)hi) { hi -= denom; rlo |= 1; } -#else - int32_t diff = (denom - hi - 1) >> 31; - hi -= denom & diff; - rlo -= diff; -#endif shift_left(hi, lo); } while (--bits >= 0); SkASSERT(rhi >= 0); diff --git a/gfx/skia/src/core/SkAAClip.cpp b/gfx/skia/trunk/src/core/SkAAClip.cpp similarity index 98% rename from gfx/skia/src/core/SkAAClip.cpp rename to gfx/skia/trunk/src/core/SkAAClip.cpp index aa7513c4d14b..14152f8317ef 100644 --- a/gfx/skia/src/core/SkAAClip.cpp +++ b/gfx/skia/trunk/src/core/SkAAClip.cpp @@ -36,9 +36,11 @@ private: #define kMaxInt32 0x7FFFFFFF +#ifdef SK_DEBUG static inline bool x_in_rect(int x, const SkIRect& rect) { return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); } +#endif static inline bool y_in_rect(int y, const SkIRect& rect) { return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); @@ -135,6 +137,7 @@ SkAAClip::Iter::Iter(const SkAAClip& clip) { fDone = true; fTop = fBottom = clip.fBounds.fBottom; fData = NULL; + fCurrYOff = NULL; fStopYOff = NULL; return; } @@ -527,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 @@ -1030,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(); @@ -1380,17 +1383,6 @@ static AlphaProc find_alpha_proc(SkRegion::Op op) { } } -static const uint8_t gEmptyRow[] = { - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, - 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, -}; - class RowIter { public: RowIter(const uint8_t* row, const SkIRect& bounds) { diff --git a/gfx/skia/src/core/SkAAClip.h b/gfx/skia/trunk/src/core/SkAAClip.h similarity index 100% rename from gfx/skia/src/core/SkAAClip.h rename to gfx/skia/trunk/src/core/SkAAClip.h diff --git a/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp b/gfx/skia/trunk/src/core/SkAdvancedTypefaceMetrics.cpp similarity index 94% rename from gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp rename to gfx/skia/trunk/src/core/SkAdvancedTypefaceMetrics.cpp index e41bb810b5df..f9b25dc96aac 100644 --- a/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp +++ b/gfx/skia/trunk/src/core/SkAdvancedTypefaceMetrics.cpp @@ -10,15 +10,14 @@ #include "SkAdvancedTypefaceMetrics.h" #include "SkTypes.h" -SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics) - #if defined(SK_BUILD_FOR_WIN) #include #endif #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID) -#include -#include FT_FREETYPE_H +// forward declare structs needed for getAdvanceData() template for freetype +struct FT_FaceRec; +typedef struct FT_FaceRec_* FT_Face; #endif #ifdef SK_BUILD_FOR_MAC @@ -71,7 +70,7 @@ void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric* range, template SkAdvancedTypefaceMetrics::AdvanceMetric* appendRange( - SkTScopedPtr >* nextSlot, + SkAutoTDelete >* nextSlot, int startId) { nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric); resetRange(nextSlot->get(), startId); @@ -147,7 +146,7 @@ SkAdvancedTypefaceMetrics::AdvanceMetric* getAdvanceData( // d. Removing a leading 0/don't cares is a win because it is omitted // e. Removing 2 repeating advances is a win - SkTScopedPtr > result; + SkAutoTDelete > result; SkAdvancedTypefaceMetrics::AdvanceMetric* curRange; SkAdvancedTypefaceMetrics::AdvanceMetric* prevRange = NULL; Data lastAdvance = kInvalidAdvance; @@ -170,6 +169,8 @@ SkAdvancedTypefaceMetrics::AdvanceMetric* getAdvanceData( Data advance = kInvalidAdvance; if (gId < lastIndex) { // Get glyph id only when subset is NULL, or the id is in subset. + SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && + static_cast(gId) <= subsetGlyphIDs[subsetIndex])); if (!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast(gId) == subsetGlyphIDs[subsetIndex])) { @@ -244,12 +245,12 @@ SkAdvancedTypefaceMetrics::AdvanceMetric* getAdvanceData( if (curRange->fStartId == lastIndex) { SkASSERT(prevRange); SkASSERT(prevRange->fNext->fStartId == lastIndex); - prevRange->fNext.reset(); + prevRange->fNext.free(); } else { finishRange(curRange, lastIndex - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); } - return result.release(); + return result.detach(); } // Make AdvanceMetric template functions available for linking with typename @@ -286,7 +287,7 @@ template void resetRange( SkAdvancedTypefaceMetrics::WidthRange* range, int startId); template SkAdvancedTypefaceMetrics::WidthRange* appendRange( - SkTScopedPtr* nextSlot, + SkAutoTDelete* nextSlot, int startId); template void finishRange( SkAdvancedTypefaceMetrics::WidthRange* range, @@ -297,7 +298,7 @@ template void resetRange( SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, int startId); template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange( - SkTScopedPtr* + SkAutoTDelete* nextSlot, int startId); template void finishRange( diff --git a/gfx/skia/trunk/src/core/SkAlphaRuns.cpp b/gfx/skia/trunk/src/core/SkAlphaRuns.cpp new file mode 100644 index 000000000000..37b1a5705ce1 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkAlphaRuns.cpp @@ -0,0 +1,73 @@ + +/* + * 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 "SkAntiRun.h" +#include "SkUtils.h" + +void SkAlphaRuns::reset(int width) { + SkASSERT(width > 0); + +#ifdef SK_DEBUG + sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width); +#endif + fRuns[0] = SkToS16(width); + fRuns[width] = 0; + fAlpha[0] = 0; + + SkDEBUGCODE(fWidth = width;) + SkDEBUGCODE(this->validate();) +} + +#ifdef SK_DEBUG + void SkAlphaRuns::assertValid(int y, int maxStep) const { + int max = (y + 1) * maxStep - (y == maxStep - 1); + + const int16_t* runs = fRuns; + const uint8_t* alpha = fAlpha; + + while (*runs) { + SkASSERT(*alpha <= max); + alpha += *runs; + runs += *runs; + } + } + + void SkAlphaRuns::dump() const { + const int16_t* runs = fRuns; + const uint8_t* alpha = fAlpha; + + SkDebugf("Runs"); + while (*runs) { + int n = *runs; + + SkDebugf(" %02x", *alpha); + if (n > 1) { + SkDebugf(",%d", n); + } + alpha += n; + runs += n; + } + SkDebugf("\n"); + } + + void SkAlphaRuns::validate() const { + SkASSERT(fWidth > 0); + + int count = 0; + const int16_t* runs = fRuns; + + while (*runs) { + SkASSERT(*runs > 0); + count += *runs; + SkASSERT(count <= fWidth); + runs += *runs; + } + SkASSERT(count == fWidth); + } +#endif diff --git a/gfx/skia/src/core/SkAnnotation.cpp b/gfx/skia/trunk/src/core/SkAnnotation.cpp similarity index 61% rename from gfx/skia/src/core/SkAnnotation.cpp rename to gfx/skia/trunk/src/core/SkAnnotation.cpp index 52fa9b79f208..6ba645ffed57 100644 --- a/gfx/skia/src/core/SkAnnotation.cpp +++ b/gfx/skia/trunk/src/core/SkAnnotation.cpp @@ -6,37 +6,37 @@ */ #include "SkAnnotation.h" -#include "SkDataSet.h" -#include "SkFlattenableBuffers.h" +#include "SkData.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" #include "SkPoint.h" #include "SkStream.h" -SkAnnotation::SkAnnotation(SkDataSet* data, uint32_t flags) { - if (NULL == data) { - data = SkDataSet::NewEmpty(); +SkAnnotation::SkAnnotation(const char key[], SkData* value) : fKey(key) { + if (NULL == value) { + value = SkData::NewEmpty(); } else { - data->ref(); + value->ref(); } - fDataSet = data; - fFlags = flags; + fData = value; } SkAnnotation::~SkAnnotation() { - fDataSet->unref(); + fData->unref(); } -SkData* SkAnnotation::find(const char name[]) const { - return fDataSet->find(name); +SkData* SkAnnotation::find(const char key[]) const { + return fKey.equals(key) ? fData : NULL; } -SkAnnotation::SkAnnotation(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - fFlags = buffer.readUInt(); - fDataSet = buffer.readFlattenableT(); +SkAnnotation::SkAnnotation(SkReadBuffer& buffer) { + buffer.readString(&fKey); + fData = buffer.readByteArrayAsData(); } -void SkAnnotation::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeUInt(fFlags); - buffer.writeFlattenable(fDataSet); +void SkAnnotation::writeToBuffer(SkWriteBuffer& buffer) const { + buffer.writeString(fKey.c_str()); + buffer.writeDataAsByteArray(fData); } const char* SkAnnotationKeys::URL_Key() { @@ -56,12 +56,7 @@ const char* SkAnnotationKeys::Link_Named_Dest_Key() { #include "SkCanvas.h" static void annotate_paint(SkPaint& paint, const char* key, SkData* value) { - SkAutoTUnref dataset(SkNEW_ARGS(SkDataSet, (key, value))); - SkAnnotation* ann = SkNEW_ARGS(SkAnnotation, (dataset, - SkAnnotation::kNoDraw_Flag)); - - paint.setAnnotation(ann)->unref(); - SkASSERT(paint.isNoDrawAnnotation()); + paint.setAnnotation(SkNEW_ARGS(SkAnnotation, (key, value)))->unref(); } void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) { diff --git a/gfx/skia/trunk/src/core/SkAntiRun.h b/gfx/skia/trunk/src/core/SkAntiRun.h new file mode 100644 index 000000000000..9a0003935f71 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkAntiRun.h @@ -0,0 +1,192 @@ + +/* + * 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 SkAntiRun_DEFINED +#define SkAntiRun_DEFINED + +#include "SkBlitter.h" + +/** Sparse array of run-length-encoded alpha (supersampling coverage) values. + Sparseness allows us to independently compose several paths into the + same SkAlphaRuns buffer. +*/ + +class SkAlphaRuns { +public: + int16_t* fRuns; + uint8_t* fAlpha; + + /// Returns true if the scanline contains only a single run, + /// of alpha value 0. + bool empty() const { + SkASSERT(fRuns[0] > 0); + return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0; + } + + /// Reinitialize for a new scanline. + void reset(int width); + + /** + * Insert into the buffer a run starting at (x-offsetX): + * if startAlpha > 0 + * one pixel with value += startAlpha, + * max 255 + * if middleCount > 0 + * middleCount pixels with value += maxValue + * if stopAlpha > 0 + * one pixel with value += stopAlpha + * Returns the offsetX value that should be passed on the next call, + * assuming we're on the same scanline. If the caller is switching + * scanlines, then offsetX should be 0 when this is called. + */ + SK_ALWAYS_INLINE int add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, + U8CPU maxValue, int offsetX) { + SkASSERT(middleCount >= 0); + SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); + + SkASSERT(fRuns[offsetX] >= 0); + + int16_t* runs = fRuns + offsetX; + uint8_t* alpha = fAlpha + offsetX; + uint8_t* lastAlpha = alpha; + x -= offsetX; + + if (startAlpha) { + SkAlphaRuns::Break(runs, alpha, x, 1); + /* I should be able to just add alpha[x] + startAlpha. + However, if the trailing edge of the previous span and the leading + edge of the current span round to the same super-sampled x value, + I might overflow to 256 with this add, hence the funny subtract (crud). + */ + unsigned tmp = alpha[x] + startAlpha; + SkASSERT(tmp <= 256); + alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256 + + runs += x + 1; + alpha += x + 1; + x = 0; + lastAlpha += x; // we don't want the +1 + SkDEBUGCODE(this->validate();) + } + + if (middleCount) { + SkAlphaRuns::Break(runs, alpha, x, middleCount); + alpha += x; + runs += x; + x = 0; + do { + alpha[0] = SkToU8(alpha[0] + maxValue); + int n = runs[0]; + SkASSERT(n <= middleCount); + alpha += n; + runs += n; + middleCount -= n; + } while (middleCount > 0); + SkDEBUGCODE(this->validate();) + lastAlpha = alpha; + } + + if (stopAlpha) { + SkAlphaRuns::Break(runs, alpha, x, 1); + alpha += x; + alpha[0] = SkToU8(alpha[0] + stopAlpha); + SkDEBUGCODE(this->validate();) + lastAlpha = alpha; + } + + return SkToS32(lastAlpha - fAlpha); // new offsetX + } + + SkDEBUGCODE(void assertValid(int y, int maxStep) const;) + SkDEBUGCODE(void dump() const;) + + /** + * Break the runs in the buffer at offsets x and x+count, properly + * updating the runs to the right and left. + * i.e. from the state AAAABBBB, run-length encoded as A4B4, + * Break(..., 2, 5) would produce AAAABBBB rle as A2A2B3B1. + * Allows add() to sum another run to some of the new sub-runs. + * i.e. adding ..CCCCC. would produce AADDEEEB, rle as A2D2E3B1. + */ + static void Break(int16_t runs[], uint8_t alpha[], int x, int count) { + SkASSERT(count > 0 && x >= 0); + + // SkAlphaRuns::BreakAt(runs, alpha, x); + // SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count); + + int16_t* next_runs = runs + x; + uint8_t* next_alpha = alpha + x; + + while (x > 0) { + int n = runs[0]; + SkASSERT(n > 0); + + if (x < n) { + alpha[x] = alpha[0]; + runs[0] = SkToS16(x); + runs[x] = SkToS16(n - x); + break; + } + runs += n; + alpha += n; + x -= n; + } + + runs = next_runs; + alpha = next_alpha; + x = count; + + for (;;) { + int n = runs[0]; + SkASSERT(n > 0); + + if (x < n) { + alpha[x] = alpha[0]; + runs[0] = SkToS16(x); + runs[x] = SkToS16(n - x); + break; + } + x -= n; + if (x <= 0) { + break; + } + runs += n; + alpha += n; + } + } + + /** + * Cut (at offset x in the buffer) a run into two shorter runs with + * matching alpha values. + * Used by the RectClipBlitter to trim a RLE encoding to match the + * clipping rectangle. + */ + static void BreakAt(int16_t runs[], uint8_t alpha[], int x) { + while (x > 0) { + int n = runs[0]; + SkASSERT(n > 0); + + if (x < n) { + alpha[x] = alpha[0]; + runs[0] = SkToS16(x); + runs[x] = SkToS16(n - x); + break; + } + runs += n; + alpha += n; + x -= n; + } + } + +private: + SkDEBUGCODE(int fWidth;) + SkDEBUGCODE(void validate() const;) +}; + +#endif diff --git a/gfx/skia/src/core/SkAutoKern.h b/gfx/skia/trunk/src/core/SkAutoKern.h similarity index 100% rename from gfx/skia/src/core/SkAutoKern.h rename to gfx/skia/trunk/src/core/SkAutoKern.h diff --git a/gfx/skia/src/core/SkBBoxHierarchy.h b/gfx/skia/trunk/src/core/SkBBoxHierarchy.h similarity index 83% rename from gfx/skia/src/core/SkBBoxHierarchy.h rename to gfx/skia/trunk/src/core/SkBBoxHierarchy.h index 62b22d80e61f..36047b9706ca 100644 --- a/gfx/skia/src/core/SkBBoxHierarchy.h +++ b/gfx/skia/trunk/src/core/SkBBoxHierarchy.h @@ -64,10 +64,20 @@ 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 diff --git a/gfx/skia/src/core/SkBBoxHierarchyRecord.cpp b/gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.cpp similarity index 87% rename from gfx/skia/src/core/SkBBoxHierarchyRecord.cpp rename to gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.cpp index 9c02468ae1c0..8e5861bb21e6 100644 --- a/gfx/skia/src/core/SkBBoxHierarchyRecord.cpp +++ b/gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.cpp @@ -11,7 +11,7 @@ SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(uint32_t recordFlags, SkBBoxHierarchy* h, - SkDevice* device) + SkBaseDevice* device) : INHERITED(recordFlags, device) { fStateTree = SkNEW(SkPictureStateTree); fBoundingHierarchy = h; @@ -22,7 +22,7 @@ SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(uint32_t recordFlags, void SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) { SkIRect r; bounds.roundOut(&r); - SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().size()); + SkPictureStateTree::Draw* draw = fStateTree->appendDraw(this->writeStream().bytesWritten()); fBoundingHierarchy->insert(draw, r, true); } @@ -33,7 +33,7 @@ int SkBBoxHierarchyRecord::save(SaveFlags flags) { int SkBBoxHierarchyRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) { - fStateTree->appendSaveLayer(this->writeStream().size()); + fStateTree->appendSaveLayer(this->writeStream().bytesWritten()); return INHERITED::saveLayer(bounds, paint, flags); } @@ -80,27 +80,27 @@ void SkBBoxHierarchyRecord::setMatrix(const SkMatrix& matrix) { bool SkBBoxHierarchyRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAntiAlias) { - fStateTree->appendClip(this->writeStream().size()); + fStateTree->appendClip(this->writeStream().bytesWritten()); return INHERITED::clipRect(rect, op, doAntiAlias); } bool SkBBoxHierarchyRecord::clipRegion(const SkRegion& region, SkRegion::Op op) { - fStateTree->appendClip(this->writeStream().size()); + fStateTree->appendClip(this->writeStream().bytesWritten()); return INHERITED::clipRegion(region, op); } bool SkBBoxHierarchyRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAntiAlias) { - fStateTree->appendClip(this->writeStream().size()); + fStateTree->appendClip(this->writeStream().bytesWritten()); return INHERITED::clipPath(path, op, doAntiAlias); } bool SkBBoxHierarchyRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAntiAlias) { - fStateTree->appendClip(this->writeStream().size()); + fStateTree->appendClip(this->writeStream().bytesWritten()); return INHERITED::clipRRect(rrect, op, doAntiAlias); } @@ -109,7 +109,7 @@ bool SkBBoxHierarchyRecord::shouldRewind(void* data) { // SkPicture has rewound its command stream. To match that rewind in the // BBH, we rewind all draws that reference commands that were recorded // past the point to which the SkPicture has rewound, which is given by - // writeStream().size(). + // writeStream().bytesWritten(). SkPictureStateTree::Draw* draw = static_cast(data); - return draw->fOffset >= writeStream().size(); + return draw->fOffset >= writeStream().bytesWritten(); } diff --git a/gfx/skia/src/core/SkBBoxHierarchyRecord.h b/gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.h similarity index 98% rename from gfx/skia/src/core/SkBBoxHierarchyRecord.h rename to gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.h index 27da3c9188fd..7284ab04ecd8 100644 --- a/gfx/skia/src/core/SkBBoxHierarchyRecord.h +++ b/gfx/skia/trunk/src/core/SkBBoxHierarchyRecord.h @@ -20,7 +20,7 @@ class SkBBoxHierarchyRecord : public SkBBoxRecord, public SkBBoxHierarchyClient public: /** This will take a ref of h */ SkBBoxHierarchyRecord(uint32_t recordFlags, SkBBoxHierarchy* h, - SkDevice*); + SkBaseDevice*); virtual void handleBBox(const SkRect& bounds) SK_OVERRIDE; diff --git a/gfx/skia/src/core/SkBBoxRecord.cpp b/gfx/skia/trunk/src/core/SkBBoxRecord.cpp similarity index 86% rename from gfx/skia/src/core/SkBBoxRecord.cpp rename to gfx/skia/trunk/src/core/SkBBoxRecord.cpp index 52d599f57ea1..a757a245ce1c 100644 --- a/gfx/skia/src/core/SkBBoxRecord.cpp +++ b/gfx/skia/trunk/src/core/SkBBoxRecord.cpp @@ -32,7 +32,7 @@ void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) { // path's device-space bounding box. SkIRect clipBounds; if (this->getClipDeviceBounds(&clipBounds)) { - this->handleBBox(SkRect::MakeFromIRect(clipBounds)); + this->handleBBox(SkRect::Make(clipBounds)); INHERITED::drawPath(path, paint); } } else if (this->transformBounds(path.getBounds(), &paint)) { @@ -43,7 +43,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 @@ -53,7 +53,7 @@ void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[], // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently // done in the recording coordinate space, which is wrong. // http://code.google.com/p/skia/issues/detail?id=1021 - static const SkScalar kMinWidth = SkFloatToScalar(0.01f); + static const SkScalar kMinWidth = 0.01f; SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2; bbox.outset(halfStrokeWidth, halfStrokeWidth); if (this->transformBounds(bbox, &paint)) { @@ -134,9 +134,10 @@ void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar to } void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) { + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) { if (this->transformBounds(dst, paint)) { - INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint); + INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags); } } @@ -178,35 +179,45 @@ void SkBBoxRecord::drawPosText(const void* text, size_t byteLength, void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { - SkRect bbox; size_t numChars = paint.countText(text, byteLength); - if (numChars > 0) { - bbox.fLeft = xpos[0]; - bbox.fRight = xpos[numChars - 1]; - // if we had a guarantee that these will be monotonically increasing, this could be sped up - for (size_t i = 1; i < numChars; ++i) { - if (xpos[i] < bbox.fLeft) { - bbox.fLeft = xpos[i]; - } - if (xpos[i] > bbox.fRight) { - bbox.fRight = xpos[i]; - } + if (numChars == 0) { + return; + } + + const SkFlatData* flatPaintData = this->getFlatPaintData(paint); + WriteTopBot(paint, *flatPaintData); + + SkScalar top = flatPaintData->topBot()[0]; + SkScalar bottom = flatPaintData->topBot()[1]; + SkScalar pad = top - bottom; + + SkRect bbox; + bbox.fLeft = SK_ScalarMax; + bbox.fRight = SK_ScalarMin; + + for (size_t i = 0; i < numChars; ++i) { + if (xpos[i] < bbox.fLeft) { + bbox.fLeft = xpos[i]; } - SkPaint::FontMetrics metrics; - paint.getFontMetrics(&metrics); - - // pad horizontally by max glyph height - SkScalar pad = (metrics.fTop - metrics.fBottom); - bbox.fLeft += pad; - bbox.fRight -= pad; - - bbox.fTop = metrics.fTop + constY; - bbox.fBottom = metrics.fBottom + constY; - if (!this->transformBounds(bbox, &paint)) { - return; + if (xpos[i] > bbox.fRight) { + bbox.fRight = xpos[i]; } } - INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint); + + // pad horizontally by max glyph height + bbox.fLeft += pad; + bbox.fRight -= pad; + + bbox.fTop = top + constY; + bbox.fBottom = bottom + constY; + + if (!this->transformBounds(bbox, &paint)) { + return; + } + // This is the equivalent of calling: + // INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint); + // but we filled our flat paint beforehand so that we could get font metrics. + drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData); } void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top, diff --git a/gfx/skia/src/core/SkBBoxRecord.h b/gfx/skia/trunk/src/core/SkBBoxRecord.h similarity index 94% rename from gfx/skia/src/core/SkBBoxRecord.h rename to gfx/skia/trunk/src/core/SkBBoxRecord.h index 9f796717e4f5..fa8b282247e8 100644 --- a/gfx/skia/src/core/SkBBoxRecord.h +++ b/gfx/skia/trunk/src/core/SkBBoxRecord.h @@ -19,7 +19,7 @@ class SkBBoxRecord : public SkPictureRecord { public: - SkBBoxRecord(uint32_t recordFlags, SkDevice* device) + SkBBoxRecord(uint32_t recordFlags, SkBaseDevice* device) : INHERITED(recordFlags, device) { } virtual ~SkBBoxRecord() { } @@ -42,7 +42,8 @@ public: virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint = NULL) SK_OVERRIDE; virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) SK_OVERRIDE; virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, diff --git a/gfx/skia/src/core/SkBitmap.cpp b/gfx/skia/trunk/src/core/SkBitmap.cpp similarity index 64% rename from gfx/skia/src/core/SkBitmap.cpp rename to gfx/skia/trunk/src/core/SkBitmap.cpp index fe4255d9b5e2..96d683c0e259 100644 --- a/gfx/skia/src/core/SkBitmap.cpp +++ b/gfx/skia/trunk/src/core/SkBitmap.cpp @@ -11,21 +11,22 @@ #include "SkColorPriv.h" #include "SkDither.h" #include "SkFlattenable.h" +#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" #include "SkUtils.h" +#include "SkValidationUtils.h" #include "SkPackBits.h" #include -SK_DEFINE_INST_COUNT(SkBitmap::Allocator) - -static bool isPos32Bits(const Sk64& value) { - return !value.isNeg() && value.is32(); +static bool reset_return_false(SkBitmap* bm) { + bm->reset(); + return false; } struct MipLevel { @@ -44,14 +45,12 @@ struct SkBitmap::MipMap : SkNoncopyable { if (levelCount < 0) { return NULL; } - Sk64 size; - size.setMul(levelCount + 1, sizeof(MipLevel)); - size.add(sizeof(MipMap)); - size.add(SkToS32(pixelSize)); - if (!isPos32Bits(size)) { + int64_t size = (levelCount + 1) * sizeof(MipLevel); + size += sizeof(MipMap) + pixelSize; + if (!sk_64_isS32(size)) { return NULL; } - MipMap* mm = (MipMap*)sk_malloc_throw(size.get32()); + MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size)); mm->fRefCnt = 1; mm->fLevelCount = levelCount; return mm; @@ -107,15 +106,7 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) { // 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,16 +126,13 @@ 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(fFlags, other.fFlags); - SkTSwap(fBytesPerPixel, other.fBytesPerPixel); SkDEBUGCODE(this->validate();) } @@ -154,14 +142,16 @@ void SkBitmap::reset() { sk_bzero(this, sizeof(*this)); } +SkBitmap::Config SkBitmap::config() const { + return SkColorTypeToBitmapConfig(fInfo.colorType()); +} + int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { int bpp; switch (config) { case kNo_Config: - case kA1_Config: bpp = 0; // not applicable break; - case kRLE_Index8_Config: case kA8_Config: case kIndex8_Config: bpp = 1; @@ -182,119 +172,134 @@ 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: - case kRLE_Index8_Config: - break; - case kA1_Config: - rowBytes.set(width); - rowBytes.add(7); - rowBytes.shiftRight(3); - 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; + int64_t size = SkBitmap::ComputeSize64(c, width, height); + return sk_64_isS32(size) ? sk_64_asS32(size) : 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; +int64_t SkBitmap::ComputeSafeSize64(Config config, + uint32_t width, + uint32_t height, + size_t rowBytes) { + SkImageInfo info = SkImageInfo::Make(width, height, + SkBitmapConfigToColorType(config), + kPremul_SkAlphaType); + return info.getSafeSize64(rowBytes); } 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 safeSize = ComputeSafeSize64(config, width, height, rowBytes); + int32_t safeSize32 = (int32_t)safeSize; + + if (safeSize32 != safeSize) { + safeSize32 = 0; + } + return safeSize32; } 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); } /////////////////////////////////////////////////////////////////////////////// -void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { +static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType, + SkAlphaType* canonical = NULL) { + switch (colorType) { + case kUnknown_SkColorType: + alphaType = kIgnore_SkAlphaType; + break; + case kAlpha_8_SkColorType: + if (kUnpremul_SkAlphaType == alphaType) { + alphaType = kPremul_SkAlphaType; + } + // fall-through + case kIndex_8_SkColorType: + case kARGB_4444_SkColorType: + case kRGBA_8888_SkColorType: + case kBGRA_8888_SkColorType: + if (kIgnore_SkAlphaType == alphaType) { + return false; + } + break; + case kRGB_565_SkColorType: + alphaType = kOpaque_SkAlphaType; + break; + default: + return false; + } + if (canonical) { + *canonical = alphaType; + } + return true; +} + +bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) { + // 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); + } + + if (info.width() < 0 || info.height() < 0) { + return reset_return_false(this); + } + + 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); + } + this->freePixels(); - if ((width | height) < 0) { - goto err; - } + fInfo = info; + fRowBytes = SkToU32(rowBytes); + return true; +} - if (rowBytes == 0) { - rowBytes = SkBitmap::ComputeRowBytes(c, width); - if (0 == rowBytes && kNo_Config != c) { - goto err; +bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, + SkAlphaType alphaType) { + SkColorType ct = SkBitmapConfigToColorType(config); + return this->setConfig(SkImageInfo::Make(width, height, ct, alphaType), + rowBytes); +} + +bool SkBitmap::setAlphaType(SkAlphaType alphaType) { + if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) { + return false; + } + if (fInfo.fAlphaType != alphaType) { + fInfo.fAlphaType = alphaType; + if (fPixelRef) { + fPixelRef->changeAlphaType(alphaType); } } - - fConfig = SkToU8(c); - fWidth = width; - fHeight = height; - fRowBytes = SkToU32(rowBytes); - - fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); - - SkDEBUGCODE(this->validate();) - return; - - // if we got here, we had an error, so we reset the bitmap to empty -err: - this->reset(); + return true; } void SkBitmap::updatePixelsFromRef() const { @@ -304,28 +309,85 @@ 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; } } } -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; +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; +} + +SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { +#ifdef SK_DEBUG + if (pr) { + SkImageInfo info; + if (this->asImageInfo(&info)) { + const SkImageInfo& prInfo = pr->info(); + SkASSERT(info.fWidth <= prInfo.fWidth); + SkASSERT(info.fHeight <= prInfo.fHeight); + SkASSERT(info.fColorType == prInfo.fColorType); + switch (prInfo.fAlphaType) { + case kIgnore_SkAlphaType: + SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType); + break; + case kOpaque_SkAlphaType: + case kPremul_SkAlphaType: + SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || + info.fAlphaType == kPremul_SkAlphaType); + break; + case kUnpremul_SkAlphaType: + SkASSERT(info.fAlphaType == kOpaque_SkAlphaType || + info.fAlphaType == kUnpremul_SkAlphaType); + break; + } + } + } +#endif + + 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) { if (fPixelRef != pr) { this->freePixels(); SkASSERT(NULL == fPixelRef); @@ -333,7 +395,6 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { SkSafeRef(pr); fPixelRef = pr; } - fPixelRefOffset = offset; this->updatePixelsFromRef(); } @@ -342,7 +403,7 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { } void SkBitmap::lockPixels() const { - if (NULL != fPixelRef && 1 == ++fPixelLockCount) { + if (NULL != fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) { fPixelRef->lockPixels(); this->updatePixelsFromRef(); } @@ -352,7 +413,7 @@ void SkBitmap::lockPixels() const { void SkBitmap::unlockPixels() const { SkASSERT(NULL == fPixelRef || fPixelLockCount > 0); - if (NULL != fPixelRef && 0 == --fPixelLockCount) { + if (NULL != fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) { fPixelRef->unlockPixels(); this->updatePixelsFromRef(); } @@ -365,14 +426,24 @@ bool SkBitmap::lockPixelsAreWritable() const { void SkBitmap::setPixels(void* p, SkColorTable* ctable) { if (NULL == p) { - this->setPixelRef(NULL, 0); + this->setPixelRef(NULL); return; } - Sk64 size = this->getSize64(); - SkASSERT(!size.isNeg() && size.is32()); + SkImageInfo info; + if (!this->asImageInfo(&info)) { + this->setPixelRef(NULL); + return; + } + + SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable); + if (NULL == pr) { + this->setPixelRef(NULL); + return; + } + + this->setPixelRef(pr)->unref(); - this->setPixelRef(new SkMallocPixelRef(p, size.get32(), ctable, false))->unref(); // since we're already allocated, we lockPixels right away this->lockPixels(); SkDEBUGCODE(this->validate();) @@ -387,25 +458,83 @@ bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) { return allocator->allocPixelRef(this, ctable); } +/////////////////////////////////////////////////////////////////////////////// + +bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, + SkColorTable* ctable) { + if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) { + return reset_return_false(this); + } + if (!this->setConfig(info)) { + return reset_return_false(this); + } + + SkMallocPixelRef::PRFactory defaultFactory; + if (NULL == factory) { + factory = &defaultFactory; + } + + SkPixelRef* pr = factory->create(info, 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& info, void* pixels, size_t rb, + void (*releaseProc)(void* addr, void* context), + void* context) { + if (!this->setConfig(info, rb)) { + this->reset(); + return false; + } + + SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels, + releaseProc, context); + if (!pr) { + this->reset(); + return false; + } + + this->setPixelRef(pr)->unref(); + return true; +} + +bool SkBitmap::allocConfigPixels(Config config, int width, int height, + bool isOpaque) { + SkColorType ct; + if (!config_to_colorType(config, &ct)) { + return false; + } + + SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType; + return this->allocPixels(SkImageInfo::Make(width, height, ct, at)); +} + +/////////////////////////////////////////////////////////////////////////////// + void SkBitmap::freePixels() { // if we're gonna free the pixels, we certainly need to free the mipmap this->freeMipMap(); - if (fColorTable) { - fColorTable->unref(); - fColorTable = NULL; - } - if (NULL != fPixelRef) { if (fPixelLockCount > 0) { fPixelRef->unlockPixels(); } fPixelRef->unref(); fPixelRef = NULL; - fPixelRefOffset = 0; + fPixelRefOrigin.setZero(); } fPixelLockCount = 0; fPixels = NULL; + fColorTable = NULL; } void SkBitmap::freeMipMap() { @@ -426,7 +555,7 @@ void SkBitmap::notifyPixelsChanged() const { } } -SkGpuTexture* SkBitmap::getTexture() const { +GrTexture* SkBitmap::getTexture() const { return fPixelRef ? fPixelRef->getTexture() : NULL; } @@ -437,17 +566,19 @@ SkGpuTexture* SkBitmap::getTexture() const { */ bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, SkColorTable* ctable) { - Sk64 size = dst->getSize64(); - if (size.isNeg() || !size.is32()) { + SkImageInfo info; + if (!dst->asImageInfo(&info)) { +// SkDebugf("unsupported config for info %d\n", dst->config()); return false; } - void* addr = sk_malloc_flags(size.get32(), 0); // returns NULL on failure - if (NULL == addr) { + SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), + ctable); + if (NULL == pr) { return false; } - dst->setPixelRef(new SkMallocPixelRef(addr, size.get32(), ctable))->unref(); + dst->setPixelRef(pr)->unref(); // since we're already allocated, we lockPixels right away dst->lockPixels(); return true; @@ -455,17 +586,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(getConfig(), fWidth): 0); -} - -Sk64 SkBitmap::getSafeSize64() const { - return ComputeSafeSize64(getConfig(), fWidth, fHeight, fRowBytes); -} - bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, size_t dstRowBytes, bool preserveDstPad) const { @@ -473,13 +593,13 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, dstRowBytes = fRowBytes; } - if (getConfig() == kRLE_Index8_Config || - dstRowBytes < ComputeRowBytes(getConfig(), fWidth) || - dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) + if (dstRowBytes < fInfo.minRowBytes() || + dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) { return false; + } if (!preserveDstPad && static_cast(dstRowBytes) == fRowBytes) { - size_t safeSize = getSafeSize(); + size_t safeSize = this->getSafeSize(); if (safeSize > dstSize || safeSize == 0) return false; else { @@ -493,16 +613,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(getConfig(), 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(getConfig(), fWidth); + size_t rowBytes = fInfo.minRowBytes(); SkAutoLockPixels lock(*this); const uint8_t* srcP = reinterpret_cast(getPixels()); uint8_t* dstP = reinterpret_cast(dst); - for (uint32_t row = 0; row < fHeight; + for (int row = 0; row < fInfo.fHeight; row++, srcP += fRowBytes, dstP += dstRowBytes) { memcpy(dstP, srcP, rowBytes); } @@ -527,51 +646,6 @@ void SkBitmap::setImmutable() { } } -bool SkBitmap::isOpaque() const { - switch (fConfig) { - case kNo_Config: - return true; - - case kA1_Config: - case kA8_Config: - case kARGB_4444_Config: - case kARGB_8888_Config: - return (fFlags & kImageIsOpaque_Flag) != 0; - - case kIndex8_Config: - case kRLE_Index8_Config: { - uint32_t flags = 0; - - this->lockPixels(); - // if lockPixels failed, we may not have a ctable ptr - if (fColorTable) { - flags = fColorTable->getFlags(); - } - this->unlockPixels(); - - return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0; - } - - case kRGB_565_Config: - return true; - - default: - SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); - return false; - } -} - -void SkBitmap::setIsOpaque(bool isOpaque) { - /* we record this regardless of fConfig, though it is ignored in - isOpaque() for configs that can't support per-pixel alpha. - */ - if (isOpaque) { - fFlags |= kImageIsOpaque_Flag; - } else { - fFlags &= ~kImageIsOpaque_Flag; - } -} - bool SkBitmap::isVolatile() const { return (fFlags & kImageIsVolatile_Flag) != 0; } @@ -591,25 +665,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; - case SkBitmap::kA1_Config: - base += x >> 3; - break; - case kRLE_Index8_Config: - SkDEBUGFAIL("Can't return addr for kRLE_Index8_Config"); - base = NULL; - break; default: SkDEBUGFAIL("Can't return addr for config"); base = NULL; @@ -624,15 +692,6 @@ SkColor SkBitmap::getColor(int x, int y) const { SkASSERT((unsigned)y < (unsigned)this->height()); switch (this->config()) { - case SkBitmap::kA1_Config: { - uint8_t* addr = this->getAddr1(x, y); - uint8_t mask = 1 << (7 - (x % 8)); - if (addr[0] & mask) { - return SK_ColorBLACK; - } else { - return 0; - } - } case SkBitmap::kA8_Config: { uint8_t* addr = this->getAddr8(x, y); return SkColorSetA(0, addr[0]); @@ -654,15 +713,8 @@ SkColor SkBitmap::getColor(int x, int y) const { uint32_t* addr = this->getAddr32(x, y); return SkUnPreMultiply::PMColorToColor(addr[0]); } - case kRLE_Index8_Config: { - uint8_t dst; - const SkBitmap::RLEPixels* rle = - (const SkBitmap::RLEPixels*)this->getPixels(); - SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y)); - return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]); - } case kNo_Config: - case kConfigCount: + default: SkASSERT(false); return 0; } @@ -680,9 +732,6 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { const int width = bm.width(); switch (bm.config()) { - case SkBitmap::kA1_Config: { - // TODO - } break; case SkBitmap::kA8_Config: { unsigned a = 0xFF; for (int y = 0; y < height; ++y) { @@ -696,7 +745,6 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { } return true; } break; - case kRLE_Index8_Config: case SkBitmap::kIndex8_Config: { SkAutoLockColors alc(bm); const SkPMColor* table = alc.colors(); @@ -748,12 +796,31 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { - SkDEBUGCODE(this->validate();) +static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { + unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | + (SkR32To4444(r) << SK_R4444_SHIFT) | + (SkG32To4444(g) << SK_G4444_SHIFT) | + (SkB32To4444(b) << SK_B4444_SHIFT); + return SkToU16(pixel); +} - if (0 == fWidth || 0 == fHeight || - kNo_Config == fConfig || kIndex8_Config == fConfig) { - return; +void SkBitmap::internalErase(const SkIRect& area, + U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { +#ifdef SK_DEBUG + SkDEBUGCODE(this->validate();) + SkASSERT(!area.isEmpty()); + { + SkIRect total = { 0, 0, this->width(), this->height() }; + SkASSERT(total.contains(area)); + } +#endif + + switch (fInfo.colorType()) { + case kUnknown_SkColorType: + case kIndex_8_SkColorType: + return; // can't erase + default: + break; } SkAutoLockPixels alp(*this); @@ -762,8 +829,8 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { return; } - int height = fHeight; - const int width = fWidth; + int height = area.height(); + const int width = area.width(); const int rowBytes = fRowBytes; // make rgb premultiplied @@ -773,35 +840,25 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { b = SkAlphaMul(b, a); } - switch (fConfig) { - case kA1_Config: { - uint8_t* p = (uint8_t*)fPixels; - const int count = (width + 7) >> 3; - a = (a >> 7) ? 0xFF : 0; - SkASSERT(count <= rowBytes); - while (--height >= 0) { - memset(p, a, count); - p += rowBytes; - } - break; - } - case kA8_Config: { - uint8_t* p = (uint8_t*)fPixels; + switch (this->colorType()) { + case kAlpha_8_SkColorType: { + uint8_t* p = this->getAddr8(area.fLeft, area.fTop); while (--height >= 0) { memset(p, a, width); p += rowBytes; } break; } - case kARGB_4444_Config: - case kRGB_565_Config: { - uint16_t* p = (uint16_t*)fPixels; + 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) { - v = SkPackARGB4444(a >> 4, r >> 4, g >> 4, b >> 4); - } else { // kRGB_565_Config - v = SkPackRGB16(r >> (8 - SK_R16_BITS), g >> (8 - SK_G16_BITS), + if (kARGB_4444_SkColorType == this->colorType()) { + v = pack_8888_to_4444(a, r, g, b); + } else { + v = SkPackRGB16(r >> (8 - SK_R16_BITS), + g >> (8 - SK_G16_BITS), b >> (8 - SK_B16_BITS)); } while (--height >= 0) { @@ -810,8 +867,10 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { } break; } - case kARGB_8888_Config: { - uint32_t* p = (uint32_t*)fPixels; + case kPMColor_SkColorType: { + // what to do about BGRA or RGBA (which ever is != PMColor ? + // for now we don't support them. + uint32_t* p = this->getAddr32(area.fLeft, area.fTop); uint32_t v = SkPackARGB32(a, r, g, b); while (--height >= 0) { @@ -820,90 +879,31 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { } break; } + default: + return; // no change, so don't call notifyPixelsChanged() } this->notifyPixelsChanged(); } -////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////// - -#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 getSubOffset(const SkBitmap& bm, int x, int y) { - switch (bm.getConfig()) { - 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: - case SkBitmap::kA1_Config: - default: - return SUB_OFFSET_FAILURE; +void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { + SkIRect area = { 0, 0, this->width(), this->height() }; + if (!area.isEmpty()) { + this->internalErase(area, a, r, g, b); } - 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. - */ -static bool getUpperLeftFromOffset(const SkBitmap& bm, int32_t* x, int32_t* y) { - SkASSERT(x != NULL && y != NULL); - const size_t offset = bm.pixelRefOffset(); - if (0 == offset) { - *x = *y = 0; - return true; +void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { + SkIRect area = { 0, 0, this->width(), this->height() }; + if (area.intersect(rect)) { + this->internalErase(area, SkColorGetA(c), SkColorGetR(c), + SkColorGetG(c), SkColorGetB(c)); } - // Use integer division to find the correct y position. - *y = SkToS32(offset / bm.rowBytes()); - // The remainder will be the x position, after we reverse getSubOffset. - *x = SkToS32(offset % bm.rowBytes()); - switch (bm.getConfig()) { - 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. - case SkBitmap::kA1_Config: - // Fall through. - default: - return false; - } - return true; } +////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////// + bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { SkDEBUGCODE(this->validate();) @@ -922,9 +922,9 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); if (pixelRef != NULL) { SkBitmap dst; - dst.setConfig(this->config(), subset.width(), subset.height()); + dst.setConfig(this->config(), subset.width(), subset.height(), 0, + this->alphaType()); dst.setIsVolatile(this->isVolatile()); - dst.setIsOpaque(this->isOpaque()); dst.setPixelRef(pixelRef)->unref(); SkDEBUGCODE(dst.validate()); result->swap(dst); @@ -932,52 +932,22 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { } } - if (kRLE_Index8_Config == fConfig) { - SkAutoLockPixels alp(*this); - // don't call readyToDraw(), since we can operate w/o a colortable - // at this stage - if (this->getPixels() == NULL) { - return false; - } - SkBitmap bm; - - bm.setConfig(kIndex8_Config, r.width(), r.height()); - bm.allocPixels(this->getColorTable()); - if (NULL == bm.getPixels()) { - return false; - } - - const RLEPixels* rle = (const RLEPixels*)this->getPixels(); - uint8_t* dst = bm.getAddr8(0, 0); - const int width = bm.width(); - const size_t rowBytes = bm.rowBytes(); - - for (int y = r.fTop; y < r.fBottom; y++) { - SkPackBits::Unpack8(dst, r.fLeft, width, rle->packedAtY(y)); - dst += rowBytes; - } - result->swap(bm); - return true; - } - // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have // exited above. SkASSERT(static_cast(r.fLeft) < static_cast(this->width())); SkASSERT(static_cast(r.fTop) < static_cast(this->height())); - size_t offset = getSubOffset(*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()); + dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), + this->alphaType()); dst.setIsVolatile(this->isVolatile()); - dst.setIsOpaque(this->isOpaque()); 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();) @@ -992,32 +962,26 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { #include "SkPaint.h" bool SkBitmap::canCopyTo(Config dstConfig) const { - if (this->getConfig() == kNo_Config) { + if (this->config() == kNo_Config) { return false; } bool sameConfigs = (this->config() == dstConfig); switch (dstConfig) { case kA8_Config: - case kARGB_4444_Config: case kRGB_565_Config: case kARGB_8888_Config: break; - case kA1_Config: case kIndex8_Config: if (!sameConfigs) { return false; } break; + case kARGB_4444_Config: + return sameConfigs || kARGB_8888_Config == this->config(); default: return false; } - - // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config - if (this->getConfig() == kA1_Config && !sameConfigs) { - return false; - } - return true; } @@ -1032,25 +996,24 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { if (fPixelRef) { SkIRect subset; - if (getUpperLeftFromOffset(*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()); + subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, + fInfo.width(), fInfo.height()); + 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) { - dst->pixelRef()->fGenerationID = fPixelRef->getGenerationID(); - } - return true; + // did we get lucky and we can just return tmpSrc? + if (tmpSrc.config() == dstConfig && 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; } } @@ -1060,8 +1023,12 @@ 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); + SkBitmap tmpDst; - tmpDst.setConfig(dstConfig, src->width(), src->height()); + tmpDst.setConfig(dstConfig, src->width(), src->height(), 0, + src->alphaType()); // allocate colortable if srcConfig == kIndex8_Config SkColorTable* ctable = (dstConfig == kIndex8_Config) ? @@ -1076,14 +1043,32 @@ 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 (tmpDst.getSize() == src->getSize()) { memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); SkPixelRef* pixelRef = tmpDst.pixelRef(); - if (pixelRef != NULL) { - pixelRef->fGenerationID = this->getGenerationID(); + + // In order to reach this point, we know that the width, config and + // rowbytes of the SkPixelRefs are the same, but it is possible for + // the heights to differ, if this SkBitmap's height is a subset of + // fPixelRef. Only if the SkPixelRefs' heights match are we + // guaranteed that this is an exact copy, meaning we should clone + // the genID. + if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { + // TODO: what to do if the two infos match, BUT + // fPixelRef is premul and pixelRef is opaque? + // skipping assert for now + // https://code.google.com/p/skia/issues/detail?id=2012 +// SkASSERT(pixelRef->info() == fPixelRef->info()); + SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); + SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColorType); + pixelRef->cloneGenID(*fPixelRef); } } else { const char* srcP = reinterpret_cast(src->getPixels()); @@ -1096,11 +1081,23 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { dstP += tmpDst.rowBytes(); } } - } else { - // if the src has alpha, we have to clear the dst first - if (!src->isOpaque()) { - tmpDst.eraseColor(SK_ColorTRANSPARENT); + } else if (SkBitmap::kARGB_4444_Config == dstConfig + && SkBitmap::kARGB_8888_Config == src->config()) { + SkASSERT(src->height() == tmpDst.height()); + SkASSERT(src->width() == tmpDst.width()); + for (int y = 0; y < src->height(); ++y) { + SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); + SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); + DITHER_4444_SCAN(y); + for (int x = 0; x < src->width(); ++x) { + dstRow[x] = SkDitherARGB32To4444(srcRow[x], + DITHER_VALUE(x)); + } } + } else { + // 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); SkCanvas canvas(tmpDst); SkPaint paint; @@ -1109,13 +1106,13 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { canvas.drawBitmap(*src, 0, 0, &paint); } - tmpDst.setIsOpaque(src->isOpaque()); - dst->swap(tmpDst); return true; } bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { + const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig); + if (!this->canCopyTo(dstConfig)) { return false; } @@ -1126,33 +1123,24 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig); if (pixelRef) { uint32_t rowBytes; - if (dstConfig == fConfig) { - pixelRef->fGenerationID = fPixelRef->getGenerationID(); + 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. 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 (!getUpperLeftFromOffset(*this, &x, &y)) { - return false; - } - pixelRefOffset = getSubOffset(*dst, x, y); - if (SUB_OFFSET_FAILURE == pixelRefOffset) { - return false; - } + SkImageInfo info = fInfo; + info.fColorType = dstCT; + if (!dst->setConfig(info, rowBytes)) { + return false; } - dst->setPixelRef(pixelRef, pixelRefOffset)->unref(); + dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); return true; } } @@ -1277,7 +1265,7 @@ void SkBitmap::buildMipMap(bool forceRebuild) { void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); - const SkBitmap::Config config = this->getConfig(); + const SkBitmap::Config config = this->config(); switch (config) { case kARGB_8888_Config: @@ -1416,7 +1404,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, SkASSERT(alpha != NULL); SkASSERT(alphaRowBytes >= src.width()); - SkBitmap::Config config = src.getConfig(); + SkBitmap::Config config = src.config(); int w = src.width(); int h = src.height(); size_t rb = src.rowBytes(); @@ -1468,7 +1456,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, s += rb; alpha += alphaRowBytes; } - ct->unlockColors(false); + ct->unlockColors(); } } else { // src is opaque, so just fill alpha[] with 0xFF memset(alpha, 0xFF, h * alphaRowBytes); @@ -1553,17 +1541,15 @@ enum { SERIALIZE_PIXELTYPE_REF_DATA }; -void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { - buffer.writeInt(fWidth); - buffer.writeInt(fHeight); +void SkBitmap::flatten(SkWriteBuffer& buffer) const { + fInfo.flatten(buffer); buffer.writeInt(fRowBytes); - buffer.writeInt(fConfig); - buffer.writeBool(this->isOpaque()); if (fPixelRef) { if (fPixelRef->getFactory()) { buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); - buffer.writeUInt(SkToU32(fPixelRefOffset)); + buffer.writeInt(fPixelRefOrigin.fX); + buffer.writeInt(fPixelRefOrigin.fY); buffer.writeFlattenable(fPixelRef); return; } @@ -1574,30 +1560,44 @@ void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { } } -void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { +void SkBitmap::unflatten(SkReadBuffer& buffer) { this->reset(); - int width = buffer.readInt(); - int height = buffer.readInt(); - int rowBytes = buffer.readInt(); - int config = buffer.readInt(); + SkImageInfo info; + info.unflatten(buffer); + size_t rowBytes = buffer.readInt(); + buffer.validate((info.width() >= 0) && (info.height() >= 0) && + SkColorTypeIsValid(info.fColorType) && + SkAlphaTypeIsValid(info.fAlphaType) && + validate_alphaType(info.fColorType, info.fAlphaType) && + info.validRowBytes(rowBytes)); - this->setConfig((Config)config, width, height, rowBytes); - this->setIsOpaque(buffer.readBool()); + bool configIsValid = this->setConfig(info, rowBytes); + buffer.validate(configIsValid); int reftype = buffer.readInt(); - switch (reftype) { - case SERIALIZE_PIXELTYPE_REF_DATA: { - size_t offset = buffer.readUInt(); - SkPixelRef* pr = buffer.readFlattenableT(); - SkSafeUnref(this->setPixelRef(pr, offset)); - break; + if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) || + (SERIALIZE_PIXELTYPE_NONE == reftype))) { + switch (reftype) { + case SERIALIZE_PIXELTYPE_REF_DATA: { + 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())))) { + origin.setZero(); + } + SkSafeUnref(this->setPixelRef(pr, origin)); + break; + } + case SERIALIZE_PIXELTYPE_NONE: + break; + default: + SkDEBUGFAIL("unrecognized pixeltype in serialized data"); + sk_throw(); } - case SERIALIZE_PIXELTYPE_NONE: - break; - default: - SkDEBUGFAIL("unrecognized pixeltype in serialized data"); - sk_throw(); } } @@ -1605,8 +1605,7 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { SkBitmap::RLEPixels::RLEPixels(int width, int height) { fHeight = height; - fYPtrs = (uint8_t**)sk_malloc_throw(height * sizeof(uint8_t*)); - sk_bzero(fYPtrs, height * sizeof(uint8_t*)); + fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*)); } SkBitmap::RLEPixels::~RLEPixels() { @@ -1617,23 +1616,28 @@ SkBitmap::RLEPixels::~RLEPixels() { #ifdef SK_DEBUG void SkBitmap::validate() const { - SkASSERT(fConfig < kConfigCount); - SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); - SkASSERT(fFlags <= (kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag)); - 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); - } - } + fInfo.validate(); + 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); + + 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 @@ -1641,7 +1645,7 @@ void SkBitmap::validate() const { void SkBitmap::toString(SkString* str) const { static const char* gConfigNames[kConfigCount] = { - "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888", "RLE" + "NONE", "A8", "INDEX8", "565", "4444", "8888" }; str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), @@ -1676,3 +1680,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/gfx/skia/trunk/src/core/SkBitmapDevice.cpp b/gfx/skia/trunk/src/core/SkBitmapDevice.cpp new file mode 100644 index 000000000000..9dde6e172ec1 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapDevice.cpp @@ -0,0 +1,410 @@ +/* + * 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 "SkBitmapDevice.h" +#include "SkConfig8888.h" +#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()); +} + +SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties) + : SkBaseDevice(deviceProperties) + , fBitmap(bitmap) { +} + +void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) { + fBitmap.setConfig(config, width, height, 0, isOpaque ? + kOpaque_SkAlphaType : kPremul_SkAlphaType); + + if (SkBitmap::kNo_Config != config) { + if (!fBitmap.allocPixels()) { + // indicate failure by zeroing our bitmap + fBitmap.setConfig(config, 0, 0, 0, isOpaque ? + kOpaque_SkAlphaType : kPremul_SkAlphaType); + } else if (!isOpaque) { + fBitmap.eraseColor(SK_ColorTRANSPARENT); + } + } +} + +SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) { + this->init(config, width, height, isOpaque); +} + +SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque, + const SkDeviceProperties& deviceProperties) + : SkBaseDevice(deviceProperties) +{ + this->init(config, width, height, isOpaque); +} + +SkBitmapDevice::~SkBitmapDevice() { +} + +void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { + SkASSERT(bm.width() == fBitmap.width()); + SkASSERT(bm.height() == fBitmap.height()); + fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config) + 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; +} + +void SkBitmapDevice::lockPixels() { + if (fBitmap.lockPixelsAreWritable()) { + fBitmap.lockPixels(); + } +} + +void SkBitmapDevice::unlockPixels() { + if (fBitmap.lockPixelsAreWritable()) { + fBitmap.unlockPixels(); + } +} + +void SkBitmapDevice::clear(SkColor color) { + fBitmap.eraseColor(color); +} + +const SkBitmap& SkBitmapDevice::onAccessBitmap() { + return fBitmap; +} + +bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) { + return false; +} + +bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src, + const SkMatrix& ctm, SkBitmap* result, + SkIPoint* offset) { + return false; +} + +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()))); + + SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); + const SkBitmap& src = this->accessBitmap(false); + + SkBitmap subset; + if (!src.extractSubset(&subset, srcRect)) { + 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); + } + SkAutoLockPixels alp(bitmap); + uint32_t* bmpPixels = reinterpret_cast(bitmap.getPixels()); + SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset); + return true; +} + +void SkBitmapDevice::writePixels(const SkBitmap& bitmap, + int x, int y, + SkCanvas::Config8888 config8888) { + if (bitmap.isNull() || bitmap.getTexture()) { + return; + } + 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 + if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(), + spriteRect.height()))) { + return; + } + drawSprite = true; + } + + // 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; + } + } + + 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); +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { + draw.drawPaint(paint); +} + +void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, + const SkPoint pts[], const SkPaint& paint) { + CHECK_FOR_ANNOTATION(paint); + draw.drawPoints(mode, count, pts, paint); +} + +void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { + CHECK_FOR_ANNOTATION(paint); + draw.drawRect(r, paint); +} + +void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { + CHECK_FOR_ANNOTATION(paint); + + SkPath path; + path.addOval(oval); + // call the VIRTUAL version, so any subclasses who do handle drawPath aren't + // required to override drawOval. + this->drawPath(draw, path, paint, NULL, true); +} + +void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) { + CHECK_FOR_ANNOTATION(paint); + +#ifdef SK_IGNORE_BLURRED_RRECT_OPT + SkPath path; + + path.addRRect(rrect); + // call the VIRTUAL version, so any subclasses who do handle drawPath aren't + // required to override drawRRect. + this->drawPath(draw, path, paint, NULL, true); +#else + draw.drawRRect(rrect, paint); +#endif +} + +void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path, + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable) { + CHECK_FOR_ANNOTATION(paint); + draw.drawPath(path, paint, prePathMatrix, pathIsMutable); +} + +void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, + const SkMatrix& matrix, const SkPaint& paint) { + draw.drawBitmap(bitmap, matrix, paint); +} + +void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, + const SkRect* src, const SkRect& dst, + const SkPaint& paint, + SkCanvas::DrawBitmapRectFlags flags) { + SkMatrix matrix; + SkRect bitmapBounds, tmpSrc, tmpDst; + SkBitmap tmpBitmap; + + bitmapBounds.isetWH(bitmap.width(), bitmap.height()); + + // Compute matrix from the two rectangles + if (src) { + tmpSrc = *src; + } else { + tmpSrc = bitmapBounds; + } + matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); + + const SkRect* dstPtr = &dst; + const SkBitmap* bitmapPtr = &bitmap; + + // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if + // needed (if the src was clipped). No check needed if src==null. + if (src) { + if (!bitmapBounds.contains(*src)) { + if (!tmpSrc.intersect(bitmapBounds)) { + return; // nothing to draw + } + // recompute dst, based on the smaller tmpSrc + matrix.mapRect(&tmpDst, tmpSrc); + dstPtr = &tmpDst; + } + + // since we may need to clamp to the borders of the src rect within + // the bitmap, we extract a subset. + SkIRect srcIR; + tmpSrc.roundOut(&srcIR); + if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { + return; + } + bitmapPtr = &tmpBitmap; + + // Since we did an extract, we need to adjust the matrix accordingly + SkScalar dx = 0, dy = 0; + if (srcIR.fLeft > 0) { + dx = SkIntToScalar(srcIR.fLeft); + } + if (srcIR.fTop > 0) { + dy = SkIntToScalar(srcIR.fTop); + } + if (dx || dy) { + matrix.preTranslate(dx, dy); + } + + SkRect extractedBitmapBounds; + extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height()); + if (extractedBitmapBounds == tmpSrc) { + // no fractional part in src, we can just call drawBitmap + goto USE_DRAWBITMAP; + } + } else { + USE_DRAWBITMAP: + // We can go faster by just calling drawBitmap, which will concat the + // matrix with the CTM, and try to call drawSprite if it can. If not, + // it will make a shader and call drawRect, as we do below. + this->drawBitmap(draw, *bitmapPtr, matrix, paint); + return; + } + + // construct a shader, so we can call drawRect with the dst + SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr, + SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode); + if (NULL == s) { + return; + } + s->setLocalMatrix(matrix); + + SkPaint paintWithShader(paint); + paintWithShader.setStyle(SkPaint::kFill_Style); + paintWithShader.setShader(s)->unref(); + + // Call ourself, in case the subclass wanted to share this setup code + // but handle the drawRect code themselves. + this->drawRect(draw, *dstPtr, paintWithShader); +} + +void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, + int x, int y, const SkPaint& paint) { + draw.drawSprite(bitmap, x, y, paint); +} + +void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint& paint) { + draw.drawText((const char*)text, len, x, y, paint); +} + +void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, + const SkScalar xpos[], SkScalar y, + int scalarsPerPos, const SkPaint& paint) { + draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint); +} + +void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text, + size_t len, const SkPath& path, + const SkMatrix* matrix, + const SkPaint& paint) { + draw.drawTextOnPath((const char*)text, len, path, matrix, paint); +} + +void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, + int vertexCount, + const SkPoint verts[], const SkPoint textures[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint) { + draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode, + indices, indexCount, paint); +} + +void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, + int x, int y, const SkPaint& paint) { + const SkBitmap& src = device->accessBitmap(false); + draw.drawSprite(src, x, y, paint); +} + +SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) { + return SkSurface::NewRaster(info); +} + +/////////////////////////////////////////////////////////////////////////////// + +bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { + if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { + // we're cool with the paint as is + return false; + } + + if (SkBitmap::kARGB_8888_Config != fBitmap.config() || + paint.getRasterizer() || + paint.getPathEffect() || + paint.isFakeBoldText() || + paint.getStyle() != SkPaint::kFill_Style || + !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { + // turn off lcd + flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag; + flags->fHinting = paint.getHinting(); + return true; + } + // we're cool with the paint as is + return false; +} diff --git a/gfx/skia/trunk/src/core/SkBitmapFilter.cpp b/gfx/skia/trunk/src/core/SkBitmapFilter.cpp new file mode 100644 index 000000000000..7443cb61b7c9 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapFilter.cpp @@ -0,0 +1,148 @@ +/* + * 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 "SkErrorInternals.h" +#include "SkConvolver.h" +#include "SkBitmapProcState.h" +#include "SkBitmap.h" +#include "SkColor.h" +#include "SkColorPriv.h" +#include "SkConvolver.h" +#include "SkUnPreMultiply.h" +#include "SkShader.h" +#include "SkRTConf.h" +#include "SkMath.h" + +// These are the per-scanline callbacks that are used when we must resort to +// resampling an image as it is blitted. Typically these are used only when +// the image is rotated or has some other complex transformation applied. +// Scaled images will usually be rescaled directly before rasterization. + +namespace { + +template +void highQualityFilter(ColorPacker pack, const SkBitmapProcState& s, int x, int y, Color* SK_RESTRICT colors, int count) { + const int maxX = s.fBitmap->width(); + const int maxY = s.fBitmap->height(); + + while (count-- > 0) { + SkPoint srcPt; + s.fInvProc(s.fInvMatrix, x + 0.5f, + y + 0.5f, &srcPt); + srcPt.fX -= SK_ScalarHalf; + srcPt.fY -= SK_ScalarHalf; + + SkScalar weight = 0; + SkScalar fr = 0, fg = 0, fb = 0, fa = 0; + + int y0 = SkClampMax(SkScalarCeilToInt(srcPt.fY-s.getBitmapFilter()->width()), maxY); + int y1 = SkClampMax(SkScalarFloorToInt(srcPt.fY+s.getBitmapFilter()->width()+1), maxY); + int x0 = SkClampMax(SkScalarCeilToInt(srcPt.fX-s.getBitmapFilter()->width()), maxX); + int x1 = SkClampMax(SkScalarFloorToInt(srcPt.fX+s.getBitmapFilter()->width())+1, maxX); + + for (int srcY = y0; srcY < y1; srcY++) { + SkScalar yWeight = s.getBitmapFilter()->lookupScalar((srcPt.fY - srcY)); + + for (int srcX = x0; srcX < x1 ; srcX++) { + SkScalar xWeight = s.getBitmapFilter()->lookupScalar((srcPt.fX - srcX)); + + SkScalar combined_weight = SkScalarMul(xWeight, yWeight); + + SkPMColor c = *s.fBitmap->getAddr32(srcX, srcY); + fr += combined_weight * SkGetPackedR32(c); + fg += combined_weight * SkGetPackedG32(c); + fb += combined_weight * SkGetPackedB32(c); + fa += combined_weight * SkGetPackedA32(c); + weight += combined_weight; + } + } + + fr = SkScalarDiv(fr, weight); + fg = SkScalarDiv(fg, weight); + fb = SkScalarDiv(fb, weight); + fa = SkScalarDiv(fa, weight); + + int a = SkClampMax(SkScalarRoundToInt(fa), 255); + int r = SkClampMax(SkScalarRoundToInt(fr), a); + int g = SkClampMax(SkScalarRoundToInt(fg), a); + int b = SkClampMax(SkScalarRoundToInt(fb), a); + + *colors++ = pack(a, r, g, b); + + x++; + } +} + +uint16_t PackTo565(int /*a*/, int r, int g, int b) { + return SkPack888ToRGB16(r, g, b); +} + +} // namespace + +void highQualityFilter32(const SkBitmapProcState& s, int x, int y, SkPMColor* SK_RESTRICT colors, int count) { + highQualityFilter(&SkPackARGB32, s, x, y, colors, count); +} + +void highQualityFilter16(const SkBitmapProcState& s, int x, int y, uint16_t* SK_RESTRICT colors, int count) { + highQualityFilter(&PackTo565, s, x, y, colors, count); +} + + +SK_CONF_DECLARE(const char *, c_bitmapFilter, "bitmap.filter", "mitchell", "Which scanline bitmap filter to use [mitchell, lanczos, hamming, gaussian, triangle, box]"); + +SkBitmapFilter *SkBitmapFilter::Allocate() { + if (!strcmp(c_bitmapFilter, "mitchell")) { + return SkNEW_ARGS(SkMitchellFilter,(1.f/3.f,1.f/3.f)); + } else if (!strcmp(c_bitmapFilter, "lanczos")) { + return SkNEW(SkLanczosFilter); + } else if (!strcmp(c_bitmapFilter, "hamming")) { + return SkNEW(SkHammingFilter); + } else if (!strcmp(c_bitmapFilter, "gaussian")) { + return SkNEW_ARGS(SkGaussianFilter,(2)); + } else if (!strcmp(c_bitmapFilter, "triangle")) { + return SkNEW(SkTriangleFilter); + } else if (!strcmp(c_bitmapFilter, "box")) { + return SkNEW(SkBoxFilter); + } else { + SkDEBUGFAIL("Unknown filter type"); + } + + return NULL; +} + +bool SkBitmapProcState::setBitmapFilterProcs() { + if (fFilterLevel != SkPaint::kHigh_FilterLevel) { + return false; + } + + if (fAlphaScale != 256) { + return false; + } + + // TODO: consider supporting other configs (e.g. 565, A8) + if (fBitmap->config() != SkBitmap::kARGB_8888_Config) { + return false; + } + + // TODO: consider supporting repeat and mirror + if (SkShader::kClamp_TileMode != fTileModeX || SkShader::kClamp_TileMode != fTileModeY) { + return false; + } + + // TODO: is this right? do we want fBitmapFilter allocated even if we can't set shader procs? + if (fInvType & (SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask)) { + fBitmapFilter = SkBitmapFilter::Allocate(); + } + + if (fInvType & SkMatrix::kScale_Mask) { + fShaderProc32 = highQualityFilter32; + fShaderProc16 = highQualityFilter16; + return true; + } else { + return false; + } +} diff --git a/gfx/skia/trunk/src/core/SkBitmapFilter.h b/gfx/skia/trunk/src/core/SkBitmapFilter.h new file mode 100644 index 000000000000..8ef0f6e1ded9 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapFilter.h @@ -0,0 +1,175 @@ + +/* + * 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 SkBitmapFilter_DEFINED +#define SkBitmapFilter_DEFINED + +#include "SkMath.h" + +// size of the precomputed bitmap filter tables for high quality filtering. +// Used to precompute the shape of the filter kernel. +// Table size chosen from experiments to see where I could start to see a difference. + +#define SKBITMAP_FILTER_TABLE_SIZE 128 + +class SkBitmapFilter { + public: + SkBitmapFilter(float width) + : fWidth(width), fInvWidth(1.f/width) { + fPrecomputed = false; + fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); + } + + SkFixed lookup(float x) const { + if (!fPrecomputed) { + precomputeTable(); + } + int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); + SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); + return fFilterTable[filter_idx]; + } + + SkScalar lookupScalar(float x) const { + if (!fPrecomputed) { + precomputeTable(); + } + int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); + SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); + return fFilterTableScalar[filter_idx]; + } + + float width() const { return fWidth; } + float invWidth() const { return fInvWidth; } + virtual float evaluate(float x) const = 0; + virtual ~SkBitmapFilter() {} + + static SkBitmapFilter* Allocate(); + protected: + float fWidth; + float fInvWidth; + + float fLookupMultiplier; + + mutable bool fPrecomputed; + mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; + mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; + private: + void precomputeTable() const { + fPrecomputed = true; + SkFixed *ftp = fFilterTable; + SkScalar *ftpScalar = fFilterTableScalar; + for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) { + float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_SIZE; + float filter_value = evaluate(fx); + *ftpScalar++ = filter_value; + *ftp++ = SkFloatToFixed(filter_value); + } + } +}; + +class SkMitchellFilter: public SkBitmapFilter { + public: + SkMitchellFilter(float b, float c, float width=2.0f) + : SkBitmapFilter(width), B(b), C(c) { + } + + virtual float evaluate(float x) const SK_OVERRIDE { + x = fabsf(x); + if (x > 2.f) { + return 0; + } else if (x > 1.f) { + return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x + + (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f); + } else { + return ((12 - 9*B - 6*C) * x*x*x + + (-18 + 12*B + 6*C) * x*x + + (6 - 2*B)) * (1.f/6.f); + } + } + protected: + float B, C; +}; + +class SkGaussianFilter: public SkBitmapFilter { + public: + SkGaussianFilter(float a, float width=2.0f) + : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) { + } + + virtual float evaluate(float x) const SK_OVERRIDE { + return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth)); + } + protected: + float alpha, expWidth; +}; + +class SkTriangleFilter: public SkBitmapFilter { + public: + SkTriangleFilter(float width=1) + : SkBitmapFilter(width) { + } + + virtual float evaluate(float x) const SK_OVERRIDE { + return SkTMax(0.f, fWidth - fabsf(x)); + } + protected: +}; + +class SkBoxFilter: public SkBitmapFilter { + public: + SkBoxFilter(float width=0.5f) + : SkBitmapFilter(width) { + } + + virtual float evaluate(float x) const SK_OVERRIDE { + return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f; + } + protected: +}; + +class SkHammingFilter: public SkBitmapFilter { +public: + SkHammingFilter(float width=1.f) + : SkBitmapFilter(width) { + } + virtual float evaluate(float x) const SK_OVERRIDE { + if (x <= -fWidth || x >= fWidth) { + return 0.0f; // Outside of the window. + } + if (x > -FLT_EPSILON && x < FLT_EPSILON) { + return 1.0f; // Special case the sinc discontinuity at the origin. + } + const float xpi = x * static_cast(SK_ScalarPI); + + return ((sk_float_sin(xpi) / xpi) * // sinc(x) + (0.54f + 0.46f * sk_float_cos(xpi / fWidth))); // hamming(x) + } +}; + +class SkLanczosFilter: public SkBitmapFilter { + public: + SkLanczosFilter(float width=3.f) + : SkBitmapFilter(width) { + } + + virtual float evaluate(float x) const SK_OVERRIDE { + if (x <= -fWidth || x >= fWidth) { + return 0.0f; // Outside of the window. + } + if (x > -FLT_EPSILON && x < FLT_EPSILON) { + return 1.0f; // Special case the discontinuity at the origin. + } + float xpi = x * static_cast(SK_ScalarPI); + return (sk_float_sin(xpi) / xpi) * // sinc(x) + sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth) + } +}; + + +#endif diff --git a/gfx/skia/src/core/SkBitmapHeap.cpp b/gfx/skia/trunk/src/core/SkBitmapHeap.cpp similarity index 92% rename from gfx/skia/src/core/SkBitmapHeap.cpp rename to gfx/skia/trunk/src/core/SkBitmapHeap.cpp index 48194b1eaaeb..da628937e903 100644 --- a/gfx/skia/src/core/SkBitmapHeap.cpp +++ b/gfx/skia/trunk/src/core/SkBitmapHeap.cpp @@ -9,12 +9,10 @@ #include "SkBitmapHeap.h" #include "SkBitmap.h" -#include "SkFlattenableBuffers.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" #include "SkTSearch.h" -SK_DEFINE_INST_COUNT(SkBitmapHeapReader) -SK_DEFINE_INST_COUNT(SkBitmapHeap::ExternalStorage) - SkBitmapHeapEntry::SkBitmapHeapEntry() : fSlot(-1) , fRefCount(0) @@ -38,26 +36,32 @@ void SkBitmapHeapEntry::addReferences(int count) { /////////////////////////////////////////////////////////////////////////////// -int SkBitmapHeap::LookupEntry::Compare(const SkBitmapHeap::LookupEntry *a, - const SkBitmapHeap::LookupEntry *b) { - if (a->fGenerationId < b->fGenerationId) { - return -1; - } else if (a->fGenerationId > b->fGenerationId) { - return 1; - } else if (a->fPixelOffset < b->fPixelOffset) { - return -1; - } else if (a->fPixelOffset > b->fPixelOffset) { - return 1; - } else if (a->fWidth < b->fWidth) { - return -1; - } else if (a->fWidth > b->fWidth) { - return 1; - } else if (a->fHeight < b->fHeight) { - return -1; - } else if (a->fHeight > b->fHeight) { - return 1; +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.fPixelOrigin < b.fPixelOrigin) { + return true; + } else if (a.fPixelOrigin > b.fPixelOrigin) { + return false; + } else if (a.fWidth < b.fWidth) { + return true; + } else if (a.fWidth > b.fWidth) { + return false; + } else if (a.fHeight < b.fHeight) { + return true; } - return 0; + return false; } /////////////////////////////////////////////////////////////////////////////// @@ -231,9 +235,10 @@ size_t SkBitmapHeap::freeMemoryIfPossible(size_t bytesToFree) { } int SkBitmapHeap::findInLookupTable(const LookupEntry& indexEntry, SkBitmapHeapEntry** entry) { - int index = SkTSearch((const LookupEntry**)fLookupTable.begin(), + int index = SkTSearch( + (const LookupEntry**)fLookupTable.begin(), fLookupTable.count(), - &indexEntry, sizeof(void*), LookupEntry::Compare); + &indexEntry, sizeof(void*)); if (index < 0) { // insert ourselves into the bitmapIndex @@ -260,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.getConfig())) { + } else if (!originalBitmap.deepCopyTo(&copiedBitmap, originalBitmap.config())) { return false; } copiedBitmap.setImmutable(); diff --git a/gfx/skia/src/core/SkBitmapHeap.h b/gfx/skia/trunk/src/core/SkBitmapHeap.h similarity index 97% rename from gfx/skia/src/core/SkBitmapHeap.h rename to gfx/skia/trunk/src/core/SkBitmapHeap.h index be99e191a427..467a21699757 100644 --- a/gfx/skia/src/core/SkBitmapHeap.h +++ b/gfx/skia/trunk/src/core/SkBitmapHeap.h @@ -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; @@ -238,9 +238,9 @@ private: uint32_t fStorageSlot; // slot of corresponding bitmap in fStorage. /** - * Compare two LookupEntry pointers, returning -1, 0, 1 for sorting. + * Compare two LookupEntry pointers for sorting and searching. */ - static int Compare(const LookupEntry* a, const LookupEntry* b); + static bool Less(const LookupEntry& a, const LookupEntry& b); }; /** diff --git a/gfx/skia/src/core/SkBitmapProcShader.cpp b/gfx/skia/trunk/src/core/SkBitmapProcShader.cpp similarity index 71% rename from gfx/skia/src/core/SkBitmapProcShader.cpp rename to gfx/skia/trunk/src/core/SkBitmapProcShader.cpp index 96cfea6749b7..d7c7269c894c 100644 --- a/gfx/skia/src/core/SkBitmapProcShader.cpp +++ b/gfx/skia/trunk/src/core/SkBitmapProcShader.cpp @@ -5,10 +5,17 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#include "SkBitmapProcShader.h" #include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" #include "SkPixelRef.h" +#include "SkErrorInternals.h" +#include "SkBitmapProcShader.h" + +#if SK_SUPPORT_GPU +#include "effects/GrSimpleTextureEffect.h" +#include "effects/GrBicubicEffect.h" +#endif bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) { switch (bm.config()) { @@ -32,7 +39,7 @@ SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, fFlags = 0; // computed in setContext } -SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer) +SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer) : INHERITED(buffer) { buffer.readBitmap(&fRawBitmap); fRawBitmap.setImmutable(); @@ -57,7 +64,7 @@ SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, return kDefault_BitmapType; } -void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const { +void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); buffer.writeBitmap(fRawBitmap); @@ -74,24 +81,37 @@ bool SkBitmapProcShader::isOpaque() const { return fRawBitmap.isOpaque(); } +static bool valid_for_drawing(const SkBitmap& bm) { + if (0 == bm.width() || 0 == bm.height()) { + return false; // nothing to draw + } + if (NULL == bm.pixelRef()) { + return false; // no pixels to read + } + if (SkBitmap::kIndex8_Config == bm.config()) { + // ugh, I have to lock-pixels to inspect the colortable + SkAutoLockPixels alp(bm); + if (!bm.getColorTable()) { + return false; + } + } + return true; +} + bool SkBitmapProcShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { + if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) { + return false; + } + // do this first, so we have a correct inverse matrix if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } fState.fOrigBitmap = fRawBitmap; - fState.fOrigBitmap.lockPixels(); - if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) { - fState.fOrigBitmap.unlockPixels(); - this->INHERITED::endContext(); - return false; - } - if (!fState.chooseProcs(this->getTotalInverse(), paint)) { - fState.fOrigBitmap.unlockPixels(); this->INHERITED::endContext(); return false; } @@ -141,7 +161,7 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device, } void SkBitmapProcShader::endContext() { - fState.fOrigBitmap.unlockPixels(); + fState.endContext(); this->INHERITED::endContext(); } @@ -335,32 +355,91 @@ void SkBitmapProcShader::toString(SkString* str) const { #include "effects/GrSimpleTextureEffect.h" #include "SkGr.h" +// Note that this will return -1 if either matrix is perspective. +static SkScalar get_combined_min_stretch(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) { + if (localMatrix.isIdentity()) { + return viewMatrix.getMinStretch(); + } else { + SkMatrix combined; + combined.setConcat(viewMatrix, localMatrix); + return combined.getMinStretch(); + } +} + GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const { SkMatrix matrix; matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); - if (this->hasLocalMatrix()) { - SkMatrix inverse; - if (!this->getLocalMatrix().invert(&inverse)) { - return NULL; - } - matrix.preConcat(inverse); + SkMatrix lmInverse; + if (!this->getLocalMatrix().invert(&lmInverse)) { + return NULL; } + matrix.preConcat(lmInverse); + SkShader::TileMode tm[] = { (TileMode)fState.fTileModeX, (TileMode)fState.fTileModeY, }; - // Must set wrap and filter on the sampler before requesting a texture. - GrTextureParams params(tm, paint.isFilterBitmap()); + // 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. + SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel(); + GrTextureParams::FilterMode textureFilterMode; + switch(paintFilterLevel) { + case SkPaint::kNone_FilterLevel: + textureFilterMode = GrTextureParams::kNone_FilterMode; + break; + case SkPaint::kLow_FilterLevel: + textureFilterMode = GrTextureParams::kBilerp_FilterMode; + break; + case SkPaint::kMedium_FilterLevel: + if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) < + SK_Scalar1) { + textureFilterMode = GrTextureParams::kMipMap_FilterMode; + } else { + // Don't trigger MIP level generation unnecessarily. + textureFilterMode = GrTextureParams::kBilerp_FilterMode; + } + break; + case SkPaint::kHigh_FilterLevel: + // Minification can look bad with bicubic filtering. + if (get_combined_min_stretch(context->getMatrix(), this->getLocalMatrix()) >= + 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; + textureFilterMode = GrTextureParams::kMipMap_FilterMode; + } + break; + default: + SkErrorInternals::SetError( kInvalidPaint_SkError, + "Sorry, I don't understand the filtering " + "mode you asked for. Falling back to " + "MIPMaps."); + textureFilterMode = GrTextureParams::kMipMap_FilterMode; + break; + + } + GrTextureParams params(tm, textureFilterMode); GrTexture* texture = GrLockAndRefCachedBitmapTexture(context, fRawBitmap, ¶ms); if (NULL == texture) { - SkDebugf("Couldn't convert bitmap to texture.\n"); + SkErrorInternals::SetError( kInternalError_SkError, + "Couldn't convert bitmap to texture."); return NULL; } - GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params); + GrEffectRef* effect = NULL; + if (paintFilterLevel == SkPaint::kHigh_FilterLevel) { + effect = GrBicubicEffect::Create(texture, matrix, tm); + } else { + effect = GrSimpleTextureEffect::Create(texture, matrix, params); + } GrUnlockAndUnrefCachedBitmapTexture(texture); return effect; } diff --git a/gfx/skia/src/core/SkBitmapProcShader.h b/gfx/skia/trunk/src/core/SkBitmapProcShader.h similarity index 92% rename from gfx/skia/src/core/SkBitmapProcShader.h rename to gfx/skia/trunk/src/core/SkBitmapProcShader.h index 5a599c3b924d..b7e60f1ca107 100644 --- a/gfx/skia/src/core/SkBitmapProcShader.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcShader.h @@ -37,8 +37,8 @@ public: #endif protected: - SkBitmapProcShader(SkFlattenableReadBuffer& ); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + SkBitmapProcShader(SkReadBuffer& ); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; SkBitmap fRawBitmap; // experimental for RLE encoding SkBitmapProcState fState; diff --git a/gfx/skia/trunk/src/core/SkBitmapProcState.cpp b/gfx/skia/trunk/src/core/SkBitmapProcState.cpp new file mode 100644 index 000000000000..cdc582bfeec6 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapProcState.cpp @@ -0,0 +1,1042 @@ + +/* + * 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 "SkBitmapProcState.h" +#include "SkColorPriv.h" +#include "SkFilterProc.h" +#include "SkPaint.h" +#include "SkShader.h" // for tilemodes +#include "SkUtilsArm.h" +#include "SkBitmapScaler.h" +#include "SkMipMap.h" +#include "SkPixelRef.h" +#include "SkScaledImageCache.h" + +#if !SK_ARM_NEON_IS_NONE +// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp +extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[]; +extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[]; +extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*); +extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); +extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int); +extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*); +extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); +extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int); +#endif + +#define NAME_WRAP(x) x +#include "SkBitmapProcState_filter.h" +#include "SkBitmapProcState_procs.h" + +/////////////////////////////////////////////////////////////////////////////// + +// true iff the matrix contains, at most, scale and translate elements +static bool matrix_only_scale_translate(const SkMatrix& m) { + return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask); +} + +/** + * For the purposes of drawing bitmaps, if a matrix is "almost" translate + * go ahead and treat it as if it were, so that subsequent code can go fast. + */ +static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) { + SkASSERT(matrix_only_scale_translate(matrix)); + + if (matrix.getType() & SkMatrix::kScale_Mask) { + SkRect src, dst; + bitmap.getBounds(&src); + + // Can't call mapRect(), since that will fix up inverted rectangles, + // e.g. when scale is negative, and we don't want to return true for + // those. + matrix.mapPoints(SkTCast(&dst), + SkTCast(&src), + 2); + + // Now round all 4 edges to device space, and then compare the device + // width/height to the original. Note: we must map all 4 and subtract + // rather than map the "width" and compare, since we care about the + // phase (in pixel space) that any translate in the matrix might impart. + SkIRect idst; + dst.round(&idst); + return idst.width() == bitmap.width() && idst.height() == bitmap.height(); + } + // if we got here, we're either kTranslate_Mask or identity + return true; +} + +static bool just_trans_general(const SkMatrix& matrix) { + SkASSERT(matrix_only_scale_translate(matrix)); + + if (matrix.getType() & SkMatrix::kScale_Mask) { + const SkScalar tol = SK_Scalar1 / 32768; + + if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) { + return false; + } + if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) { + return false; + } + } + // if we got here, treat us as either kTranslate_Mask or identity + return true; +} + +/////////////////////////////////////////////////////////////////////////////// + +static bool valid_for_filtering(unsigned dimension) { + // for filtering, width and height must fit in 14bits, since we use steal + // 2 bits from each to store our 4bit subpixel data + return (dimension & ~0x3FFF) == 0; +} + +static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) { + SkPoint v1, v2; + + v1.fX = mat.getScaleX(); + v1.fY = mat.getSkewY(); + + v2.fX = mat.getSkewX(); + v2.fY = mat.getScaleY(); + + return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd()); +} + +class AutoScaledCacheUnlocker { +public: + AutoScaledCacheUnlocker(SkScaledImageCache::ID** idPtr) : fIDPtr(idPtr) {} + ~AutoScaledCacheUnlocker() { + if (fIDPtr && *fIDPtr) { + SkScaledImageCache::Unlock(*fIDPtr); + *fIDPtr = NULL; + } + } + + // forgets the ID, so it won't call Unlock + void release() { + fIDPtr = NULL; + } + +private: + SkScaledImageCache::ID** fIDPtr; +}; +#define AutoScaledCacheUnlocker(...) SK_REQUIRE_LOCAL_VAR(AutoScaledCacheUnlocker) + +// TODO -- we may want to pass the clip into this function so we only scale +// the portion of the image that we're going to need. This will complicate +// the interface to the cache, but might be well worth it. + +bool SkBitmapProcState::possiblyScaleImage() { + AutoScaledCacheUnlocker unlocker(&fScaledCacheID); + + SkASSERT(NULL == fBitmap); + SkASSERT(NULL == fScaledCacheID); + + if (fFilterLevel <= SkPaint::kLow_FilterLevel) { + return false; + } + + // Check to see if the transformation matrix is simple, and if we're + // doing high quality scaling. If so, do the bitmap scale here and + // remove the scaling component from the matrix. + + if (SkPaint::kHigh_FilterLevel == fFilterLevel && + fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) && + fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) { + + SkScalar invScaleX = fInvMatrix.getScaleX(); + SkScalar invScaleY = fInvMatrix.getScaleY(); + + fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, + invScaleX, invScaleY, + &fScaledBitmap); + if (fScaledCacheID) { + fScaledBitmap.lockPixels(); + if (!fScaledBitmap.getPixels()) { + fScaledBitmap.unlockPixels(); + // found a purged entry (discardablememory?), release it + SkScaledImageCache::Unlock(fScaledCacheID); + fScaledCacheID = NULL; + // fall through to rebuild + } + } + + if (NULL == fScaledCacheID) { + int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX); + int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY); + + // All the criteria are met; let's make a new bitmap. + + SkConvolutionProcs simd; + sk_bzero(&simd, sizeof(simd)); + this->platformConvolutionProcs(&simd); + + if (!SkBitmapScaler::Resize(&fScaledBitmap, + fOrigBitmap, + SkBitmapScaler::RESIZE_BEST, + dest_width, + dest_height, + simd, + SkScaledImageCache::GetAllocator())) { + // we failed to create fScaledBitmap, so just return and let + // the scanline proc handle it. + return false; + + } + SkASSERT(NULL != fScaledBitmap.getPixels()); + fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, + invScaleX, + invScaleY, + fScaledBitmap); + if (!fScaledCacheID) { + fScaledBitmap.reset(); + return false; + } + SkASSERT(NULL != fScaledBitmap.getPixels()); + } + + SkASSERT(NULL != fScaledBitmap.getPixels()); + fBitmap = &fScaledBitmap; + + // set the inv matrix type to translate-only; + fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(), + fInvMatrix.getTranslateY() / fInvMatrix.getScaleY()); + + // no need for any further filtering; we just did it! + fFilterLevel = SkPaint::kNone_FilterLevel; + unlocker.release(); + return true; + } + + /* + * If High, then our special-case for scale-only did not take, and so we + * have to make a choice: + * 1. fall back on mipmaps + bilerp + * 2. fall back on scanline bicubic filter + * For now, we compute the "scale" value from the matrix, and have a + * threshold to decide when bicubic is better, and when mips are better. + * No doubt a fancier decision tree could be used uere. + * + * If Medium, then we just try to build a mipmap and select a level, + * setting the filter-level to kLow to signal that we just need bilerp + * to process the selected level. + */ + + SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix); + + if (SkPaint::kHigh_FilterLevel == fFilterLevel) { + // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller + // than this, then the mipmaps quality may be greater (certainly faster) + // so we only keep High quality if the scale is greater than this. + // + // Since we're dealing with the inverse, we compare against its inverse. + const SkScalar bicubicLimit = 4.0f; + const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit; + if (scaleSqd < bicubicLimitSqd) { // use bicubic scanline + return false; + } + + // else set the filter-level to Medium, since we're scaling down and + // want to reqeust mipmaps + fFilterLevel = SkPaint::kMedium_FilterLevel; + } + + SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel); + + /** + * Medium quality means use a mipmap for down-scaling, and just bilper + * for upscaling. Since we're examining the inverse matrix, we look for + * a scale > 1 to indicate down scaling by the CTM. + */ + if (scaleSqd > SK_Scalar1) { + const SkMipMap* mip = NULL; + + SkASSERT(NULL == fScaledCacheID); + fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip); + if (!fScaledCacheID) { + SkASSERT(NULL == mip); + mip = SkMipMap::Build(fOrigBitmap); + if (mip) { + fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap, + mip); + mip->unref(); // the cache took a ref + SkASSERT(fScaledCacheID); + } + } else { + SkASSERT(mip); + } + + if (mip) { + SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd)); + SkMipMap::Level level; + if (mip->extractLevel(levelScale, &level)) { + SkScalar invScaleFixup = level.fScale; + fInvMatrix.postScale(invScaleFixup, invScaleFixup); + + fScaledBitmap.setConfig(fOrigBitmap.config(), + level.fWidth, level.fHeight, + level.fRowBytes); + fScaledBitmap.setPixels(level.fPixels); + fBitmap = &fScaledBitmap; + fFilterLevel = SkPaint::kLow_FilterLevel; + unlocker.release(); + return true; + } + } + } + + return false; +} + +static bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) { + SkPixelRef* pr = src.pixelRef(); + if (pr && pr->decodeInto(pow2, dst)) { + return true; + } + + /* + * If decodeInto() fails, it is possibe that we have an old subclass that + * does not, or cannot, implement that. In that case we fall back to the + * older protocol of having the pixelRef handle the caching for us. + */ + *dst = src; + dst->lockPixels(); + return SkToBool(dst->getPixels()); +} + +bool SkBitmapProcState::lockBaseBitmap() { + AutoScaledCacheUnlocker unlocker(&fScaledCacheID); + + SkPixelRef* pr = fOrigBitmap.pixelRef(); + + SkASSERT(NULL == fScaledCacheID); + + if (pr->isLocked() || !pr->implementsDecodeInto()) { + // fast-case, no need to look in our cache + fScaledBitmap = fOrigBitmap; + fScaledBitmap.lockPixels(); + if (NULL == fScaledBitmap.getPixels()) { + return false; + } + } else { + fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap, + SK_Scalar1, SK_Scalar1, + &fScaledBitmap); + if (fScaledCacheID) { + fScaledBitmap.lockPixels(); + if (!fScaledBitmap.getPixels()) { + fScaledBitmap.unlockPixels(); + // found a purged entry (discardablememory?), release it + SkScaledImageCache::Unlock(fScaledCacheID); + fScaledCacheID = NULL; + // fall through to rebuild + } + } + + if (NULL == fScaledCacheID) { + if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) { + return false; + } + + // TODO: if fScaled comes back at a different width/height than fOrig, + // we need to update the matrix we are using to sample from this guy. + + fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap, + SK_Scalar1, SK_Scalar1, + fScaledBitmap); + if (!fScaledCacheID) { + fScaledBitmap.reset(); + return false; + } + } + } + fBitmap = &fScaledBitmap; + unlocker.release(); + 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); + } + SkDELETE(fBitmapFilter); +} + +bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { + SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); + + fBitmap = NULL; + fInvMatrix = inv; + fFilterLevel = paint.getFilterLevel(); + + SkASSERT(NULL == fScaledCacheID); + + // possiblyScaleImage will look to see if it can rescale the image as a + // preprocess; either by scaling up to the target size, or by selecting + // a nearby mipmap level. If it does, it will adjust the working + // matrix as well as the working bitmap. It may also adjust the filter + // quality to avoid re-filtering an already perfectly scaled image. + if (!this->possiblyScaleImage()) { + if (!this->lockBaseBitmap()) { + return false; + } + } + // The above logic should have always assigned fBitmap, but in case it + // didn't, we check for that now... + if (NULL == fBitmap) { + return false; + } + + bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; + bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && + SkShader::kClamp_TileMode == fTileModeY; + + if (!(clampClamp || trivialMatrix)) { + fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); + } + + // Now that all possible changes to the matrix have taken place, check + // to see if we're really close to a no-scale matrix. If so, explicitly + // set it to be so. Subsequent code may inspect this matrix to choose + // a faster path in this case. + + // This code will only execute if the matrix has some scale component; + // if it's already pure translate then we won't do this inversion. + + if (matrix_only_scale_translate(fInvMatrix)) { + SkMatrix forward; + if (fInvMatrix.invert(&forward)) { + if (clampClamp ? just_trans_clamp(forward, *fBitmap) + : just_trans_general(forward)) { + SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); + SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); + fInvMatrix.setTranslate(tx, ty); + } + } + } + + fInvProc = fInvMatrix.getMapXYProc(); + fInvType = fInvMatrix.getType(); + fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); + fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); + fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); + fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); + + fAlphaScale = SkAlpha255To256(paint.getAlpha()); + + fShaderProc32 = NULL; + fShaderProc16 = NULL; + fSampleProc32 = NULL; + fSampleProc16 = NULL; + + // recompute the triviality of the matrix here because we may have + // changed it! + + trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; + + if (SkPaint::kHigh_FilterLevel == fFilterLevel) { + // If this is still set, that means we wanted HQ sampling + // but couldn't do it as a preprocess. Let's try to install + // the scanline version of the HQ sampler. If that process fails, + // downgrade to bilerp. + + // NOTE: Might need to be careful here in the future when we want + // to have the platform proc have a shot at this; it's possible that + // the chooseBitmapFilterProc will fail to install a shader but a + // platform-specific one might succeed, so it might be premature here + // to fall back to bilerp. This needs thought. + + if (!this->setBitmapFilterProcs()) { + fFilterLevel = SkPaint::kLow_FilterLevel; + } + } + + if (SkPaint::kLow_FilterLevel == fFilterLevel) { + // Only try bilerp if the matrix is "interesting" and + // the image has a suitable size. + + if (fInvType <= SkMatrix::kTranslate_Mask || + !valid_for_filtering(fBitmap->width() | fBitmap->height())) { + fFilterLevel = SkPaint::kNone_FilterLevel; + } + } + + // At this point, we know exactly what kind of sampling the per-scanline + // shader will perform. + + fMatrixProc = this->chooseMatrixProc(trivialMatrix); + if (NULL == fMatrixProc) { + return false; + } + + /////////////////////////////////////////////////////////////////////// + + // No need to do this if we're doing HQ sampling; if filter quality is + // still set to HQ by the time we get here, then we must have installed + // the shader procs above and can skip all this. + + if (fFilterLevel < SkPaint::kHigh_FilterLevel) { + + int index = 0; + if (fAlphaScale < 256) { // note: this distinction is not used for D16 + index |= 1; + } + if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { + index |= 2; + } + if (fFilterLevel > SkPaint::kNone_FilterLevel) { + index |= 4; + } + // bits 3,4,5 encoding the source bitmap format + switch (fBitmap->config()) { + case SkBitmap::kARGB_8888_Config: + index |= 0; + break; + case SkBitmap::kRGB_565_Config: + index |= 8; + break; + case SkBitmap::kIndex8_Config: + index |= 16; + break; + case SkBitmap::kARGB_4444_Config: + index |= 24; + break; + case SkBitmap::kA8_Config: + index |= 32; + fPaintPMColor = SkPreMultiplyColor(paint.getColor()); + break; + default: + return false; + } + + #if !SK_ARM_NEON_IS_ALWAYS + static const SampleProc32 gSkBitmapProcStateSample32[] = { + S32_opaque_D32_nofilter_DXDY, + S32_alpha_D32_nofilter_DXDY, + S32_opaque_D32_nofilter_DX, + S32_alpha_D32_nofilter_DX, + S32_opaque_D32_filter_DXDY, + S32_alpha_D32_filter_DXDY, + S32_opaque_D32_filter_DX, + S32_alpha_D32_filter_DX, + + S16_opaque_D32_nofilter_DXDY, + S16_alpha_D32_nofilter_DXDY, + S16_opaque_D32_nofilter_DX, + S16_alpha_D32_nofilter_DX, + S16_opaque_D32_filter_DXDY, + S16_alpha_D32_filter_DXDY, + S16_opaque_D32_filter_DX, + S16_alpha_D32_filter_DX, + + SI8_opaque_D32_nofilter_DXDY, + SI8_alpha_D32_nofilter_DXDY, + SI8_opaque_D32_nofilter_DX, + SI8_alpha_D32_nofilter_DX, + SI8_opaque_D32_filter_DXDY, + SI8_alpha_D32_filter_DXDY, + SI8_opaque_D32_filter_DX, + SI8_alpha_D32_filter_DX, + + S4444_opaque_D32_nofilter_DXDY, + S4444_alpha_D32_nofilter_DXDY, + S4444_opaque_D32_nofilter_DX, + S4444_alpha_D32_nofilter_DX, + S4444_opaque_D32_filter_DXDY, + S4444_alpha_D32_filter_DXDY, + S4444_opaque_D32_filter_DX, + S4444_alpha_D32_filter_DX, + + // A8 treats alpha/opaque the same (equally efficient) + SA8_alpha_D32_nofilter_DXDY, + SA8_alpha_D32_nofilter_DXDY, + SA8_alpha_D32_nofilter_DX, + SA8_alpha_D32_nofilter_DX, + SA8_alpha_D32_filter_DXDY, + SA8_alpha_D32_filter_DXDY, + SA8_alpha_D32_filter_DX, + SA8_alpha_D32_filter_DX + }; + + static const SampleProc16 gSkBitmapProcStateSample16[] = { + S32_D16_nofilter_DXDY, + S32_D16_nofilter_DX, + S32_D16_filter_DXDY, + S32_D16_filter_DX, + + S16_D16_nofilter_DXDY, + S16_D16_nofilter_DX, + S16_D16_filter_DXDY, + S16_D16_filter_DX, + + SI8_D16_nofilter_DXDY, + SI8_D16_nofilter_DX, + SI8_D16_filter_DXDY, + SI8_D16_filter_DX, + + // Don't support 4444 -> 565 + NULL, NULL, NULL, NULL, + // Don't support A8 -> 565 + NULL, NULL, NULL, NULL + }; + #endif + + fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; + index >>= 1; // shift away any opaque/alpha distinction + fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; + + // our special-case shaderprocs + if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { + if (clampClamp) { + fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); + } else if (SkShader::kRepeat_TileMode == fTileModeX && + SkShader::kRepeat_TileMode == fTileModeY) { + fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); + } + } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) { + fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); + } + + if (NULL == fShaderProc32) { + fShaderProc32 = this->chooseShaderProc32(); + } + } + + // see if our platform has any accelerated overrides + this->platformProcs(); + + return true; +} + +static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, + int x, int y, + SkPMColor* SK_RESTRICT colors, + int count) { + SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); + SkASSERT(s.fInvKy == 0); + SkASSERT(count > 0 && colors != NULL); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); + + const int maxX = s.fBitmap->width() - 1; + const int maxY = s.fBitmap->height() - 1; + int ix = s.fFilterOneX + x; + int iy = SkClampMax(s.fFilterOneY + y, maxY); +#ifdef SK_DEBUG + { + SkPoint pt; + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, &pt); + int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY); + int ix2 = SkScalarFloorToInt(pt.fX); + + SkASSERT(iy == iy2); + SkASSERT(ix == ix2); + } +#endif + const SkPMColor* row = s.fBitmap->getAddr32(0, iy); + + // clamp to the left + if (ix < 0) { + int n = SkMin32(-ix, count); + sk_memset32(colors, row[0], n); + count -= n; + if (0 == count) { + return; + } + colors += n; + SkASSERT(-ix == n); + ix = 0; + } + // copy the middle + if (ix <= maxX) { + int n = SkMin32(maxX - ix + 1, count); + memcpy(colors, row + ix, n * sizeof(SkPMColor)); + count -= n; + if (0 == count) { + return; + } + colors += n; + } + SkASSERT(count > 0); + // clamp to the right + sk_memset32(colors, row[maxX], count); +} + +static inline int sk_int_mod(int x, int n) { + SkASSERT(n > 0); + if ((unsigned)x >= (unsigned)n) { + if (x < 0) { + x = n + ~(~x % n); + } else { + x = x % n; + } + } + return x; +} + +static inline int sk_int_mirror(int x, int n) { + x = sk_int_mod(x, 2 * n); + if (x >= n) { + x = n + ~(x - n); + } + return x; +} + +static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s, + int x, int y, + SkPMColor* SK_RESTRICT colors, + int count) { + SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0); + SkASSERT(s.fInvKy == 0); + SkASSERT(count > 0 && colors != NULL); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); + + const int stopX = s.fBitmap->width(); + const int stopY = s.fBitmap->height(); + int ix = s.fFilterOneX + x; + int iy = sk_int_mod(s.fFilterOneY + y, stopY); +#ifdef SK_DEBUG + { + SkPoint pt; + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, &pt); + int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); + int ix2 = SkScalarFloorToInt(pt.fX); + + SkASSERT(iy == iy2); + SkASSERT(ix == ix2); + } +#endif + const SkPMColor* row = s.fBitmap->getAddr32(0, iy); + + ix = sk_int_mod(ix, stopX); + for (;;) { + int n = SkMin32(stopX - ix, count); + memcpy(colors, row + ix, n * sizeof(SkPMColor)); + count -= n; + if (0 == count) { + return; + } + colors += n; + ix = 0; + } +} + +static void S32_D32_constX_shaderproc(const SkBitmapProcState& s, + int x, int y, + SkPMColor* SK_RESTRICT colors, + int count) { + SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0); + SkASSERT(s.fInvKy == 0); + SkASSERT(count > 0 && colors != NULL); + SkASSERT(1 == s.fBitmap->width()); + + int iY0; + int iY1 SK_INIT_TO_AVOID_WARNING; + int iSubY SK_INIT_TO_AVOID_WARNING; + + if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { + SkBitmapProcState::MatrixProc mproc = s.getMatrixProc(); + uint32_t xy[2]; + + mproc(s, xy, 1, x, y); + + iY0 = xy[0] >> 18; + iY1 = xy[0] & 0x3FFF; + iSubY = (xy[0] >> 14) & 0xF; + } else { + int yTemp; + + if (s.fInvType > SkMatrix::kTranslate_Mask) { + SkPoint pt; + s.fInvProc(s.fInvMatrix, + SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, + &pt); + // When the matrix has a scale component the setup code in + // chooseProcs multiples the inverse matrix by the inverse of the + // bitmap's width and height. Since this method is going to do + // its own tiling and sampling we need to undo that here. + if (SkShader::kClamp_TileMode != s.fTileModeX || + SkShader::kClamp_TileMode != s.fTileModeY) { + yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height()); + } else { + yTemp = SkScalarFloorToInt(pt.fY); + } + } else { + yTemp = s.fFilterOneY + y; + } + + const int stopY = s.fBitmap->height(); + switch (s.fTileModeY) { + case SkShader::kClamp_TileMode: + iY0 = SkClampMax(yTemp, stopY-1); + break; + case SkShader::kRepeat_TileMode: + iY0 = sk_int_mod(yTemp, stopY); + break; + case SkShader::kMirror_TileMode: + default: + iY0 = sk_int_mirror(yTemp, stopY); + break; + } + +#ifdef SK_DEBUG + { + SkPoint pt; + s.fInvProc(s.fInvMatrix, + SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, + &pt); + if (s.fInvType > SkMatrix::kTranslate_Mask && + (SkShader::kClamp_TileMode != s.fTileModeX || + SkShader::kClamp_TileMode != s.fTileModeY)) { + pt.fY *= s.fBitmap->height(); + } + int iY2; + + switch (s.fTileModeY) { + case SkShader::kClamp_TileMode: + iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1); + break; + case SkShader::kRepeat_TileMode: + iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY); + break; + case SkShader::kMirror_TileMode: + default: + iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY); + break; + } + + SkASSERT(iY0 == iY2); + } +#endif + } + + const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0); + SkPMColor color; + + if (SkPaint::kNone_FilterLevel != s.fFilterLevel) { + const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1); + + if (s.fAlphaScale < 256) { + Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale); + } else { + Filter_32_opaque(iSubY, *row0, *row1, &color); + } + } else { + if (s.fAlphaScale < 256) { + color = SkAlphaMulQ(*row0, s.fAlphaScale); + } else { + color = *row0; + } + } + + sk_memset32(colors, color, count); +} + +static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y, + SkPMColor* SK_RESTRICT colors, int count) { + // if we get called, the matrix is too tricky, so we just draw nothing + sk_memset32(colors, 0, count); +} + +bool SkBitmapProcState::setupForTranslate() { + SkPoint pt; + fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt); + + /* + * if the translate is larger than our ints, we can get random results, or + * worse, we might get 0x80000000, which wreaks havoc on us, since we can't + * negate it. + */ + const SkScalar too_big = SkIntToScalar(1 << 30); + if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) { + return false; + } + + // Since we know we're not filtered, we re-purpose these fields allow + // us to go from device -> src coordinates w/ just an integer add, + // rather than running through the inverse-matrix + fFilterOneX = SkScalarFloorToInt(pt.fX); + fFilterOneY = SkScalarFloorToInt(pt.fY); + return true; +} + +SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() { + + if (SkBitmap::kARGB_8888_Config != fBitmap->config()) { + return NULL; + } + + static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; + + if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) { + if (SkPaint::kNone_FilterLevel == fFilterLevel && + fInvType <= SkMatrix::kTranslate_Mask && + !this->setupForTranslate()) { + return DoNothing_shaderproc; + } + return S32_D32_constX_shaderproc; + } + + if (fAlphaScale < 256) { + return NULL; + } + if (fInvType > SkMatrix::kTranslate_Mask) { + return NULL; + } + if (SkPaint::kNone_FilterLevel != fFilterLevel) { + return NULL; + } + + SkShader::TileMode tx = (SkShader::TileMode)fTileModeX; + SkShader::TileMode ty = (SkShader::TileMode)fTileModeY; + + if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) { + if (this->setupForTranslate()) { + return Clamp_S32_D32_nofilter_trans_shaderproc; + } + return DoNothing_shaderproc; + } + if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) { + if (this->setupForTranslate()) { + return Repeat_S32_D32_nofilter_trans_shaderproc; + } + return DoNothing_shaderproc; + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +static void check_scale_nofilter(uint32_t bitmapXY[], int count, + unsigned mx, unsigned my) { + unsigned y = *bitmapXY++; + SkASSERT(y < my); + + const uint16_t* xptr = reinterpret_cast(bitmapXY); + for (int i = 0; i < count; ++i) { + SkASSERT(xptr[i] < mx); + } +} + +static void check_scale_filter(uint32_t bitmapXY[], int count, + unsigned mx, unsigned my) { + uint32_t YY = *bitmapXY++; + unsigned y0 = YY >> 18; + unsigned y1 = YY & 0x3FFF; + SkASSERT(y0 < my); + SkASSERT(y1 < my); + + for (int i = 0; i < count; ++i) { + uint32_t XX = bitmapXY[i]; + unsigned x0 = XX >> 18; + unsigned x1 = XX & 0x3FFF; + SkASSERT(x0 < mx); + SkASSERT(x1 < mx); + } +} + +static void check_affine_nofilter(uint32_t bitmapXY[], int count, + unsigned mx, unsigned my) { + for (int i = 0; i < count; ++i) { + uint32_t XY = bitmapXY[i]; + unsigned x = XY & 0xFFFF; + unsigned y = XY >> 16; + SkASSERT(x < mx); + SkASSERT(y < my); + } +} + +static void check_affine_filter(uint32_t bitmapXY[], int count, + unsigned mx, unsigned my) { + for (int i = 0; i < count; ++i) { + uint32_t YY = *bitmapXY++; + unsigned y0 = YY >> 18; + unsigned y1 = YY & 0x3FFF; + SkASSERT(y0 < my); + SkASSERT(y1 < my); + + uint32_t XX = *bitmapXY++; + unsigned x0 = XX >> 18; + unsigned x1 = XX & 0x3FFF; + SkASSERT(x0 < mx); + SkASSERT(x1 < mx); + } +} + +void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state, + uint32_t bitmapXY[], int count, + int x, int y) { + SkASSERT(bitmapXY); + SkASSERT(count > 0); + + state.fMatrixProc(state, bitmapXY, count, x, y); + + void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my); + + // There are four formats possible: + // scale -vs- affine + // filter -vs- nofilter + if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { + proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter; + } else { + proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter; + } + proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height()); +} + +SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const { + return DebugMatrixProc; +} + +#endif + +/////////////////////////////////////////////////////////////////////////////// +/* + The storage requirements for the different matrix procs are as follows, + where each X or Y is 2 bytes, and N is the number of pixels/elements: + + scale/translate nofilter Y(4bytes) + N * X + affine/perspective nofilter N * (X Y) + scale/translate filter Y Y + N * (X X) + affine/perspective filter N * (Y Y X X) + */ +int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { + int32_t size = static_cast(bufferSize); + + size &= ~3; // only care about 4-byte aligned chunks + if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { + size -= 4; // the shared Y (or YY) coordinate + if (size < 0) { + size = 0; + } + size >>= 1; + } else { + size >>= 2; + } + + if (fFilterLevel != SkPaint::kNone_FilterLevel) { + size >>= 1; + } + + return size; +} diff --git a/gfx/skia/src/core/SkBitmapProcState.h b/gfx/skia/trunk/src/core/SkBitmapProcState.h similarity index 80% rename from gfx/skia/src/core/SkBitmapProcState.h rename to gfx/skia/trunk/src/core/SkBitmapProcState.h index 69f4c2f0d255..d5a354e36aca 100644 --- a/gfx/skia/src/core/SkBitmapProcState.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcState.h @@ -11,7 +11,10 @@ #define SkBitmapProcState_DEFINED #include "SkBitmap.h" +#include "SkBitmapFilter.h" #include "SkMatrix.h" +#include "SkPaint.h" +#include "SkScaledImageCache.h" #define FractionalInt_IS_64BIT @@ -30,9 +33,13 @@ #endif class SkPaint; +struct SkConvolutionProcs; struct SkBitmapProcState { + SkBitmapProcState(): fScaledCacheID(NULL), fBitmapFilter(NULL) {} + ~SkBitmapProcState(); + typedef void (*ShaderProc32)(const SkBitmapProcState&, int x, int y, SkPMColor[], int count); @@ -58,8 +65,8 @@ struct SkBitmapProcState { typedef U16CPU (*FixedTileLowBitsProc)(SkFixed, int); // returns 0..0xF typedef U16CPU (*IntTileProc)(int value, int count); // returns 0..count-1 - const SkBitmap* fBitmap; // chooseProcs - orig or mip - const SkMatrix* fInvMatrix; // chooseProcs + const SkBitmap* fBitmap; // chooseProcs - orig or scaled + SkMatrix fInvMatrix; // chooseProcs SkMatrix::MapXYProc fInvProc; // chooseProcs SkFractionalInt fInvSxFractionalInt; @@ -80,7 +87,13 @@ struct SkBitmapProcState { uint8_t fInvType; // chooseProcs uint8_t fTileModeX; // CONSTRUCTOR uint8_t fTileModeY; // CONSTRUCTOR - SkBool8 fDoFilter; // chooseProcs + 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: @@ -97,6 +110,12 @@ struct SkBitmapProcState { */ void platformProcs(); + /** Platforms can also optionally overwrite the convolution functions + if we have SIMD versions of them. + */ + + void platformConvolutionProcs(SkConvolutionProcs*); + /** Given the byte size of the index buffer to be passed to the matrix proc, return the maximum number of resulting pixels that can be computed (i.e. the number of SkPMColor values to be written by the sample proc). @@ -113,6 +132,8 @@ struct SkBitmapProcState { ShaderProc32 getShaderProc32() const { return fShaderProc32; } ShaderProc16 getShaderProc16() const { return fShaderProc16; } + SkBitmapFilter* getBitmapFilter() const { return fBitmapFilter; } + #ifdef SK_DEBUG MatrixProc getMatrixProc() const; #else @@ -131,14 +152,29 @@ private: SampleProc32 fSampleProc32; // chooseProcs SampleProc16 fSampleProc16; // chooseProcs - SkMatrix fUnitInvMatrix; // chooseProcs SkBitmap fOrigBitmap; // CONSTRUCTOR - SkBitmap fMipBitmap; + SkBitmap fScaledBitmap; // chooseProcs + + SkScaledImageCache::ID* fScaledCacheID; MatrixProc chooseMatrixProc(bool trivial_matrix); bool chooseProcs(const SkMatrix& inv, const SkPaint&); ShaderProc32 chooseShaderProc32(); + // returns false if we did not try to scale the image. In that case, we + // will need to "lock" its pixels some other way. + bool possiblyScaleImage(); + + // returns false if we failed to "lock" the pixels at all. Typically this + // means we have to abort the shader. + bool lockBaseBitmap(); + + SkBitmapFilter* fBitmapFilter; + + // If supported, sets fShaderProc32 and fShaderProc16 and returns true, + // otherwise returns false. + bool setBitmapFilterProcs(); + // Return false if we failed to setup for fast translate (e.g. overflow) bool setupForTranslate(); @@ -179,9 +215,9 @@ void S32_opaque_D32_filter_DX(const SkBitmapProcState& s, const uint32_t xy[], void S32_alpha_D32_filter_DX(const SkBitmapProcState& s, const uint32_t xy[], int count, SkPMColor colors[]); void S32_opaque_D32_filter_DXDY(const SkBitmapProcState& s, - const uint32_t xy[], int count, SkPMColor colors[]); + const uint32_t xy[], int count, SkPMColor colors[]); void S32_alpha_D32_filter_DXDY(const SkBitmapProcState& s, - const uint32_t xy[], int count, SkPMColor colors[]); + const uint32_t xy[], int count, SkPMColor colors[]); void ClampX_ClampY_filter_scale(const SkBitmapProcState& s, uint32_t xy[], int count, int x, int y); void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[], @@ -191,6 +227,12 @@ void ClampX_ClampY_filter_affine(const SkBitmapProcState& s, void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, uint32_t xy[], int count, int x, int y); void S32_D16_filter_DX(const SkBitmapProcState& s, - const uint32_t* xy, int count, uint16_t* colors); + const uint32_t* xy, int count, uint16_t* colors); + +void highQualityFilter32(const SkBitmapProcState &s, int x, int y, + SkPMColor *SK_RESTRICT colors, int count); +void highQualityFilter16(const SkBitmapProcState &s, int x, int y, + uint16_t *SK_RESTRICT colors, int count); + #endif diff --git a/gfx/skia/src/core/SkBitmapProcState_filter.h b/gfx/skia/trunk/src/core/SkBitmapProcState_filter.h similarity index 100% rename from gfx/skia/src/core/SkBitmapProcState_filter.h rename to gfx/skia/trunk/src/core/SkBitmapProcState_filter.h diff --git a/gfx/skia/src/core/SkBitmapProcState_matrix.h b/gfx/skia/trunk/src/core/SkBitmapProcState_matrix.h similarity index 97% rename from gfx/skia/src/core/SkBitmapProcState_matrix.h rename to gfx/skia/trunk/src/core/SkBitmapProcState_matrix.h index cc65c2d801af..d796d0b04c4c 100644 --- a/gfx/skia/src/core/SkBitmapProcState_matrix.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_matrix.h @@ -55,7 +55,7 @@ void SCALE_NOFILTER_NAME(const SkBitmapProcState& s, SkFractionalInt fx; { SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &pt); fx = SkScalarToFractionalInt(pt.fY); const unsigned maxY = s.fBitmap->height() - 1; @@ -116,7 +116,7 @@ void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s, PREAMBLE(s); SkPoint srcPt; - s.fInvProc(*s.fInvMatrix, + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &srcPt); @@ -143,7 +143,7 @@ void PERSP_NOFILTER_NAME(const SkBitmapProcState& s, int maxX = s.fBitmap->width() - 1; int maxY = s.fBitmap->height() - 1; - SkPerspIter iter(*s.fInvMatrix, + SkPerspIter iter(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, count); @@ -188,7 +188,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, { SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + 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; @@ -222,7 +222,7 @@ void AFFINE_FILTER_NAME(const SkBitmapProcState& s, PREAMBLE(s); SkPoint srcPt; - s.fInvProc(*s.fInvMatrix, + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &srcPt); @@ -254,7 +254,7 @@ void PERSP_FILTER_NAME(const SkBitmapProcState& s, SkFixed oneX = s.fFilterOneX; SkFixed oneY = s.fFilterOneY; - SkPerspIter iter(*s.fInvMatrix, + SkPerspIter iter(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, count); diff --git a/gfx/skia/src/core/SkBitmapProcState_matrixProcs.cpp b/gfx/skia/trunk/src/core/SkBitmapProcState_matrixProcs.cpp similarity index 86% rename from gfx/skia/src/core/SkBitmapProcState_matrixProcs.cpp rename to gfx/skia/trunk/src/core/SkBitmapProcState_matrixProcs.cpp index 15c17b67dca3..57376d5699df 100644 --- a/gfx/skia/src/core/SkBitmapProcState_matrixProcs.cpp +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_matrixProcs.cpp @@ -9,13 +9,7 @@ #include "SkShader.h" #include "SkUtils.h" #include "SkUtilsArm.h" - -// Helper to ensure that when we shift down, we do it w/o sign-extension -// so the caller doesn't have to manually mask off the top 16 bits -// -static unsigned SK_USHIFT16(unsigned x) { - return x >> 16; -} +#include "SkBitmapProcState_utils.h" /* returns 0...(n-1) given any x (positive or negative). @@ -36,35 +30,6 @@ static inline int sk_int_mod(int x, int n) { return x; } -/* - * The decal_ functions require that - * 1. dx > 0 - * 2. [fx, fx+dx, fx+2dx, fx+3dx, ... fx+(count-1)dx] are all <= maxX - * - * In addition, we use SkFractionalInt to keep more fractional precision than - * just SkFixed, so we will abort the decal_ call if dx is very small, since - * the decal_ function just operates on SkFixed. If that were changed, we could - * skip the very_small test here. - */ -static inline bool can_truncate_to_fixed_for_decal(SkFractionalInt frX, - SkFractionalInt frDx, - int count, unsigned max) { - SkFixed dx = SkFractionalIntToFixed(frDx); - - // if decal_ kept SkFractionalInt precision, this would just be dx <= 0 - // I just made up the 1/256. Just don't want to perceive accumulated error - // if we truncate frDx and lose its low bits. - if (dx <= SK_Fixed1 / 256) { - return false; - } - - // We cast to unsigned so we don't have to check for negative values, which - // will now appear as very large positive values, and thus fail our test! - SkFixed fx = SkFractionalIntToFixed(frX); - return (unsigned)SkFixedFloorToInt(fx) <= max && - (unsigned)SkFixedFloorToInt(fx + dx * (count - 1)) < max; -} - 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); @@ -112,24 +77,12 @@ extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[]; static inline U16CPU fixed_clamp(SkFixed x) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (x < 0) + if (x < 0) { x = 0; - if (x >> 16) - x = 0xFFFF; -#else - if (x >> 16) - { -#if 0 // is this faster? - x = (~x >> 31) & 0xFFFF; -#else - if (x < 0) - x = 0; - else - x = 0xFFFF; -#endif } -#endif + if (x >> 16) { + x = 0xFFFF; + } return x; } @@ -185,20 +138,12 @@ static SkBitmapProcState::FixedTileLowBitsProc choose_tile_lowbits_proc(unsigned } static inline U16CPU int_clamp(int x, int n) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR - if (x >= n) + if (x >= n) { x = n - 1; - if (x < 0) - x = 0; -#else - if ((unsigned)x >= (unsigned)n) { - if (x < 0) { - x = 0; - } else { - x = n - 1; - } } -#endif + if (x < 0) { + x = 0; + } return x; } @@ -311,7 +256,7 @@ static void fill_sequential(uint16_t xptr[], int start, int count) { static int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy, int x, int y) { SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &pt); **xy = s.fIntTileProcY(SkScalarToFixed(pt.fY) >> 16, s.fBitmap->height()); @@ -472,7 +417,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { // test_int_tileprocs(); // check for our special case when there is no scale/affine/perspective if (trivial_matrix) { - SkASSERT(!fDoFilter); + SkASSERT(SkPaint::kNone_FilterLevel == fFilterLevel); fIntTileProcY = choose_int_tile_proc(fTileModeY); switch (fTileModeX) { case SkShader::kClamp_TileMode: @@ -485,7 +430,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { } int index = 0; - if (fDoFilter) { + if (fFilterLevel != SkPaint::kNone_FilterLevel) { index = 1; } if (fInvType & SkMatrix::kPerspective_Mask) { diff --git a/gfx/skia/src/core/SkBitmapProcState_procs.h b/gfx/skia/trunk/src/core/SkBitmapProcState_procs.h similarity index 99% rename from gfx/skia/src/core/SkBitmapProcState_procs.h rename to gfx/skia/trunk/src/core/SkBitmapProcState_procs.h index da9ca89bbf95..68c79835a9d1 100644 --- a/gfx/skia/src/core/SkBitmapProcState_procs.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_procs.h @@ -157,7 +157,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y, #define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors() #define RETURNDST(src) table[src] #define SRC_TO_FILTER(src) table[src] -#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false) +#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors() #include "SkBitmapProcState_sample.h" #undef FILTER_PROC @@ -172,7 +172,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y, const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors() #define RETURNDST(src) SkAlphaMulQ(table[src], alphaScale) #define SRC_TO_FILTER(src) table[src] -#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors(false) +#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors() #include "SkBitmapProcState_sample.h" // SRC == 4444 @@ -337,7 +337,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y, #define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config) #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(false) +#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors() #include "SkBitmapProcState_shaderproc.h" #undef NAME_WRAP diff --git a/gfx/skia/src/core/SkBitmapProcState_sample.h b/gfx/skia/trunk/src/core/SkBitmapProcState_sample.h similarity index 96% rename from gfx/skia/src/core/SkBitmapProcState_sample.h rename to gfx/skia/trunk/src/core/SkBitmapProcState_sample.h index ea377f2368f7..5c5f199f25cf 100644 --- a/gfx/skia/src/core/SkBitmapProcState_sample.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_sample.h @@ -42,7 +42,7 @@ void MAKENAME(_nofilter_DXDY)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fDoFilter == false); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -85,7 +85,7 @@ void MAKENAME(_nofilter_DX)(const SkBitmapProcState& s, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)); - SkASSERT(s.fDoFilter == false); + SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -139,7 +139,7 @@ void MAKENAME(_filter_DX)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fDoFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE @@ -185,7 +185,7 @@ void MAKENAME(_filter_DXDY)(const SkBitmapProcState& s, const uint32_t* SK_RESTRICT xy, int count, DSTTYPE* SK_RESTRICT colors) { SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fDoFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) #ifdef PREAMBLE diff --git a/gfx/skia/src/core/SkBitmapProcState_shaderproc.h b/gfx/skia/trunk/src/core/SkBitmapProcState_shaderproc.h similarity index 95% rename from gfx/skia/src/core/SkBitmapProcState_shaderproc.h rename to gfx/skia/trunk/src/core/SkBitmapProcState_shaderproc.h index 6b8f74aedd16..0014b4a526f5 100644 --- a/gfx/skia/src/core/SkBitmapProcState_shaderproc.h +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_shaderproc.h @@ -21,7 +21,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, int x, int y, SkMatrix::kScale_Mask)) == 0); SkASSERT(s.fInvKy == 0); SkASSERT(count > 0 && colors != NULL); - SkASSERT(s.fDoFilter); + SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel); SkDEBUGCODE(CHECKSTATE(s);) const unsigned maxX = s.fBitmap->width() - 1; @@ -34,7 +34,7 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, int x, int y, { SkPoint pt; - s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, + s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &pt); SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1); const unsigned maxY = s.fBitmap->height() - 1; diff --git a/gfx/skia/trunk/src/core/SkBitmapProcState_utils.h b/gfx/skia/trunk/src/core/SkBitmapProcState_utils.h new file mode 100644 index 000000000000..3c4c1fa8c67f --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapProcState_utils.h @@ -0,0 +1,40 @@ +#ifndef SkBitmapProcState_utils_DEFINED +#define SkBitmapProcState_utils_DEFINED + +// Helper to ensure that when we shift down, we do it w/o sign-extension +// so the caller doesn't have to manually mask off the top 16 bits +// +static unsigned SK_USHIFT16(unsigned x) { + return x >> 16; +} + +/* + * The decal_ functions require that + * 1. dx > 0 + * 2. [fx, fx+dx, fx+2dx, fx+3dx, ... fx+(count-1)dx] are all <= maxX + * + * In addition, we use SkFractionalInt to keep more fractional precision than + * just SkFixed, so we will abort the decal_ call if dx is very small, since + * the decal_ function just operates on SkFixed. If that were changed, we could + * skip the very_small test here. + */ +static inline bool can_truncate_to_fixed_for_decal(SkFractionalInt frX, + SkFractionalInt frDx, + int count, unsigned max) { + SkFixed dx = SkFractionalIntToFixed(frDx); + + // if decal_ kept SkFractionalInt precision, this would just be dx <= 0 + // I just made up the 1/256. Just don't want to perceive accumulated error + // if we truncate frDx and lose its low bits. + if (dx <= SK_Fixed1 / 256) { + return false; + } + + // We cast to unsigned so we don't have to check for negative values, which + // will now appear as very large positive values, and thus fail our test! + SkFixed fx = SkFractionalIntToFixed(frX); + return (unsigned)SkFixedFloorToInt(fx) <= max && + (unsigned)SkFixedFloorToInt(fx + dx * (count - 1)) < max; +} + +#endif /* #ifndef SkBitmapProcState_utils_DEFINED */ diff --git a/gfx/skia/trunk/src/core/SkBitmapScaler.cpp b/gfx/skia/trunk/src/core/SkBitmapScaler.cpp new file mode 100644 index 000000000000..67a9508ee982 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapScaler.cpp @@ -0,0 +1,319 @@ +#include "SkBitmapScaler.h" +#include "SkBitmapFilter.h" +#include "SkRect.h" +#include "SkTArray.h" +#include "SkErrorInternals.h" +#include "SkConvolver.h" + +// SkResizeFilter ---------------------------------------------------------------- + +// Encapsulates computation and storage of the filters required for one complete +// resize operation. +class SkResizeFilter { +public: + SkResizeFilter(SkBitmapScaler::ResizeMethod method, + int srcFullWidth, int srcFullHeight, + int destWidth, int destHeight, + const SkIRect& destSubset, + const SkConvolutionProcs& convolveProcs); + ~SkResizeFilter() { + SkDELETE( fBitmapFilter ); + } + + // Returns the filled filter values. + const SkConvolutionFilter1D& xFilter() { return fXFilter; } + const SkConvolutionFilter1D& yFilter() { return fYFilter; } + +private: + + SkBitmapFilter* fBitmapFilter; + + // Computes one set of filters either horizontally or vertically. The caller + // will specify the "min" and "max" rather than the bottom/top and + // right/bottom so that the same code can be re-used in each dimension. + // + // |srcDependLo| and |srcDependSize| gives the range for the source + // depend rectangle (horizontally or vertically at the caller's discretion + // -- see above for what this means). + // + // Likewise, the range of destination values to compute and the scale factor + // for the transform is also specified. + + void computeFilters(int srcSize, + int destSubsetLo, int destSubsetSize, + float scale, + SkConvolutionFilter1D* output, + const SkConvolutionProcs& convolveProcs); + + SkConvolutionFilter1D fXFilter; + SkConvolutionFilter1D fYFilter; +}; + +SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method, + int srcFullWidth, int srcFullHeight, + int destWidth, int destHeight, + const SkIRect& destSubset, + const SkConvolutionProcs& convolveProcs) { + + // method will only ever refer to an "algorithm method". + SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && + (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); + + switch(method) { + case SkBitmapScaler::RESIZE_BOX: + fBitmapFilter = SkNEW(SkBoxFilter); + break; + case SkBitmapScaler::RESIZE_TRIANGLE: + fBitmapFilter = SkNEW(SkTriangleFilter); + break; + case SkBitmapScaler::RESIZE_MITCHELL: + fBitmapFilter = SkNEW_ARGS(SkMitchellFilter, (1.f/3.f, 1.f/3.f)); + break; + case SkBitmapScaler::RESIZE_HAMMING: + fBitmapFilter = SkNEW(SkHammingFilter); + break; + case SkBitmapScaler::RESIZE_LANCZOS3: + fBitmapFilter = SkNEW(SkLanczosFilter); + break; + default: + // NOTREACHED: + fBitmapFilter = SkNEW_ARGS(SkMitchellFilter, (1.f/3.f, 1.f/3.f)); + break; + } + + + float scaleX = static_cast(destWidth) / + static_cast(srcFullWidth); + float scaleY = static_cast(destHeight) / + static_cast(srcFullHeight); + + this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(), + scaleX, &fXFilter, convolveProcs); + this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(), + scaleY, &fYFilter, convolveProcs); +} + +// TODO(egouriou): Take advantage of periods in the convolution. +// Practical resizing filters are periodic outside of the border area. +// For Lanczos, a scaling by a (reduced) factor of p/q (q pixels in the +// source become p pixels in the destination) will have a period of p. +// A nice consequence is a period of 1 when downscaling by an integral +// factor. Downscaling from typical display resolutions is also bound +// to produce interesting periods as those are chosen to have multiple +// small factors. +// Small periods reduce computational load and improve cache usage if +// 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 scale, + SkConvolutionFilter1D* output, + const SkConvolutionProcs& convolveProcs) { + int 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 + // that the range covered by the filter won't necessarily cover any source + // pixel boundaries. Therefore, we use these clamped values (max of 1) for + // some computations. + float clampedScale = SkTMin(1.0f, scale); + + // This is how many source pixels from the center we need to count + // to support the filtering function. + float srcSupport = fBitmapFilter->width() / clampedScale; + + // Speed up the divisions below by turning them into multiplies. + float invScale = 1.0f / scale; + + SkTArray filterValues(64); + SkTArray fixedFilterValues(64); + + // 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; + destSubsetI++) { + // Reset the arrays. We don't declare them inside so they can re-use the + // same malloc-ed buffer. + filterValues.reset(); + fixedFilterValues.reset(); + + // This is the pixel in the source directly under the pixel in the dest. + // Note that we base computations on the "center" of the pixels. To see + // why, observe that the destination pixel at coordinates (0, 0) in a 5.0x + // downscale should "cover" the pixels around the pixel with *its center* + // at coordinates (2.5, 2.5) in the source, not those around (0, 0). + // Hence we need to scale coordinates (0.5, 0.5), not (0, 0). + float srcPixel = (static_cast(destSubsetI) + 0.5f) * invScale; + + // Compute the (inclusive) range of source pixels the filter covers. + int srcBegin = SkTMax(0, SkScalarFloorToInt(srcPixel - srcSupport)); + int srcEnd = SkTMin(srcSize - 1, SkScalarCeilToInt(srcPixel + srcSupport)); + + // Compute the unnormalized filter value at each location of the source + // it covers. + float filterSum = 0.0f; // Sub of the filter values for normalizing. + for (int curFilterPixel = srcBegin; curFilterPixel <= srcEnd; + curFilterPixel++) { + // Distance from the center of the filter, this is the filter coordinate + // in source space. We also need to consider the center of the pixel + // when comparing distance against 'srcPixel'. In the 5x downscale + // example used above the distance from the center of the filter to + // the pixel with coordinates (2, 2) should be 0, because its center + // is at (2.5, 2.5). + float srcFilterDist = + ((static_cast(curFilterPixel) + 0.5f) - srcPixel); + + // Since the filter really exists in dest space, map it there. + float destFilterDist = srcFilterDist * clampedScale; + + // Compute the filter value at that location. + float filterValue = fBitmapFilter->evaluate(destFilterDist); + filterValues.push_back(filterValue); + + filterSum += filterValue; + } + SkASSERT(!filterValues.empty()); + + // The filter must be normalized so that we don't affect the brightness of + // the image. Convert to normalized fixed point. + short fixedSum = 0; + for (int i = 0; i < filterValues.count(); i++) { + short curFixed = output->FloatToFixed(filterValues[i] / filterSum); + fixedSum += curFixed; + fixedFilterValues.push_back(curFixed); + } + + // The conversion to fixed point will leave some rounding errors, which + // we add back in to avoid affecting the brightness of the image. We + // arbitrarily add this to the center of the filter array (this won't always + // be the center of the filter function since it could get clipped on the + // edges, but it doesn't matter enough to worry about that case). + short leftovers = output->FloatToFixed(1.0f) - fixedSum; + fixedFilterValues[fixedFilterValues.count() / 2] += leftovers; + + // Now it's ready to go. + output->AddFilter(srcBegin, &fixedFilterValues[0], + static_cast(fixedFilterValues.count())); + } + + if (convolveProcs.fApplySIMDPadding) { + convolveProcs.fApplySIMDPadding( output ); + } +} + +static SkBitmapScaler::ResizeMethod ResizeMethodToAlgorithmMethod( + SkBitmapScaler::ResizeMethod method) { + // Convert any "Quality Method" into an "Algorithm Method" + if (method >= SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD && + method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD) { + return method; + } + // The call to SkBitmapScalerGtv::Resize() above took care of + // GPU-acceleration in the cases where it is possible. So now we just + // pick the appropriate software method for each resize quality. + switch (method) { + // Users of RESIZE_GOOD are willing to trade a lot of quality to + // get speed, allowing the use of linear resampling to get hardware + // acceleration (SRB). Hence any of our "good" software filters + // will be acceptable, so we use a triangle. + case SkBitmapScaler::RESIZE_GOOD: + return SkBitmapScaler::RESIZE_TRIANGLE; + // Users of RESIZE_BETTER are willing to trade some quality in order + // to improve performance, but are guaranteed not to devolve to a linear + // resampling. In visual tests we see that Hamming-1 is not as good as + // Lanczos-2, however it is about 40% faster and Lanczos-2 itself is + // about 30% faster than Lanczos-3. The use of Hamming-1 has been deemed + // an acceptable trade-off between quality and speed. + case SkBitmapScaler::RESIZE_BETTER: + return SkBitmapScaler::RESIZE_HAMMING; + default: + return SkBitmapScaler::RESIZE_MITCHELL; + } +} + +// static +bool SkBitmapScaler::Resize(SkBitmap* resultPtr, + const SkBitmap& source, + ResizeMethod method, + int destWidth, int destHeight, + const SkIRect& destSubset, + const SkConvolutionProcs& convolveProcs, + SkBitmap::Allocator* allocator) { + // 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 }; + if (!dest.contains(destSubset)) { + SkErrorInternals::SetError( kInvalidArgument_SkError, + "Sorry, you passed me a bitmap resize " + " method I have never heard of: %d", + method ); + } + + // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just + // return empty. + if (source.width() < 1 || source.height() < 1 || + destWidth < 1 || destHeight < 1) { + // todo: seems like we could handle negative dstWidth/Height, since that + // is just a negative scale (flip) + return false; + } + + method = ResizeMethodToAlgorithmMethod(method); + + // Check that we deal with an "algorithm methods" from this point onward. + SkASSERT((SkBitmapScaler::RESIZE_FIRST_ALGORITHM_METHOD <= method) && + (method <= SkBitmapScaler::RESIZE_LAST_ALGORITHM_METHOD)); + + SkAutoLockPixels locker(source); + if (!source.readyToDraw() || + source.config() != SkBitmap::kARGB_8888_Config) { + return false; + } + + SkResizeFilter filter(method, source.width(), source.height(), + destWidth, destHeight, destSubset, convolveProcs); + + // Get a source bitmap encompassing this touched area. We construct the + // offsets and row strides such that it looks like a new bitmap, while + // referring to the old data. + const unsigned char* sourceSubset = + reinterpret_cast(source.getPixels()); + + // Convolve into the result. + SkBitmap result; + result.setConfig(SkBitmap::kARGB_8888_Config, + destSubset.width(), destSubset.height(), 0, + source.alphaType()); + result.allocPixels(allocator, NULL); + if (!result.readyToDraw()) { + return false; + } + + BGRAConvolve2D(sourceSubset, static_cast(source.rowBytes()), + !source.isOpaque(), filter.xFilter(), filter.yFilter(), + static_cast(result.rowBytes()), + static_cast(result.getPixels()), + convolveProcs, true); + + *resultPtr = result; + resultPtr->lockPixels(); + 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/gfx/skia/trunk/src/core/SkBitmapScaler.h b/gfx/skia/trunk/src/core/SkBitmapScaler.h new file mode 100644 index 000000000000..c8d8a84185e3 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkBitmapScaler.h @@ -0,0 +1,108 @@ +/* + * 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 SkBitmapScaler_DEFINED +#define SkBitmapScaler_DEFINED + +#include "SkBitmap.h" +#include "SkConvolver.h" + +/** \class SkBitmapScaler + + Provides the interface for high quality image resampling. + */ + +class SK_API SkBitmapScaler { +public: + enum ResizeMethod { + // Quality Methods + // + // Those enumeration values express a desired quality/speed tradeoff. + // They are translated into an algorithm-specific method that depends + // on the capabilities (CPU, GPU) of the underlying platform. + // It is possible for all three methods to be mapped to the same + // algorithm on a given platform. + + // Good quality resizing. Fastest resizing with acceptable visual quality. + // This is typically intended for use during interactive layouts + // where slower platforms may want to trade image quality for large + // increase in resizing performance. + // + // For example the resizing implementation may devolve to linear + // filtering if this enables GPU acceleration to be used. + // + // Note that the underlying resizing method may be determined + // on the fly based on the parameters for a given resize call. + // For example an implementation using a GPU-based linear filter + // in the common case may still use a higher-quality software-based + // filter in cases where using the GPU would actually be slower - due + // to too much latency - or impossible - due to image format or size + // constraints. + RESIZE_GOOD, + + // Medium quality resizing. Close to high quality resizing (better + // than linear interpolation) with potentially some quality being + // traded-off for additional speed compared to RESIZE_BEST. + // + // This is intended, for example, for generation of large thumbnails + // (hundreds of pixels in each dimension) from large sources, where + // a linear filter would produce too many artifacts but where + // a RESIZE_HIGH might be too costly time-wise. + RESIZE_BETTER, + + // High quality resizing. The algorithm is picked to favor image quality. + RESIZE_BEST, + + // + // Algorithm-specific enumerations + // + + // Box filter. This is a weighted average of all of the pixels touching + // the destination pixel. For enlargement, this is nearest neighbor. + // + // You probably don't want this, it is here for testing since it is easy to + // compute. Use RESIZE_LANCZOS3 instead. + RESIZE_BOX, + RESIZE_TRIANGLE, + RESIZE_LANCZOS3, + RESIZE_HAMMING, + RESIZE_MITCHELL, + + // enum aliases for first and last methods by algorithm or by quality. + RESIZE_FIRST_QUALITY_METHOD = RESIZE_GOOD, + RESIZE_LAST_QUALITY_METHOD = RESIZE_BEST, + RESIZE_FIRST_ALGORITHM_METHOD = RESIZE_BOX, + 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, + const SkConvolutionProcs&, + SkBitmap::Allocator* allocator = NULL); +}; + +#endif diff --git a/gfx/skia/src/core/SkBitmapShader16BilerpTemplate.h b/gfx/skia/trunk/src/core/SkBitmapShader16BilerpTemplate.h similarity index 100% rename from gfx/skia/src/core/SkBitmapShader16BilerpTemplate.h rename to gfx/skia/trunk/src/core/SkBitmapShader16BilerpTemplate.h diff --git a/gfx/skia/src/core/SkBitmapShaderTemplate.h b/gfx/skia/trunk/src/core/SkBitmapShaderTemplate.h similarity index 100% rename from gfx/skia/src/core/SkBitmapShaderTemplate.h rename to gfx/skia/trunk/src/core/SkBitmapShaderTemplate.h diff --git a/gfx/skia/src/core/SkBitmap_scroll.cpp b/gfx/skia/trunk/src/core/SkBitmap_scroll.cpp similarity index 100% rename from gfx/skia/src/core/SkBitmap_scroll.cpp rename to gfx/skia/trunk/src/core/SkBitmap_scroll.cpp diff --git a/gfx/skia/src/core/SkBlitBWMaskTemplate.h b/gfx/skia/trunk/src/core/SkBlitBWMaskTemplate.h similarity index 98% rename from gfx/skia/src/core/SkBlitBWMaskTemplate.h rename to gfx/skia/trunk/src/core/SkBlitBWMaskTemplate.h index 00d2326bfff8..798e44aaa49e 100644 --- a/gfx/skia/src/core/SkBlitBWMaskTemplate.h +++ b/gfx/skia/trunk/src/core/SkBlitBWMaskTemplate.h @@ -79,8 +79,6 @@ static void SK_BLITBWMASK_NAME(const SkBitmap& bitmap, const SkMask& srcMask, co // back up manually so we can keep in sync with our byte-aligned src // and not trigger an assert from the getAddr## function device -= left_edge & 7; - // have cx reflect our actual starting x-coord - cx -= left_edge & 7; if (full_runs < 0) { diff --git a/gfx/skia/src/core/SkBlitMask.h b/gfx/skia/trunk/src/core/SkBlitMask.h similarity index 100% rename from gfx/skia/src/core/SkBlitMask.h rename to gfx/skia/trunk/src/core/SkBlitMask.h diff --git a/gfx/skia/src/core/SkBlitMask_D32.cpp b/gfx/skia/trunk/src/core/SkBlitMask_D32.cpp similarity index 99% rename from gfx/skia/src/core/SkBlitMask_D32.cpp rename to gfx/skia/trunk/src/core/SkBlitMask_D32.cpp index 80cc787991ed..1f16d775b51e 100644 --- a/gfx/skia/src/core/SkBlitMask_D32.cpp +++ b/gfx/skia/trunk/src/core/SkBlitMask_D32.cpp @@ -383,13 +383,9 @@ static int upscale31To255(int value) { return value; } -static int mul(int a, int b) { - return a * b >> 8; -} - static int src_alpha_blend(int src, int dst, int srcA, int mask) { - return dst + mul(src - mul(srcA, dst), mask); + return dst + SkAlphaMul(src - SkAlphaMul(srcA, dst), mask); } static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst, diff --git a/gfx/skia/src/core/SkBlitRow_D16.cpp b/gfx/skia/trunk/src/core/SkBlitRow_D16.cpp similarity index 96% rename from gfx/skia/src/core/SkBlitRow_D16.cpp rename to gfx/skia/trunk/src/core/SkBlitRow_D16.cpp index 309e459c2e6a..e244723986a8 100644 --- a/gfx/skia/src/core/SkBlitRow_D16.cpp +++ b/gfx/skia/trunk/src/core/SkBlitRow_D16.cpp @@ -224,8 +224,6 @@ static const SkBlitRow::Proc gDefault_565_Procs[] = { S32A_D565_Blend_Dither }; -extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags); - SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) { SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); // just so we don't crash @@ -240,12 +238,6 @@ SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) { proc = gDefault_565_Procs[flags]; } break; - case SkBitmap::kARGB_4444_Config: - proc = PlatformProcs4444(flags); - if (NULL == proc) { - proc = SkBlitRow_Factory_4444(flags); - } - break; default: break; } diff --git a/gfx/skia/src/core/SkBlitRow_D32.cpp b/gfx/skia/trunk/src/core/SkBlitRow_D32.cpp similarity index 100% rename from gfx/skia/src/core/SkBlitRow_D32.cpp rename to gfx/skia/trunk/src/core/SkBlitRow_D32.cpp diff --git a/gfx/skia/src/core/SkBlitter.cpp b/gfx/skia/trunk/src/core/SkBlitter.cpp similarity index 97% rename from gfx/skia/src/core/SkBlitter.cpp rename to gfx/skia/trunk/src/core/SkBlitter.cpp index f43ad75a442b..31a3edea769a 100644 --- a/gfx/skia/src/core/SkBlitter.cpp +++ b/gfx/skia/trunk/src/core/SkBlitter.cpp @@ -12,7 +12,8 @@ #include "SkColor.h" #include "SkColorFilter.h" #include "SkFilterShader.h" -#include "SkFlattenableBuffers.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" #include "SkMask.h" #include "SkMaskFilter.h" #include "SkTemplatesPriv.h" @@ -682,13 +683,13 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) protected: - Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { - fProxy = buffer.readFlattenableT(); + Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) { + fProxy = buffer.readShader(); fPMColor = buffer.readColor(); fMask = NULL; } - 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); @@ -780,6 +781,7 @@ private: void* fObj; Proc fProc; }; +#define SkAutoCallProc(...) SK_REQUIRE_LOCAL_VAR(SkAutoCallProc) static void destroy_blitter(void* blitter) { ((SkBlitter*)blitter)->~SkBlitter(); @@ -850,14 +852,16 @@ 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) { + void* storage, size_t storageSize, + bool drawCoverage) { SkASSERT(storageSize == 0 || storage != 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.getConfig()) { + if (SkBitmap::kNo_Config == device.config() || + (drawCoverage && (SkBitmap::kA8_Config != device.config()))) { SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); return blitter; } @@ -940,14 +944,15 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, return blitter; } - switch (device.getConfig()) { - case SkBitmap::kA1_Config: - SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter, - storage, storageSize, (device, *paint)); - break; + switch (device.config()) { case SkBitmap::kA8_Config: - if (shader) { + if (drawCoverage) { + SkASSERT(NULL == shader); + SkASSERT(NULL == paint->getXfermode()); + SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Coverage_Blitter, + storage, storageSize, (device, *paint)); + } else if (shader) { SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, storage, storageSize, (device, *paint)); } else { @@ -956,10 +961,6 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, } break; - case SkBitmap::kARGB_4444_Config: - blitter = SkBlitter_ChooseD4444(device, *paint, storage, storageSize); - break; - case SkBitmap::kRGB_565_Config: blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize); break; diff --git a/gfx/skia/src/core/SkBlitter.h b/gfx/skia/trunk/src/core/SkBlitter.h similarity index 98% rename from gfx/skia/src/core/SkBlitter.h rename to gfx/skia/trunk/src/core/SkBlitter.h index 0a075f89adf2..b659fe473581 100644 --- a/gfx/skia/src/core/SkBlitter.h +++ b/gfx/skia/trunk/src/core/SkBlitter.h @@ -76,7 +76,8 @@ public: static SkBlitter* Choose(const SkBitmap& device, const SkMatrix& matrix, const SkPaint& paint, - void* storage, size_t storageSize); + void* storage, size_t storageSize, + bool drawCoverage = false); static SkBlitter* ChooseSprite(const SkBitmap& device, const SkPaint&, diff --git a/gfx/skia/src/core/SkBlitter_A8.cpp b/gfx/skia/trunk/src/core/SkBlitter_A8.cpp similarity index 81% rename from gfx/skia/src/core/SkBlitter_A8.cpp rename to gfx/skia/trunk/src/core/SkBlitter_A8.cpp index 02554643d26e..983a226e3460 100644 --- a/gfx/skia/src/core/SkBlitter_A8.cpp +++ b/gfx/skia/trunk/src/core/SkBlitter_A8.cpp @@ -336,6 +336,10 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { fShader->shadeSpan(x, y, span, width); if (fXfermode) { fXfermode->xferA8(device, span, width, alpha); + } else { + for (int i = width - 1; i >= 0; --i) { + device[i] = aa_blend8(span[i], device[i], alpha[i]); + } } y += 1; @@ -343,3 +347,85 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { alpha += mask.fRowBytes; } } + +/////////////////////////////////////////////////////////////////////////////// + +SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkBitmap& device, + const SkPaint& paint) : SkRasterBlitter(device) { + SkASSERT(NULL == paint.getShader()); + SkASSERT(NULL == paint.getXfermode()); + SkASSERT(NULL == paint.getColorFilter()); +} + +void SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], + const int16_t runs[]) { + uint8_t* device = fDevice.getAddr8(x, y); + SkDEBUGCODE(int totalCount = 0;) + + for (;;) { + int count = runs[0]; + SkASSERT(count >= 0); + if (count == 0) { + return; + } + if (antialias[0]) { + memset(device, antialias[0], count); + } + runs += count; + antialias += count; + device += count; + + SkDEBUGCODE(totalCount += count;) + } + SkASSERT(fDevice.width() == totalCount); +} + +void SkA8_Coverage_Blitter::blitH(int x, int y, int width) { + memset(fDevice.getAddr8(x, y), 0xFF, width); +} + +void SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { + if (0 == alpha) { + return; + } + + uint8_t* dst = fDevice.getAddr8(x, y); + const size_t dstRB = fDevice.rowBytes(); + while (--height >= 0) { + *dst = alpha; + dst += dstRB; + } +} + +void SkA8_Coverage_Blitter::blitRect(int x, int y, int width, int height) { + uint8_t* dst = fDevice.getAddr8(x, y); + const size_t dstRB = fDevice.rowBytes(); + while (--height >= 0) { + memset(dst, 0xFF, width); + dst += dstRB; + } +} + +void SkA8_Coverage_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { + SkASSERT(SkMask::kA8_Format == mask.fFormat); + + int x = clip.fLeft; + int y = clip.fTop; + int width = clip.width(); + int height = clip.height(); + + uint8_t* dst = fDevice.getAddr8(x, y); + const uint8_t* src = mask.getAddr8(x, y); + const size_t srcRB = mask.fRowBytes; + const size_t dstRB = fDevice.rowBytes(); + + while (--height >= 0) { + memcpy(dst, src, width); + dst += dstRB; + src += srcRB; + } +} + +const SkBitmap* SkA8_Coverage_Blitter::justAnOpaqueColor(uint32_t*) { + return NULL; +} diff --git a/gfx/skia/src/core/SkBlitter_ARGB32.cpp b/gfx/skia/trunk/src/core/SkBlitter_ARGB32.cpp similarity index 100% rename from gfx/skia/src/core/SkBlitter_ARGB32.cpp rename to gfx/skia/trunk/src/core/SkBlitter_ARGB32.cpp diff --git a/gfx/skia/src/core/SkBlitter_RGB16.cpp b/gfx/skia/trunk/src/core/SkBlitter_RGB16.cpp similarity index 93% rename from gfx/skia/src/core/SkBlitter_RGB16.cpp rename to gfx/skia/trunk/src/core/SkBlitter_RGB16.cpp index 615a6a39dbe8..256cbc6936f6 100644 --- a/gfx/skia/src/core/SkBlitter_RGB16.cpp +++ b/gfx/skia/trunk/src/core/SkBlitter_RGB16.cpp @@ -390,63 +390,53 @@ void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask, do { int w = width; if (w >= UNROLL) { - uint32x4_t color; /* can use same one */ - uint32x4_t dev_lo, dev_hi; - uint32x4_t t1; - uint32x4_t wn1, wn2; - uint16x4_t odev_lo, odev_hi; - uint16x4_t alpha_lo, alpha_hi; - uint16x8_t alpha_full; + uint32x4_t color, dev_lo, dev_hi; + uint32x4_t wn1, wn2, tmp; + uint32x4_t vmask_g16, vmask_ng16; + uint16x8_t valpha, vdev; + uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi; + // prepare constants + vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE); + vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE); color = vdupq_n_u32(expanded32); do { - /* alpha is 8x8, widen and split to get pair of 16x4's */ - alpha_full = vmovl_u8(vld1_u8(alpha)); - alpha_full = vaddq_u16(alpha_full, vshrq_n_u16(alpha_full,7)); - alpha_full = vshrq_n_u16(alpha_full, 3); - alpha_lo = vget_low_u16(alpha_full); - alpha_hi = vget_high_u16(alpha_full); + // alpha is 8x8, widen and split to get a pair of 16x4 + valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha)); + valpha = vshrq_n_u16(valpha, 3); + valpha_lo = vget_low_u16(valpha); + valpha_hi = vget_high_u16(valpha); - dev_lo = vmovl_u16(vld1_u16(device)); - dev_hi = vmovl_u16(vld1_u16(device+4)); + // load pixels + vdev = vld1q_u16(device); + dev_lo = vmovl_u16(vget_low_u16(vdev)); + dev_hi = vmovl_u16(vget_high_u16(vdev)); - /* unpack in 32 bits */ - dev_lo = vorrq_u32( - vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)), - vshlq_n_u32(vandq_u32(dev_lo, - vdupq_n_u32(0x000007E0)), - 16) - ); - dev_hi = vorrq_u32( - vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)), - vshlq_n_u32(vandq_u32(dev_hi, - vdupq_n_u32(0x000007E0)), - 16) - ); + // unpack them in 32 bits + dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16); + dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16); - /* blend the two */ - t1 = vmulq_u32(vsubq_u32(color, dev_lo), vmovl_u16(alpha_lo)); - t1 = vshrq_n_u32(t1, 5); - dev_lo = vaddq_u32(dev_lo, t1); + // blend with color + tmp = (color - dev_lo) * vmovl_u16(valpha_lo); + tmp = vshrq_n_u32(tmp, 5); + dev_lo += tmp; - t1 = vmulq_u32(vsubq_u32(color, dev_hi), vmovl_u16(alpha_hi)); - t1 = vshrq_n_u32(t1, 5); - dev_hi = vaddq_u32(dev_hi, t1); + tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi)); + tmp = vshrq_n_u32(tmp, 5); + dev_hi += tmp; - /* re-compact and store */ - wn1 = vandq_u32(dev_lo, vdupq_n_u32(0x0000F81F)), - wn2 = vshrq_n_u32(dev_lo, 16); - wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0)); - odev_lo = vmovn_u32(vorrq_u32(wn1, wn2)); + // re-compact + wn1 = dev_lo & vmask_ng16; + wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16; + odev_lo = vmovn_u32(wn1 | wn2); - wn1 = vandq_u32(dev_hi, vdupq_n_u32(0x0000F81F)), - wn2 = vshrq_n_u32(dev_hi, 16); - wn2 = vandq_u32(wn2, vdupq_n_u32(0x000007E0)); - odev_hi = vmovn_u32(vorrq_u32(wn1, wn2)); + wn1 = dev_hi & vmask_ng16; + wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16; + odev_hi = vmovn_u32(wn1 | wn2); - vst1_u16(device, odev_lo); - vst1_u16(device+4, odev_hi); + // store + vst1q_u16(device, vcombine_u16(odev_lo, odev_hi)); device += UNROLL; alpha += UNROLL; @@ -454,7 +444,7 @@ void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask, } while (w >= UNROLL); } - /* residuals (which is everything if we have no neon) */ + // residuals while (w > 0) { *device = blend_compact(expanded32, SkExpand_rgb_16(*device), SkAlpha255To256(*alpha++) >> 3); @@ -826,7 +816,7 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, // shaders take care of global alpha, so we never set it in SkBlitRow if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { flags |= SkBlitRow::kSrcPixelAlpha_Flag; - } + } // don't dither if the shader is really 16bit if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) { flags |= SkBlitRow::kDither_Flag; diff --git a/gfx/skia/src/core/SkBlitter_Sprite.cpp b/gfx/skia/trunk/src/core/SkBlitter_Sprite.cpp similarity index 98% rename from gfx/skia/src/core/SkBlitter_Sprite.cpp rename to gfx/skia/trunk/src/core/SkBlitter_Sprite.cpp index db7cc69a7818..9322e2039673 100644 --- a/gfx/skia/src/core/SkBlitter_Sprite.cpp +++ b/gfx/skia/trunk/src/core/SkBlitter_Sprite.cpp @@ -66,7 +66,7 @@ SkBlitter* SkBlitter::ChooseSprite( const SkBitmap& device, SkSpriteBlitter* blitter; - switch (device.getConfig()) { + switch (device.config()) { case SkBitmap::kRGB_565_Config: blitter = SkSpriteBlitter::ChooseD16(source, paint, storage, storageSize); diff --git a/gfx/skia/src/core/SkBuffer.cpp b/gfx/skia/trunk/src/core/SkBuffer.cpp similarity index 93% rename from gfx/skia/src/core/SkBuffer.cpp rename to gfx/skia/trunk/src/core/SkBuffer.cpp index 915264d957f0..590b05b85982 100644 --- a/gfx/skia/src/core/SkBuffer.cpp +++ b/gfx/skia/trunk/src/core/SkBuffer.cpp @@ -34,6 +34,14 @@ size_t SkRBuffer::skipToAlign4() return n; } +bool SkRBufferWithSizeCheck::read(void* buffer, size_t size) { + fError = fError || (fPos + size > fStop); + if (!fError && (size > 0)) { + readNoSizeCheck(buffer, size); + } + return !fError; +} + void* SkWBuffer::skip(size_t size) { void* result = fPos; diff --git a/gfx/skia/src/core/SkBuffer.h b/gfx/skia/trunk/src/core/SkBuffer.h similarity index 72% rename from gfx/skia/src/core/SkBuffer.h rename to gfx/skia/trunk/src/core/SkBuffer.h index 96333899078d..9791cf55a14a 100644 --- a/gfx/skia/src/core/SkBuffer.h +++ b/gfx/skia/trunk/src/core/SkBuffer.h @@ -39,6 +39,8 @@ public: fStop = (const char*)data + size; } + virtual ~SkRBuffer() { } + /** Return the number of bytes that have been read from the beginning of the data pointer. */ @@ -56,25 +58,33 @@ public: /** Read the specified number of bytes from the data pointer. If buffer is not null, copy those bytes into buffer. */ - void read(void* buffer, size_t size) { + virtual bool read(void* buffer, size_t size) { if (size) { this->readNoSizeCheck(buffer, size); } + return true; } const void* skip(size_t size); // return start of skipped data size_t skipToAlign4(); - void* readPtr() { void* ptr; read(&ptr, sizeof(ptr)); return ptr; } - SkScalar readScalar() { SkScalar x; read(&x, 4); return x; } - uint32_t readU32() { uint32_t x; read(&x, 4); return x; } - int32_t readS32() { int32_t x; read(&x, 4); return x; } - uint16_t readU16() { uint16_t x; read(&x, 2); return x; } - int16_t readS16() { int16_t x; read(&x, 2); return x; } - uint8_t readU8() { uint8_t x; read(&x, 1); return x; } - bool readBool() { return this->readU8() != 0; } + bool readPtr(void** ptr) { return read(ptr, sizeof(void*)); } + bool readScalar(SkScalar* x) { return read(x, 4); } + bool readU32(uint32_t* x) { return read(x, 4); } + bool readS32(int32_t* x) { return read(x, 4); } + bool readU16(uint16_t* x) { return read(x, 2); } + bool readS16(int16_t* x) { return read(x, 2); } + bool readU8(uint8_t* x) { return read(x, 1); } + bool readBool(bool* x) { + uint8_t u8; + if (this->readU8(&u8)) { + *x = (u8 != 0); + return true; + } + return false; + } -private: +protected: void readNoSizeCheck(void* buffer, size_t size); const char* fData; @@ -82,6 +92,28 @@ private: const char* fStop; }; +/** \class SkRBufferWithSizeCheck + + Same as SkRBuffer, except that a size check is performed before the read operation and an + error is set if the read operation is attempting to read past the end of the data. +*/ +class SkRBufferWithSizeCheck : public SkRBuffer { +public: + SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {} + + /** Read the specified number of bytes from the data pointer. If buffer is not + null and the number of bytes to read does not overflow this object's data, + copy those bytes into buffer. + */ + virtual bool read(void* buffer, size_t size) SK_OVERRIDE; + + /** Returns whether or not a read operation attempted to read past the end of the data. + */ + bool isValid() const { return !fError; } +private: + bool fError; +}; + /** \class SkWBuffer Light weight class for writing data to a memory block. diff --git a/gfx/skia/src/core/SkCanvas.cpp b/gfx/skia/trunk/src/core/SkCanvas.cpp similarity index 79% rename from gfx/skia/src/core/SkCanvas.cpp rename to gfx/skia/trunk/src/core/SkCanvas.cpp index 5b2e381aa640..ed8274dc5d3b 100644 --- a/gfx/skia/src/core/SkCanvas.cpp +++ b/gfx/skia/trunk/src/core/SkCanvas.cpp @@ -8,26 +8,26 @@ #include "SkCanvas.h" +#include "SkBitmapDevice.h" #include "SkBounder.h" -#include "SkDevice.h" #include "SkDeviceImageFilterProxy.h" #include "SkDraw.h" #include "SkDrawFilter.h" #include "SkDrawLooper.h" #include "SkMetaData.h" +#include "SkPathOps.h" #include "SkPicture.h" #include "SkRasterClip.h" #include "SkRRect.h" -#include "SkScalarCompare.h" #include "SkSurface_Base.h" #include "SkTemplates.h" #include "SkTextFormatParams.h" #include "SkTLazy.h" #include "SkUtils.h" -SK_DEFINE_INST_COUNT(SkBounder) -SK_DEFINE_INST_COUNT(SkCanvas) -SK_DEFINE_INST_COUNT(SkDrawFilter) +#if SK_SUPPORT_GPU +#include "GrRenderTarget.h" +#endif // experimental for faster tiled drawing... //#define SK_ENABLE_CLIP_QUICKREJECT @@ -122,13 +122,13 @@ typedef SkTLazy SkLazyPaint; void SkCanvas::predrawNotify() { if (fSurfaceBase) { - fSurfaceBase->aboutToDraw(this); + fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); } } /////////////////////////////////////////////////////////////////////////////// -/* This is the record we keep for each SkDevice that the user installs. +/* This is the record we keep for each SkBaseDevice that the user installs. The clip/matrix/proc are fields that reflect the top of the save/restore stack. Whenever the canvas changes, it marks a dirty flag, and then before these are used (assuming we're not on a layer) we rebuild these cache @@ -137,12 +137,12 @@ void SkCanvas::predrawNotify() { */ struct DeviceCM { DeviceCM* fNext; - SkDevice* fDevice; + SkBaseDevice* fDevice; SkRasterClip fClip; const SkMatrix* fMatrix; SkPaint* fPaint; // may be null (in the future) - DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) + DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas) : fNext(NULL) { if (NULL != device) { device->ref(); @@ -213,6 +213,7 @@ 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 SkDrawFilter* fFilter; // the current filter (or null) @@ -226,7 +227,7 @@ public: */ DeviceCM* fTopLayer; - MCRec(const MCRec* prev, int flags) { + MCRec(const MCRec* prev, int flags) : fFlags(flags) { if (NULL != prev) { if (flags & SkCanvas::kMatrix_SaveFlag) { fMatrixStorage = *prev->fMatrix; @@ -313,7 +314,7 @@ public: return false; } - SkDevice* getDevice() const { return fDevice; } + SkBaseDevice* getDevice() const { return fDevice; } int getX() const { return fDevice->getOrigin().x(); } int getY() const { return fDevice->getOrigin().y(); } const SkMatrix& getMatrix() const { return *fMatrix; } @@ -334,7 +335,8 @@ 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(); @@ -346,8 +348,7 @@ 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, + (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, true); // we'll clear the imageFilter for the actual draws in next(), so // it will only be applied during the restore(). @@ -457,44 +458,22 @@ public: private: SkBounder* fBounder; }; +#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit) #include "SkColorPriv.h" -class AutoValidator { -public: - AutoValidator(SkDevice* device) : fDevice(device) {} - ~AutoValidator() { -#ifdef SK_DEBUG - const SkBitmap& bm = fDevice->accessBitmap(false); - if (bm.config() == SkBitmap::kARGB_4444_Config) { - for (int y = 0; y < bm.height(); y++) { - const SkPMColor16* p = bm.getAddr16(0, y); - for (int x = 0; x < bm.width(); x++) { - SkPMColor16 c = p[x]; - SkPMColor16Assert(c); - } - } - } -#endif - } -private: - SkDevice* fDevice; -}; - ////////// macros to place around the internal draw calls ////////////////// #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ -/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ this->predrawNotify(); \ AutoDrawLooper looper(this, paint, true); \ while (looper.next(type)) { \ SkAutoBounderCommit ac(fBounder); \ SkDrawIter iter(this); -#define LOOPER_BEGIN(paint, type) \ -/* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ +#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); @@ -503,11 +482,12 @@ private: //////////////////////////////////////////////////////////////////////////// -SkDevice* SkCanvas::init(SkDevice* device) { +SkBaseDevice* SkCanvas::init(SkBaseDevice* device) { fBounder = NULL; - fLocalBoundsCompareType.setEmpty(); - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBounds.setEmpty(); + fCachedLocalClipBoundsDirty = true; fAllowSoftClip = true; + fAllowSimplifyClip = false; fDeviceCMDirty = false; fSaveLayerCount = 0; fMetaData = NULL; @@ -525,24 +505,37 @@ SkDevice* SkCanvas::init(SkDevice* device) { } SkCanvas::SkCanvas() -: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { + : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) +{ inc_canvas(); this->init(NULL); } -SkCanvas::SkCanvas(SkDevice* device) - : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { +SkCanvas::SkCanvas(int width, int height) + : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) +{ + inc_canvas(); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kNo_Config, width, height); + this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); +} + +SkCanvas::SkCanvas(SkBaseDevice* device) + : 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(SkDevice, (bitmap)))->unref(); + this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); } SkCanvas::~SkCanvas() { @@ -584,37 +577,37 @@ SkMetaData& SkCanvas::getMetaData() { /////////////////////////////////////////////////////////////////////////////// void SkCanvas::flush() { - SkDevice* device = this->getDevice(); + SkBaseDevice* device = this->getDevice(); if (device) { device->flush(); } } SkISize SkCanvas::getDeviceSize() const { - SkDevice* d = this->getDevice(); + SkBaseDevice* d = this->getDevice(); return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); } -SkDevice* SkCanvas::getDevice() const { +SkBaseDevice* SkCanvas::getDevice() const { // return root device MCRec* rec = (MCRec*) fMCStack.front(); SkASSERT(rec && rec->fLayer); return rec->fLayer->fDevice; } -SkDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { +SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { if (updateMatrixClip) { const_cast(this)->updateDeviceCMCache(); } return fMCRec->fTopLayer->fDevice; } -SkDevice* SkCanvas::setDevice(SkDevice* device) { +SkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) { // return root device SkDeque::F2BIter iter(fMCStack); MCRec* rec = (MCRec*)iter.next(); SkASSERT(rec && rec->fLayer); - SkDevice* rootDevice = rec->fLayer->fDevice; + SkBaseDevice* rootDevice = rec->fLayer->fDevice; if (rootDevice == device) { return device; @@ -664,7 +657,7 @@ SkDevice* SkCanvas::setDevice(SkDevice* device) { bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y, Config8888 config8888) { - SkDevice* device = this->getDevice(); + SkBaseDevice* device = this->getDevice(); if (!device) { return false; } @@ -672,7 +665,7 @@ bool SkCanvas::readPixels(SkBitmap* bitmap, } bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { - SkDevice* device = this->getDevice(); + SkBaseDevice* device = this->getDevice(); if (!device) { return false; } @@ -696,7 +689,7 @@ bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, Config8888 config8888) { - SkDevice* device = this->getDevice(); + SkBaseDevice* device = this->getDevice(); if (device) { if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()), SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) { @@ -741,8 +734,9 @@ int SkCanvas::internalSave(SaveFlags flags) { newTop->fNext = fMCRec; fMCRec = newTop; - fClipStack.save(); - SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); + if (SkCanvas::kClip_SaveFlag & flags) { + fClipStack.save(); + } return saveCount; } @@ -767,7 +761,7 @@ static SkBitmap::Config resolve_config(SkCanvas* canvas, uint32_t configMask = 0; for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) { - SkDevice* device = canvas->getLayerDevice(i); + SkBaseDevice* device = canvas->getLayerDevice(i); if (device->intersects(bounds)) configMask |= 1 << device->config(); } @@ -797,11 +791,18 @@ static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { } 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; @@ -819,11 +820,11 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, ir = clipBounds; } - fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); + fClipStack.clipDevRect(ir, op); // early exit if the clip is now empty if (bounds_affects_clip(flags) && - !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) { + !fMCRec->fRasterClip->op(ir, op)) { return false; } @@ -838,6 +839,18 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, return this->internalSaveLayer(bounds, paint, flags, false); } +static SkBaseDevice* createCompatibleDevice(SkCanvas* canvas, + SkBitmap::Config config, + int width, int height, + bool isOpaque) { + SkBaseDevice* device = canvas->getDevice(); + if (device) { + return device->createCompatibleDevice(config, width, height, isOpaque); + } else { + return NULL; + } +} + int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, bool justForImageFilter) { // do this before we create the layer. We don't call the public save() since @@ -847,7 +860,7 @@ 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; } @@ -868,10 +881,10 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, bool isOpaque; SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); - SkDevice* device; + SkBaseDevice* device; if (paint && paint->getImageFilter()) { - device = this->createCompatibleDevice(config, ir.width(), ir.height(), - isOpaque); + device = createCompatibleDevice(this, config, ir.width(), ir.height(), + isOpaque); } else { device = this->createLayerDevice(config, ir.width(), ir.height(), isOpaque); @@ -915,9 +928,12 @@ void SkCanvas::internalRestore() { SkASSERT(fMCStack.count() != 0); fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; + + if (SkCanvas::kClip_SaveFlag & fMCRec->fFlags) { + fClipStack.restore(); + } - fClipStack.restore(); // reserve our layer (if any) DeviceCM* layer = fMCRec->fLayer; // may be null // now detach it from fMCRec so we can pop(). Gets freed after its drawn @@ -945,8 +961,6 @@ void SkCanvas::internalRestore() { } SkDELETE(layer); } - - SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); } int SkCanvas::getSaveCount() const { @@ -969,20 +983,20 @@ bool SkCanvas::isDrawingToLayer() const { return fSaveLayerCount > 0; } -///////////////////////////////////////////////////////////////////////////// - -// 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 -#ifndef SK_ALLOW_OVER_32K_BITMAPS - || bitmap.width() > 32767 || bitmap.height() > 32767 -#endif - ; +SkSurface* SkCanvas::newSurface(const SkImageInfo& info) { + return this->onNewSurface(info); } -void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, +SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) { + SkBaseDevice* dev = this->getDevice(); + return dev ? dev->newSurface(info) : NULL; +} + +///////////////////////////////////////////////////////////////////////////// + +void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { - if (reject_bitmap(bitmap)) { + if (bitmap.drawsNothing()) { return; } @@ -990,10 +1004,28 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect if (NULL == paint) { paint = lazy.init(); } - this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); + + SkDEBUGCODE(bitmap.validate();) + CHECK_LOCKCOUNT_BALANCE(bitmap); + + 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()); + } + + LOOPER_END } -void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y, +void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) { SkPaint tmp; if (NULL == paint) { @@ -1003,18 +1035,22 @@ void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y, LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { - SkDevice* dstDev = iter.fDevice; + SkBaseDevice* dstDev = iter.fDevice; paint = &looper.paint(); SkImageFilter* filter = paint->getImageFilter(); SkIPoint pos = { x - iter.getX(), y - iter.getY() }; if (filter && !dstDev->canHandleImageFilter(filter)) { SkDeviceImageFilterProxy proxy(dstDev); SkBitmap dst; + SkIPoint offset = SkIPoint::Make(0, 0); const SkBitmap& src = srcDev->accessBitmap(false); - if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) { + SkMatrix matrix = *iter.fMatrix; + matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); + if (filter->filterImage(&proxy, src, matrix, &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); @@ -1025,12 +1061,11 @@ void SkCanvas::internalDrawDevice(SkDevice* 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) { @@ -1046,11 +1081,13 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, if (filter && !iter.fDevice->canHandleImageFilter(filter)) { SkDeviceImageFilterProxy proxy(iter.fDevice); SkBitmap dst; - if (filter->filterImage(&proxy, bitmap, *iter.fMatrix, - &dst, &pos)) { + SkIPoint offset = SkIPoint::Make(0, 0); + SkMatrix matrix = *iter.fMatrix; + matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); + if (filter->filterImage(&proxy, bitmap, matrix, &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 { @@ -1064,37 +1101,37 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, bool SkCanvas::translate(SkScalar dx, SkScalar dy) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; return fMCRec->fMatrix->preTranslate(dx, dy); } bool SkCanvas::scale(SkScalar sx, SkScalar sy) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; return fMCRec->fMatrix->preScale(sx, sy); } bool SkCanvas::rotate(SkScalar degrees) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; return fMCRec->fMatrix->preRotate(degrees); } bool SkCanvas::skew(SkScalar sx, SkScalar sy) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; return fMCRec->fMatrix->preSkew(sx, sy); } bool SkCanvas::concat(const SkMatrix& matrix) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; return fMCRec->fMatrix->preConcat(matrix); } void SkCanvas::setMatrix(const SkMatrix& matrix) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; *fMCRec->fMatrix = matrix; } @@ -1118,7 +1155,7 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { if (this->quickReject(rect)) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; fClipStack.clipEmpty(); return fMCRec->fRasterClip->setEmpty(); @@ -1129,11 +1166,11 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { AutoValidateClip avc(this); fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; doAA &= fAllowSoftClip; if (fMCRec->fMatrix->rectStaysRect()) { - // for these simpler matrices, we can stay a rect ever after applying + // for these simpler matrices, we can stay a rect even after applying // the matrix. This means we don't have to a) make a path, and b) tell // the region code to scan-convert the path, only to discover that it // is really just a rect. @@ -1143,7 +1180,7 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { fClipStack.clipDevRect(r, op, doAA); return fMCRec->fRasterClip->op(r, op, doAA); } else { - // since we're rotate or some such thing, we convert the rect to a path + // 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 // avoid recursion in the case where we are subclassed (e.g. Pictures) // we explicitly call "our" version of clipPath. @@ -1165,7 +1202,10 @@ static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, // bounds, than just using the device. However, if currRgn is complex, // our region blitter may hork, so we do that case in two steps. if (currClip->isRect()) { - return currClip->setPath(devPath, *currClip, doAA); + // 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); } else { base.setRect(currClip->getBounds()); SkRasterClip clip; @@ -1173,7 +1213,7 @@ static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, return currClip->op(clip, op); } } else { - const SkDevice* device = canvas->getDevice(); + const SkBaseDevice* device = canvas->getDevice(); if (!device) { return currClip->setEmpty(); } @@ -1211,7 +1251,7 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { if (this->quickReject(path.getBounds())) { fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; fClipStack.clipEmpty(); return fMCRec->fRasterClip->setEmpty(); @@ -1222,7 +1262,7 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { AutoValidateClip avc(this); fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; doAA &= fAllowSoftClip; SkPath devPath; @@ -1241,14 +1281,121 @@ 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); + if (fAllowSimplifyClip) { + devPath.reset(); + devPath.setFillType(SkPath::kInverseEvenOdd_FillType); + const SkClipStack* clipStack = getClipStack(); + SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart); + 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."); + } + SkRegion::Op elementOp = element->getOp(); + if (elementOp == SkRegion::kReplace_Op) { + devPath = operand; + } else { + Op(devPath, operand, (SkPathOp) elementOp, &devPath); + } + // 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(); + } + op = SkRegion::kReplace_Op; + } + return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); } +bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op, + bool inverseFilled) { + // This is for updating the clip conservatively using only bounds + // information. + // Contract: + // The current clip must contain the true clip. The true + // clip is the clip that would have normally been computed + // by calls to clipPath and clipRRect + // Objective: + // Keep the current clip as small as possible without + // breaking the contract, using only clip bounding rectangles + // (for performance). + + // N.B.: This *never* calls back through a virtual on canvas, so subclasses + // don't have to worry about getting caught in a loop. Thus anywhere + // we call a virtual method, we explicitly prefix it with + // SkCanvas:: to be sure to call the base-class. + + if (inverseFilled) { + switch (op) { + 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); + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + case SkRegion::kReverseDifference_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. + SkRect deviceBounds; + SkIRect deviceIBounds; + this->getDevice()->getGlobalBounds(&deviceIBounds); + deviceBounds = SkRect::Make(deviceIBounds); + this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag); + // set the clip in device space + 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; + } + default: + SkASSERT(0); // unhandled op? + } + } else { + // Not inverse filled + switch (op) { + case SkRegion::kIntersect_Op: + case SkRegion::kUnion_Op: + case SkRegion::kReplace_Op: + return this->SkCanvas::clipRect(bounds, op, false); + case SkRegion::kDifference_Op: + // Difference can only shrink the current clip. + // Leaving clip unchanged conservatively fullfills the contract. + return this->getClipDeviceBounds(NULL); + 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); + 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); + default: + SkASSERT(0); // unhandled op? + } + } + return true; +} + bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { AutoValidateClip avc(this); fDeviceCMDirty = true; - fLocalBoundsCompareTypeDirty = true; + fCachedLocalClipBoundsDirty = true; // todo: signal fClipStack that we have a region, and therefore (I guess) // we have to ignore it, and use the region directly? @@ -1260,7 +1407,7 @@ bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { #ifdef SK_DEBUG void SkCanvas::validateClip() const { // construct clipRgn from the clipstack - const SkDevice* device = this->getDevice(); + const SkBaseDevice* device = this->getDevice(); if (!device) { SkASSERT(this->getTotalClip().isEmpty()); return; @@ -1321,19 +1468,6 @@ void SkCanvas::replayClips(ClipVisitor* visitor) const { /////////////////////////////////////////////////////////////////////////////// -void SkCanvas::computeLocalClipBoundsCompareType() const { - SkRect r; - - if (!this->getClipBounds(&r)) { - fLocalBoundsCompareType.setEmpty(); - } else { - fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft), - SkScalarToCompareType(r.fTop), - SkScalarToCompareType(r.fRight), - SkScalarToCompareType(r.fBottom)); - } -} - bool SkCanvas::quickReject(const SkRect& rect) const { if (!rect.isFinite()) @@ -1350,17 +1484,14 @@ bool SkCanvas::quickReject(const SkRect& rect) const { dst.roundOut(&idst); return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); } else { - const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); + const SkRect& clipR = this->getLocalClipBounds(); // for speed, do the most likely reject compares first - SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); - SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); - if (userT >= clipR.fBottom || userB <= clipR.fTop) { + // TODO: should we use | instead, or compare all 4 at once? + if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { return true; } - SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); - SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); - if (userL >= clipR.fRight || userR <= clipR.fLeft) { + if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { return true; } return false; @@ -1371,17 +1502,6 @@ 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)) { @@ -1402,15 +1522,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; @@ -1445,10 +1558,10 @@ const SkRegion& SkCanvas::getTotalClip() const { return fMCRec->fRasterClip->forceGetBW(); } -SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque) { - SkDevice* device = this->getTopDevice(); +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); @@ -1457,17 +1570,20 @@ SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, } } -SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque) { - SkDevice* device = this->getDevice(); - if (device) { - return device->createCompatibleDevice(config, width, height, isOpaque); - } else { - return NULL; +GrContext* SkCanvas::getGrContext() { +#if SK_SUPPORT_GPU + SkBaseDevice* device = this->getTopDevice(); + if (NULL != device) { + GrRenderTarget* renderTarget = device->accessRenderTarget(); + if (NULL != renderTarget) { + return renderTarget->getContext(); + } } -} +#endif + return NULL; + +} ////////////////////////////////////////////////////////////////////////////// // These are the virtual drawing methods @@ -1488,7 +1604,7 @@ void SkCanvas::drawPaint(const SkPaint& 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()); @@ -1505,23 +1621,24 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 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()); @@ -1533,14 +1650,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()); @@ -1552,14 +1671,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()); @@ -1571,9 +1692,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; } } @@ -1581,12 +1704,20 @@ void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { if (rrect.isRect()) { // call the non-virtual version this->SkCanvas::drawRect(rrect.getBounds(), paint); - } else { - SkPath path; - path.addRRect(rrect); + return; + } else if (rrect.isOval()) { // call the non-virtual version - this->SkCanvas::drawPath(path, paint); + this->SkCanvas::drawOval(rrect.getBounds(), paint); + return; } + + LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) + + while (iter.next()) { + iter.fDevice->drawRRect(iter, rrect, looper.paint()); + } + + LOOPER_END } @@ -1597,10 +1728,12 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 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; } } @@ -1611,7 +1744,7 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& 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()); @@ -1640,21 +1773,22 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, SkMatrix matrix; matrix.setTranslate(x, y); - this->internalDrawBitmap(bitmap, NULL, matrix, paint); + this->internalDrawBitmap(bitmap, matrix, paint); } // this one is non-virtual, so it can be called safely by other canvas apis void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) { - if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) { + 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); } @@ -1668,44 +1802,34 @@ 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()); + iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); } LOOPER_END } void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, - const SkRect& dst, const SkPaint* paint) { + const SkRect& dst, const SkPaint* paint, + DrawBitmapRectFlags flags) { SkDEBUGCODE(bitmap.validate();) - this->internalDrawBitmapRect(bitmap, src, dst, paint); + this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); } void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkDEBUGCODE(bitmap.validate();) - this->internalDrawBitmap(bitmap, NULL, matrix, paint); -} - -void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, - const SkMatrix& matrix, const SkPaint& paint) { - SkDEBUGCODE(bitmap.validate();) - CHECK_LOCKCOUNT_BALANCE(bitmap); - - LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) - - while (iter.next()) { - iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); - } - - LOOPER_END + this->internalDrawBitmap(bitmap, matrix, paint); } 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; @@ -1764,7 +1888,8 @@ void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, s.fRight = srcX[x+1]; d.fLeft = dstX[x]; d.fRight = dstX[x+1]; - this->internalDrawBitmapRect(bitmap, &s, d, paint); + this->internalDrawBitmapRect(bitmap, &s, d, paint, + kNone_DrawBitmapRectFlag); } } } @@ -1779,8 +1904,8 @@ void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, class SkDeviceFilteredPaint { public: - SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { - SkDevice::TextFlags flags; + SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { + SkBaseDevice::TextFlags flags; if (device->filterTextFlags(paint, &flags)) { SkPaint* newPaint = fLazy.set(paint); newPaint->setFlags(flags.fFlags); @@ -1874,7 +1999,7 @@ 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) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); @@ -1890,7 +2015,7 @@ 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) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); @@ -1906,7 +2031,7 @@ void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkPaint& paint) { CHECK_SHADER_NOSETCONTEXT(paint); - LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); @@ -1922,7 +2047,7 @@ void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPaint& paint) { CHECK_SHADER_NOSETCONTEXT(paint); - LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) while (iter.next()) { iter.fDevice->drawTextOnPath(iter, text, byteLength, path, @@ -1932,23 +2057,6 @@ void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, LOOPER_END } -#ifdef SK_BUILD_FOR_ANDROID -void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix) { - CHECK_SHADER_NOSETCONTEXT(paint); - - LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) - - while (iter.next()) { - iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, - looper.paint(), path, matrix); - } - - LOOPER_END -} -#endif - void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint verts[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, @@ -1956,7 +2064,7 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 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, @@ -1967,10 +2075,6 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, LOOPER_END } -void SkCanvas::drawData(const void* data, size_t length) { - // do nothing. Subclasses may do something with the data -} - ////////////////////////////////////////////////////////////////////////////// // These methods are NOT virtual, and therefore must call back into virtual // methods, rather than actually drawing themselves. @@ -2112,7 +2216,7 @@ void SkCanvas::LayerIter::next() { fDone = !fImpl->next(); } -SkDevice* SkCanvas::LayerIter::device() const { +SkBaseDevice* SkCanvas::LayerIter::device() const { return fImpl->getDevice(); } diff --git a/gfx/skia/src/core/SkChunkAlloc.cpp b/gfx/skia/trunk/src/core/SkChunkAlloc.cpp similarity index 98% rename from gfx/skia/src/core/SkChunkAlloc.cpp rename to gfx/skia/trunk/src/core/SkChunkAlloc.cpp index 30cc4e19a7c3..62cdf1532f75 100644 --- a/gfx/skia/src/core/SkChunkAlloc.cpp +++ b/gfx/skia/trunk/src/core/SkChunkAlloc.cpp @@ -52,6 +52,7 @@ SkChunkAlloc::SkChunkAlloc(size_t minSize) { fMinSize = minSize; fChunkSize = fMinSize; fTotalCapacity = 0; + fTotalUsed = 0; fBlockCount = 0; } @@ -64,6 +65,7 @@ void SkChunkAlloc::reset() { fBlock = NULL; fChunkSize = fMinSize; // reset to our initial minSize fTotalCapacity = 0; + fTotalUsed = 0; fBlockCount = 0; } @@ -90,6 +92,8 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { } void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { + fTotalUsed += bytes; + bytes = SkAlign4(bytes); Block* block = fBlock; diff --git a/gfx/skia/src/core/SkClipStack.cpp b/gfx/skia/trunk/src/core/SkClipStack.cpp similarity index 86% rename from gfx/skia/src/core/SkClipStack.cpp rename to gfx/skia/trunk/src/core/SkClipStack.cpp index 9afef3f31182..c66a219b629b 100644 --- a/gfx/skia/src/core/SkClipStack.cpp +++ b/gfx/skia/trunk/src/core/SkClipStack.cpp @@ -288,10 +288,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 @@ -406,6 +406,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; @@ -443,12 +446,15 @@ void SkClipStack::save() { void SkClipStack::restore() { fSaveCount -= 1; + restoreTo(fSaveCount); +} + +void SkClipStack::restoreTo(int saveCount) { while (!fDeque.empty()) { Element* element = (Element*)fDeque.back(); - if (element->fSaveCount <= fSaveCount) { + if (element->fSaveCount <= saveCount) { break; } - this->purgeClip(element); element->~Element(); fDeque.pop_back(); } @@ -528,40 +534,39 @@ void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) { SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart); Element* element = (Element*) iter.prev(); - if (element && element->canBeIntersectedInPlace(fSaveCount, op)) { - switch (element->fType) { - case Element::kEmpty_Type: - element->checkEmpty(); - return; - case Element::kRect_Type: - if (element->rectRectIntersectAllowed(rect, doAA)) { - this->purgeClip(element); - if (!element->fRect.intersect(rect)) { + if (NULL != element) { + if (element->canBeIntersectedInPlace(fSaveCount, op)) { + switch (element->fType) { + case Element::kEmpty_Type: + element->checkEmpty(); + return; + case Element::kRect_Type: + if (element->rectRectIntersectAllowed(rect, doAA)) { + if (!element->fRect.intersect(rect)) { + element->setEmpty(); + return; + } + + element->fDoAA = doAA; + Element* prev = (Element*) iter.prev(); + element->updateBoundAndGenID(prev); + return; + } + break; + case Element::kPath_Type: + if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { element->setEmpty(); return; } - - element->fDoAA = doAA; - Element* prev = (Element*) iter.prev(); - element->updateBoundAndGenID(prev); - return; - } - break; - case Element::kPath_Type: - if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { - this->purgeClip(element); - element->setEmpty(); - return; - } - break; + break; + } + } else if (SkRegion::kReplace_Op == op) { + this->restoreTo(fSaveCount - 1); + element = (Element*) fDeque.back(); } } new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); ((Element*) fDeque.back())->updateBoundAndGenID(element); - - if (element && element->fSaveCount == fSaveCount) { - this->purgeClip(element); - } } void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { @@ -571,34 +576,33 @@ void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { } Element* element = (Element*)fDeque.back(); - if (element && 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)) { - this->purgeClip(element); - element->setEmpty(); + if (NULL != element) { + if (element->canBeIntersectedInPlace(fSaveCount, op)) { + const SkRect& pathBounds = path.getBounds(); + switch (element->fType) { + case Element::kEmpty_Type: + element->checkEmpty(); return; - } - break; - case Element::kPath_Type: - if (!SkRect::Intersects(element->fPath.getBounds(), pathBounds)) { - this->purgeClip(element); - element->setEmpty(); - return; - } - break; + 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); - - if (element && element->fSaveCount == fSaveCount) { - this->purgeClip(element); - } } void SkClipStack::clipEmpty() { @@ -612,27 +616,17 @@ void SkClipStack::clipEmpty() { return; case Element::kRect_Type: case Element::kPath_Type: - this->purgeClip(element); element->setEmpty(); return; } } new (fDeque.push_back()) Element(fSaveCount); - if (element && element->fSaveCount == fSaveCount) { - this->purgeClip(element); - } ((Element*)fDeque.back())->fGenID = kEmptyGenID; } bool SkClipStack::isWideOpen() const { - if (0 == fDeque.count()) { - return true; - } - - const Element* back = (const Element*) fDeque.back(); - return kWideOpenGenID == back->fGenID || - (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty()); + return this->getTopmostGenID() == kWideOpenGenID; } /////////////////////////////////////////////////////////////////////////////// @@ -726,45 +720,20 @@ void SkClipStack::getConservativeBounds(int offsetX, } } -void SkClipStack::addPurgeClipCallback(PFPurgeClipCB callback, void* data) const { - ClipCallbackData temp = { callback, data }; - fCallbackData.append(1, &temp); -} - -void SkClipStack::removePurgeClipCallback(PFPurgeClipCB callback, void* data) const { - ClipCallbackData temp = { callback, data }; - int index = fCallbackData.find(temp); - if (index >= 0) { - fCallbackData.removeShuffle(index); - } -} - -// The clip state represented by 'element' will never be used again. Purge it. -void SkClipStack::purgeClip(Element* element) { - SkASSERT(NULL != element); - if (element->fGenID >= 0 && element->fGenID < kFirstUnreservedGenID) { - return; - } - - for (int i = 0; i < fCallbackData.count(); ++i) { - (*fCallbackData[i].fCallback)(element->fGenID, fCallbackData[i].fData); - } - - // Invalidate element's gen ID so handlers can detect already handled records - element->fGenID = kInvalidGenID; -} - int32_t SkClipStack::GetNextGenID() { // TODO: handle overflow. return sk_atomic_inc(&gGenID); } int32_t SkClipStack::getTopmostGenID() const { - if (fDeque.empty()) { - return kInvalidGenID; + return kWideOpenGenID; } - Element* element = (Element*)fDeque.back(); - return element->fGenID; + const Element* back = static_cast(fDeque.back()); + if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty()) { + return kWideOpenGenID; + } + + return back->getGenID(); } diff --git a/gfx/skia/src/core/SkColor.cpp b/gfx/skia/trunk/src/core/SkColor.cpp similarity index 100% rename from gfx/skia/src/core/SkColor.cpp rename to gfx/skia/trunk/src/core/SkColor.cpp diff --git a/gfx/skia/trunk/src/core/SkColorFilter.cpp b/gfx/skia/trunk/src/core/SkColorFilter.cpp new file mode 100644 index 000000000000..8cf9fc010a19 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkColorFilter.cpp @@ -0,0 +1,45 @@ +/* + * 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 "SkColorFilter.h" + +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" +#include "SkShader.h" +#include "SkUnPreMultiply.h" +#include "SkString.h" + +bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const { + return false; +} + +bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const { + return false; +} + +bool SkColorFilter::asComponentTable(SkBitmap*) const { + return false; +} + +void SkColorFilter::filterSpan16(const uint16_t s[], int count, uint16_t d[]) const { + SkASSERT(this->getFlags() & SkColorFilter::kHasFilter16_Flag); + SkDEBUGFAIL("missing implementation of SkColorFilter::filterSpan16"); + + if (d != s) { + memcpy(d, s, count * sizeof(uint16_t)); + } +} + +SkColor SkColorFilter::filterColor(SkColor c) const { + SkPMColor dst, src = SkPreMultiplyColor(c); + this->filterSpan(&src, 1, &dst); + return SkUnPreMultiply::PMColorToColor(dst); +} + +GrEffectRef* SkColorFilter::asNewEffect(GrContext*) const { + return NULL; +} diff --git a/gfx/skia/trunk/src/core/SkColorTable.cpp b/gfx/skia/trunk/src/core/SkColorTable.cpp new file mode 100644 index 000000000000..b8e7b059e8fa --- /dev/null +++ b/gfx/skia/trunk/src/core/SkColorTable.cpp @@ -0,0 +1,112 @@ + +/* + * 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 "SkColorTable.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" +#include "SkStream.h" +#include "SkTemplates.h" + +// As copy constructor is hidden in the class hierarchy, we need to call +// default constructor explicitly to suppress a compiler warning. +SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() { + f16BitCache = NULL; + fAlphaType = src.fAlphaType; + int count = src.count(); + fCount = SkToU16(count); + fColors = reinterpret_cast( + sk_malloc_throw(count * sizeof(SkPMColor))); + memcpy(fColors, src.fColors, count * sizeof(SkPMColor)); + + SkDEBUGCODE(fColorLockCount = 0;) + SkDEBUGCODE(f16BitCacheLockCount = 0;) +} + +SkColorTable::SkColorTable(const SkPMColor colors[], int count, SkAlphaType at) + : f16BitCache(NULL), fAlphaType(SkToU8(at)) +{ + SkASSERT(0 == count || NULL != colors); + + if (count < 0) { + count = 0; + } else if (count > 256) { + count = 256; + } + + fCount = SkToU16(count); + fColors = reinterpret_cast( + sk_malloc_throw(count * sizeof(SkPMColor))); + + memcpy(fColors, colors, count * sizeof(SkPMColor)); + + SkDEBUGCODE(fColorLockCount = 0;) + SkDEBUGCODE(f16BitCacheLockCount = 0;) +} + +SkColorTable::~SkColorTable() +{ + SkASSERT(fColorLockCount == 0); + SkASSERT(f16BitCacheLockCount == 0); + + sk_free(fColors); + sk_free(f16BitCache); +} + +void SkColorTable::unlockColors() { + SkASSERT(fColorLockCount != 0); + SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);) +} + +#include "SkColorPriv.h" + +static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], + int count) { + while (--count >= 0) { + *dst++ = SkPixel32ToPixel16_ToU16(*src++); + } +} + +const uint16_t* SkColorTable::lock16BitCache() { + if (this->isOpaque() && NULL == f16BitCache) { + f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t)); + build_16bitcache(f16BitCache, fColors, fCount); + } + + SkDEBUGCODE(f16BitCacheLockCount += 1); + return f16BitCache; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkColorTable::SkColorTable(SkReadBuffer& buffer) { + f16BitCache = NULL; + SkDEBUGCODE(fColorLockCount = 0;) + SkDEBUGCODE(f16BitCacheLockCount = 0;) + + fAlphaType = SkToU8(buffer.readUInt()); + fCount = buffer.getArrayCount(); + 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(SkWriteBuffer& buffer) const { + buffer.writeUInt(fAlphaType); + buffer.writeColorArray(fColors, fCount); +} diff --git a/gfx/skia/src/core/SkComposeShader.cpp b/gfx/skia/trunk/src/core/SkComposeShader.cpp similarity index 93% rename from gfx/skia/src/core/SkComposeShader.cpp rename to gfx/skia/trunk/src/core/SkComposeShader.cpp index de0ffdb24a19..b5ea63c24c5e 100644 --- a/gfx/skia/src/core/SkComposeShader.cpp +++ b/gfx/skia/trunk/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,17 +26,17 @@ SkComposeShader::SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode) { SkSafeRef(mode); } -SkComposeShader::SkComposeShader(SkFlattenableReadBuffer& buffer) : +SkComposeShader::SkComposeShader(SkReadBuffer& buffer) : INHERITED(buffer) { - fShaderA = buffer.readFlattenableT(); + fShaderA = buffer.readShader(); if (NULL == fShaderA) { fShaderA = SkNEW_ARGS(SkColorShader, (0)); } - fShaderB = buffer.readFlattenableT(); + fShaderB = buffer.readShader(); if (NULL == fShaderB) { fShaderB = SkNEW_ARGS(SkColorShader, (0)); } - fMode = buffer.readFlattenableT(); + fMode = buffer.readXfermode(); } SkComposeShader::~SkComposeShader() { @@ -59,8 +60,9 @@ private: SkPaint* fPaint; uint8_t fAlpha; }; +#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); diff --git a/gfx/skia/src/core/SkConfig8888.cpp b/gfx/skia/trunk/src/core/SkConfig8888.cpp similarity index 95% rename from gfx/skia/src/core/SkConfig8888.cpp rename to gfx/skia/trunk/src/core/SkConfig8888.cpp index f889f20744fa..dd5cbc47240c 100644 --- a/gfx/skia/src/core/SkConfig8888.cpp +++ b/gfx/skia/trunk/src/core/SkConfig8888.cpp @@ -1,5 +1,6 @@ #include "SkConfig8888.h" #include "SkMathPriv.h" +#include "SkUnPreMultiply.h" namespace { @@ -57,23 +58,20 @@ inline uint32_t convert_pixel(uint32_t pixel) { uint32_t a, r, g, b; unpack_config8888(pixel, &a, &r, &g, &b); if (IN_PM && !OUT_PM) { - // We're doing the explicit divide to match WebKit layout - // test expectations. We can modify and rebaseline if there - // it can be shown that there is a more performant way to - // unpremul. + // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a. if (a) { - r = r * 0xff / a; - g = g * 0xff / a; - b = b * 0xff / 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 WebKit's conversion which we are replacing. - // We can consider alternative rounding rules for performance. - r = SkMulDiv255Ceiling(r, a); - g = SkMulDiv255Ceiling(g, a); - b = SkMulDiv255Ceiling(b, a); + // This matches SkUnPreMultiply conversion which we are replacing. + r = SkMulDiv255Round(r, a); + g = SkMulDiv255Round(g, a); + b = SkMulDiv255Round(b, a); } return pack_config8888(a, r, g, b); } diff --git a/gfx/skia/src/core/SkConfig8888.h b/gfx/skia/trunk/src/core/SkConfig8888.h similarity index 97% rename from gfx/skia/src/core/SkConfig8888.h rename to gfx/skia/trunk/src/core/SkConfig8888.h index 36bc9b4ed48f..96eaef2447f5 100644 --- a/gfx/skia/src/core/SkConfig8888.h +++ b/gfx/skia/trunk/src/core/SkConfig8888.h @@ -6,8 +6,6 @@ * found in the LICENSE file. */ -#ifndef SkConfig8888_DEFINED -#define SkConfig8888_DEFINED #include "SkCanvas.h" #include "SkColorPriv.h" @@ -76,5 +74,3 @@ static inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, } } - -#endif diff --git a/gfx/skia/trunk/src/core/SkConvolver.cpp b/gfx/skia/trunk/src/core/SkConvolver.cpp new file mode 100644 index 000000000000..7666e6fadc99 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkConvolver.cpp @@ -0,0 +1,461 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "SkConvolver.h" +#include "SkSize.h" +#include "SkTypes.h" + +namespace { + + // Converts the argument to an 8-bit unsigned value by clamping to the range + // 0-255. + inline unsigned char ClampTo8(int a) { + if (static_cast(a) < 256) { + return a; // Avoid the extra check in the common case. + } + if (a < 0) { + return 0; + } + return 255; + } + + // Stores a list of rows in a circular buffer. The usage is you write into it + // by calling AdvanceRow. It will keep track of which row in the buffer it + // should use next, and the total number of rows added. + class CircularRowBuffer { + public: + // The number of pixels in each row is given in |sourceRowPixelWidth|. + // The maximum number of rows needed in the buffer is |maxYFilterSize| + // (we only need to store enough rows for the biggest filter). + // + // We use the |firstInputRow| to compute the coordinates of all of the + // following rows returned by Advance(). + CircularRowBuffer(int destRowPixelWidth, int maxYFilterSize, + int firstInputRow) + : fRowByteWidth(destRowPixelWidth * 4), + fNumRows(maxYFilterSize), + fNextRow(0), + fNextRowCoordinate(firstInputRow) { + fBuffer.reset(fRowByteWidth * maxYFilterSize); + fRowAddresses.reset(fNumRows); + } + + // Moves to the next row in the buffer, returning a pointer to the beginning + // of it. + unsigned char* advanceRow() { + unsigned char* row = &fBuffer[fNextRow * fRowByteWidth]; + fNextRowCoordinate++; + + // Set the pointer to the next row to use, wrapping around if necessary. + fNextRow++; + if (fNextRow == fNumRows) { + fNextRow = 0; + } + return row; + } + + // Returns a pointer to an "unrolled" array of rows. These rows will start + // at the y coordinate placed into |*firstRowIndex| and will continue in + // order for the maximum number of rows in this circular buffer. + // + // The |firstRowIndex_| may be negative. This means the circular buffer + // starts before the top of the image (it hasn't been filled yet). + unsigned char* const* GetRowAddresses(int* firstRowIndex) { + // Example for a 4-element circular buffer holding coords 6-9. + // Row 0 Coord 8 + // Row 1 Coord 9 + // Row 2 Coord 6 <- fNextRow = 2, fNextRowCoordinate = 10. + // Row 3 Coord 7 + // + // The "next" row is also the first (lowest) coordinate. This computation + // may yield a negative value, but that's OK, the math will work out + // since the user of this buffer will compute the offset relative + // to the firstRowIndex and the negative rows will never be used. + *firstRowIndex = fNextRowCoordinate - fNumRows; + + int curRow = fNextRow; + for (int i = 0; i < fNumRows; i++) { + fRowAddresses[i] = &fBuffer[curRow * fRowByteWidth]; + + // Advance to the next row, wrapping if necessary. + curRow++; + if (curRow == fNumRows) { + curRow = 0; + } + } + return &fRowAddresses[0]; + } + + private: + // The buffer storing the rows. They are packed, each one fRowByteWidth. + SkTArray fBuffer; + + // Number of bytes per row in the |buffer|. + int fRowByteWidth; + + // The number of rows available in the buffer. + int fNumRows; + + // The next row index we should write into. This wraps around as the + // circular buffer is used. + int fNextRow; + + // The y coordinate of the |fNextRow|. This is incremented each time a + // new row is appended and does not wrap. + int fNextRowCoordinate; + + // Buffer used by GetRowAddresses(). + SkTArray fRowAddresses; + }; + +// Convolves horizontally along a single row. The row data is given in +// |srcData| and continues for the numValues() of the filter. +template + void ConvolveHorizontally(const unsigned char* srcData, + const SkConvolutionFilter1D& filter, + unsigned char* outRow) { + // Loop over each pixel on this row in the output image. + int numValues = filter.numValues(); + for (int outX = 0; outX < numValues; outX++) { + // Get the filter that determines the current output pixel. + int filterOffset, filterLength; + const SkConvolutionFilter1D::ConvolutionFixed* filterValues = + filter.FilterForValue(outX, &filterOffset, &filterLength); + + // Compute the first pixel in this row that the filter affects. It will + // touch |filterLength| pixels (4 bytes each) after this. + const unsigned char* rowToFilter = &srcData[filterOffset * 4]; + + // Apply the filter to the row to get the destination pixel in |accum|. + int accum[4] = {0}; + for (int filterX = 0; filterX < filterLength; filterX++) { + SkConvolutionFilter1D::ConvolutionFixed curFilter = filterValues[filterX]; + accum[0] += curFilter * rowToFilter[filterX * 4 + 0]; + accum[1] += curFilter * rowToFilter[filterX * 4 + 1]; + accum[2] += curFilter * rowToFilter[filterX * 4 + 2]; + if (hasAlpha) { + accum[3] += curFilter * rowToFilter[filterX * 4 + 3]; + } + } + + // Bring this value back in range. All of the filter scaling factors + // are in fixed point with kShiftBits bits of fractional part. + accum[0] >>= SkConvolutionFilter1D::kShiftBits; + accum[1] >>= SkConvolutionFilter1D::kShiftBits; + accum[2] >>= SkConvolutionFilter1D::kShiftBits; + if (hasAlpha) { + accum[3] >>= SkConvolutionFilter1D::kShiftBits; + } + + // Store the new pixel. + outRow[outX * 4 + 0] = ClampTo8(accum[0]); + outRow[outX * 4 + 1] = ClampTo8(accum[1]); + outRow[outX * 4 + 2] = ClampTo8(accum[2]); + if (hasAlpha) { + outRow[outX * 4 + 3] = ClampTo8(accum[3]); + } + } + } + +// Does vertical convolution to produce one output row. The filter values and +// length are given in the first two parameters. These are applied to each +// of the rows pointed to in the |sourceDataRows| array, with each row +// being |pixelWidth| wide. +// +// The output must have room for |pixelWidth * 4| bytes. +template + void ConvolveVertically(const SkConvolutionFilter1D::ConvolutionFixed* filterValues, + int filterLength, + unsigned char* const* sourceDataRows, + int pixelWidth, + unsigned char* outRow) { + // We go through each column in the output and do a vertical convolution, + // generating one output pixel each time. + for (int outX = 0; outX < pixelWidth; outX++) { + // Compute the number of bytes over in each row that the current column + // we're convolving starts at. The pixel will cover the next 4 bytes. + int byteOffset = outX * 4; + + // Apply the filter to one column of pixels. + int accum[4] = {0}; + for (int filterY = 0; filterY < filterLength; filterY++) { + SkConvolutionFilter1D::ConvolutionFixed curFilter = filterValues[filterY]; + accum[0] += curFilter * sourceDataRows[filterY][byteOffset + 0]; + accum[1] += curFilter * sourceDataRows[filterY][byteOffset + 1]; + accum[2] += curFilter * sourceDataRows[filterY][byteOffset + 2]; + if (hasAlpha) { + accum[3] += curFilter * sourceDataRows[filterY][byteOffset + 3]; + } + } + + // Bring this value back in range. All of the filter scaling factors + // are in fixed point with kShiftBits bits of precision. + accum[0] >>= SkConvolutionFilter1D::kShiftBits; + accum[1] >>= SkConvolutionFilter1D::kShiftBits; + accum[2] >>= SkConvolutionFilter1D::kShiftBits; + if (hasAlpha) { + accum[3] >>= SkConvolutionFilter1D::kShiftBits; + } + + // Store the new pixel. + outRow[byteOffset + 0] = ClampTo8(accum[0]); + outRow[byteOffset + 1] = ClampTo8(accum[1]); + outRow[byteOffset + 2] = ClampTo8(accum[2]); + if (hasAlpha) { + unsigned char alpha = ClampTo8(accum[3]); + + // Make sure the alpha channel doesn't come out smaller than any of the + // color channels. We use premultipled alpha channels, so this should + // never happen, but rounding errors will cause this from time to time. + // These "impossible" colors will cause overflows (and hence random pixel + // values) when the resulting bitmap is drawn to the screen. + // + // We only need to do this when generating the final output row (here). + int maxColorChannel = SkTMax(outRow[byteOffset + 0], + SkTMax(outRow[byteOffset + 1], + outRow[byteOffset + 2])); + if (alpha < maxColorChannel) { + outRow[byteOffset + 3] = maxColorChannel; + } else { + outRow[byteOffset + 3] = alpha; + } + } else { + // No alpha channel, the image is opaque. + outRow[byteOffset + 3] = 0xff; + } + } + } + + void ConvolveVertically(const SkConvolutionFilter1D::ConvolutionFixed* filterValues, + int filterLength, + unsigned char* const* sourceDataRows, + int pixelWidth, + unsigned char* outRow, + bool sourceHasAlpha) { + if (sourceHasAlpha) { + ConvolveVertically(filterValues, filterLength, + sourceDataRows, pixelWidth, + outRow); + } else { + ConvolveVertically(filterValues, filterLength, + sourceDataRows, pixelWidth, + outRow); + } + } + +} // namespace + +// SkConvolutionFilter1D --------------------------------------------------------- + +SkConvolutionFilter1D::SkConvolutionFilter1D() +: fMaxFilter(0) { +} + +SkConvolutionFilter1D::~SkConvolutionFilter1D() { +} + +void SkConvolutionFilter1D::AddFilter(int filterOffset, + const float* filterValues, + int filterLength) { + SkASSERT(filterLength > 0); + + SkTArray fixedValues; + fixedValues.reset(filterLength); + + for (int i = 0; i < filterLength; ++i) { + fixedValues.push_back(FloatToFixed(filterValues[i])); + } + + AddFilter(filterOffset, &fixedValues[0], filterLength); +} + +void SkConvolutionFilter1D::AddFilter(int filterOffset, + const ConvolutionFixed* filterValues, + int filterLength) { + // It is common for leading/trailing filter values to be zeros. In such + // cases it is beneficial to only store the central factors. + // For a scaling to 1/4th in each dimension using a Lanczos-2 filter on + // a 1080p image this optimization gives a ~10% speed improvement. + int filterSize = filterLength; + int firstNonZero = 0; + while (firstNonZero < filterLength && filterValues[firstNonZero] == 0) { + firstNonZero++; + } + + if (firstNonZero < filterLength) { + // Here we have at least one non-zero factor. + int lastNonZero = filterLength - 1; + while (lastNonZero >= 0 && filterValues[lastNonZero] == 0) { + lastNonZero--; + } + + filterOffset += firstNonZero; + filterLength = lastNonZero + 1 - firstNonZero; + SkASSERT(filterLength > 0); + + for (int i = firstNonZero; i <= lastNonZero; i++) { + fFilterValues.push_back(filterValues[i]); + } + } else { + // Here all the factors were zeroes. + filterLength = 0; + } + + FilterInstance instance; + + // We pushed filterLength elements onto fFilterValues + instance.fDataLocation = (static_cast(fFilterValues.count()) - + filterLength); + instance.fOffset = filterOffset; + instance.fTrimmedLength = filterLength; + instance.fLength = filterSize; + fFilters.push_back(instance); + + fMaxFilter = SkTMax(fMaxFilter, filterLength); +} + +const SkConvolutionFilter1D::ConvolutionFixed* SkConvolutionFilter1D::GetSingleFilter( + int* specifiedFilterlength, + int* filterOffset, + int* filterLength) const { + const FilterInstance& filter = fFilters[0]; + *filterOffset = filter.fOffset; + *filterLength = filter.fTrimmedLength; + *specifiedFilterlength = filter.fLength; + if (filter.fTrimmedLength == 0) { + return NULL; + } + + return &fFilterValues[filter.fDataLocation]; +} + +void BGRAConvolve2D(const unsigned char* sourceData, + int sourceByteRowStride, + bool sourceHasAlpha, + const SkConvolutionFilter1D& filterX, + const SkConvolutionFilter1D& filterY, + int outputByteRowStride, + unsigned char* output, + const SkConvolutionProcs& convolveProcs, + bool useSimdIfPossible) { + + int maxYFilterSize = filterY.maxFilter(); + + // The next row in the input that we will generate a horizontally + // convolved row for. If the filter doesn't start at the beginning of the + // image (this is the case when we are only resizing a subset), then we + // don't want to generate any output rows before that. Compute the starting + // row for convolution as the first pixel for the first vertical filter. + int filterOffset, filterLength; + const SkConvolutionFilter1D::ConvolutionFixed* filterValues = + filterY.FilterForValue(0, &filterOffset, &filterLength); + int nextXRow = filterOffset; + + // We loop over each row in the input doing a horizontal convolution. This + // will result in a horizontally convolved image. We write the results into + // a circular buffer of convolved rows and do vertical convolution as rows + // are available. This prevents us from having to store the entire + // intermediate image and helps cache coherency. + // We will need four extra rows to allow horizontal convolution could be done + // simultaneously. We also pad each row in row buffer to be aligned-up to + // 16 bytes. + // TODO(jiesun): We do not use aligned load from row buffer in vertical + // convolution pass yet. Somehow Windows does not like it. + int rowBufferWidth = (filterX.numValues() + 15) & ~0xF; + int rowBufferHeight = maxYFilterSize + + (convolveProcs.fConvolve4RowsHorizontally ? 4 : 0); + CircularRowBuffer rowBuffer(rowBufferWidth, + rowBufferHeight, + filterOffset); + + // Loop over every possible output row, processing just enough horizontal + // convolutions to run each subsequent vertical convolution. + SkASSERT(outputByteRowStride >= filterX.numValues() * 4); + int numOutputRows = filterY.numValues(); + + // We need to check which is the last line to convolve before we advance 4 + // lines in one iteration. + int lastFilterOffset, lastFilterLength; + + // SSE2 can access up to 3 extra pixels past the end of the + // buffer. At the bottom of the image, we have to be careful + // not to access data past the end of the buffer. Normally + // we fall back to the C++ implementation for the last row. + // If the last row is less than 3 pixels wide, we may have to fall + // back to the C++ version for more rows. Compute how many + // rows we need to avoid the SSE implementation for here. + filterX.FilterForValue(filterX.numValues() - 1, &lastFilterOffset, + &lastFilterLength); + int avoidSimdRows = 1 + convolveProcs.fExtraHorizontalReads / + (lastFilterOffset + lastFilterLength); + + filterY.FilterForValue(numOutputRows - 1, &lastFilterOffset, + &lastFilterLength); + + for (int outY = 0; outY < numOutputRows; outY++) { + filterValues = filterY.FilterForValue(outY, + &filterOffset, &filterLength); + + // Generate output rows until we have enough to run the current filter. + while (nextXRow < filterOffset + filterLength) { + if (convolveProcs.fConvolve4RowsHorizontally && + nextXRow + 3 < lastFilterOffset + lastFilterLength - + avoidSimdRows) { + const unsigned char* src[4]; + unsigned char* outRow[4]; + for (int i = 0; i < 4; ++i) { + src[i] = &sourceData[(nextXRow + i) * sourceByteRowStride]; + outRow[i] = rowBuffer.advanceRow(); + } + convolveProcs.fConvolve4RowsHorizontally(src, filterX, outRow); + nextXRow += 4; + } else { + // Check if we need to avoid SSE2 for this row. + if (convolveProcs.fConvolveHorizontally && + nextXRow < lastFilterOffset + lastFilterLength - + avoidSimdRows) { + convolveProcs.fConvolveHorizontally( + &sourceData[nextXRow * sourceByteRowStride], + filterX, rowBuffer.advanceRow(), sourceHasAlpha); + } else { + if (sourceHasAlpha) { + ConvolveHorizontally( + &sourceData[nextXRow * sourceByteRowStride], + filterX, rowBuffer.advanceRow()); + } else { + ConvolveHorizontally( + &sourceData[nextXRow * sourceByteRowStride], + filterX, rowBuffer.advanceRow()); + } + } + nextXRow++; + } + } + + // Compute where in the output image this row of final data will go. + unsigned char* curOutputRow = &output[outY * outputByteRowStride]; + + // Get the list of rows that the circular buffer has, in order. + int firstRowInCircularBuffer; + unsigned char* const* rowsToConvolve = + rowBuffer.GetRowAddresses(&firstRowInCircularBuffer); + + // Now compute the start of the subset of those rows that the filter + // needs. + unsigned char* const* firstRowForFilter = + &rowsToConvolve[filterOffset - firstRowInCircularBuffer]; + + if (convolveProcs.fConvolveVertically) { + convolveProcs.fConvolveVertically(filterValues, filterLength, + firstRowForFilter, + filterX.numValues(), curOutputRow, + sourceHasAlpha); + } else { + ConvolveVertically(filterValues, filterLength, + firstRowForFilter, + filterX.numValues(), curOutputRow, + sourceHasAlpha); + } + } +} diff --git a/gfx/skia/trunk/src/core/SkConvolver.h b/gfx/skia/trunk/src/core/SkConvolver.h new file mode 100644 index 000000000000..94a5e9159878 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkConvolver.h @@ -0,0 +1,203 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SK_CONVOLVER_H +#define SK_CONVOLVER_H + +#include "SkSize.h" +#include "SkTypes.h" +#include "SkTArray.h" + +// avoid confusion with Mac OS X's math library (Carbon) +#if defined(__APPLE__) +#undef FloatToConvolutionFixed +#undef ConvolutionFixedToFloat +#endif + +// Represents a filter in one dimension. Each output pixel has one entry in this +// object for the filter values contributing to it. You build up the filter +// list by calling AddFilter for each output pixel (in order). +// +// We do 2-dimensional convolution by first convolving each row by one +// SkConvolutionFilter1D, then convolving each column by another one. +// +// Entries are stored in ConvolutionFixed point, shifted left by kShiftBits. +class SkConvolutionFilter1D { +public: + typedef short ConvolutionFixed; + + // The number of bits that ConvolutionFixed point values are shifted by. + enum { kShiftBits = 14 }; + + SK_API SkConvolutionFilter1D(); + SK_API ~SkConvolutionFilter1D(); + + // Convert between floating point and our ConvolutionFixed point representation. + static ConvolutionFixed FloatToFixed(float f) { + return static_cast(f * (1 << kShiftBits)); + } + static unsigned char FixedToChar(ConvolutionFixed x) { + return static_cast(x >> kShiftBits); + } + static float FixedToFloat(ConvolutionFixed x) { + // The cast relies on ConvolutionFixed being a short, implying that on + // the platforms we care about all (16) bits will fit into + // the mantissa of a (32-bit) float. + SK_COMPILE_ASSERT(sizeof(ConvolutionFixed) == 2, ConvolutionFixed_type_should_fit_in_float_mantissa); + float raw = static_cast(x); + return ldexpf(raw, -kShiftBits); + } + + // Returns the maximum pixel span of a filter. + int maxFilter() const { return fMaxFilter; } + + // Returns the number of filters in this filter. This is the dimension of the + // output image. + int numValues() const { return static_cast(fFilters.count()); } + + // Appends the given list of scaling values for generating a given output + // pixel. |filterOffset| is the distance from the edge of the image to where + // the scaling factors start. The scaling factors apply to the source pixels + // starting from this position, and going for the next |filterLength| pixels. + // + // You will probably want to make sure your input is normalized (that is, + // all entries in |filterValuesg| sub to one) to prevent affecting the overall + // brighness of the image. + // + // The filterLength must be > 0. + // + // This version will automatically convert your input to ConvolutionFixed point. + SK_API void AddFilter(int filterOffset, + const float* filterValues, + int filterLength); + + // Same as the above version, but the input is already ConvolutionFixed point. + void AddFilter(int filterOffset, + const ConvolutionFixed* filterValues, + int filterLength); + + // Retrieves a filter for the given |valueOffset|, a position in the output + // image in the direction we're convolving. The offset and length of the + // filter values are put into the corresponding out arguments (see AddFilter + // above for what these mean), and a pointer to the first scaling factor is + // returned. There will be |filterLength| values in this array. + inline const ConvolutionFixed* FilterForValue(int valueOffset, + int* filterOffset, + int* filterLength) const { + const FilterInstance& filter = fFilters[valueOffset]; + *filterOffset = filter.fOffset; + *filterLength = filter.fTrimmedLength; + if (filter.fTrimmedLength == 0) { + return NULL; + } + return &fFilterValues[filter.fDataLocation]; + } + + // Retrieves the filter for the offset 0, presumed to be the one and only. + // The offset and length of the filter values are put into the corresponding + // out arguments (see AddFilter). Note that |filterLegth| and + // |specifiedFilterLength| may be different if leading/trailing zeros of the + // original floating point form were clipped. + // There will be |filterLength| values in the return array. + // Returns NULL if the filter is 0-length (for instance when all floating + // point values passed to AddFilter were clipped to 0). + SK_API const ConvolutionFixed* GetSingleFilter(int* specifiedFilterLength, + int* filterOffset, + int* filterLength) const; + + // Add another value to the fFilterValues array -- useful for + // SIMD padding which happens outside of this class. + + void addFilterValue( ConvolutionFixed val ) { + fFilterValues.push_back( val ); + } +private: + struct FilterInstance { + // Offset within filterValues for this instance of the filter. + int fDataLocation; + + // Distance from the left of the filter to the center. IN PIXELS + int fOffset; + + // Number of values in this filter instance. + int fTrimmedLength; + + // Filter length as specified. Note that this may be different from + // 'trimmed_length' if leading/trailing zeros of the original floating + // point form were clipped differently on each tail. + int fLength; + }; + + // Stores the information for each filter added to this class. + SkTArray fFilters; + + // We store all the filter values in this flat list, indexed by + // |FilterInstance.data_location| to avoid the mallocs required for storing + // each one separately. + SkTArray fFilterValues; + + // The maximum size of any filter we've added. + int fMaxFilter; +}; + +typedef void (*SkConvolveVertically_pointer)( + const SkConvolutionFilter1D::ConvolutionFixed* filterValues, + int filterLength, + unsigned char* const* sourceDataRows, + int pixelWidth, + unsigned char* outRow, + bool hasAlpha); +typedef void (*SkConvolve4RowsHorizontally_pointer)( + const unsigned char* srcData[4], + const SkConvolutionFilter1D& filter, + unsigned char* outRow[4]); +typedef void (*SkConvolveHorizontally_pointer)( + const unsigned char* srcData, + const SkConvolutionFilter1D& filter, + unsigned char* outRow, + bool hasAlpha); +typedef void (*SkConvolveFilterPadding_pointer)( + SkConvolutionFilter1D* filter); + +struct SkConvolutionProcs { + // This is how many extra pixels may be read by the + // conolve*horizontally functions. + int fExtraHorizontalReads; + SkConvolveVertically_pointer fConvolveVertically; + SkConvolve4RowsHorizontally_pointer fConvolve4RowsHorizontally; + SkConvolveHorizontally_pointer fConvolveHorizontally; + SkConvolveFilterPadding_pointer fApplySIMDPadding; +}; + + + +// Does a two-dimensional convolution on the given source image. +// +// It is assumed the source pixel offsets referenced in the input filters +// reference only valid pixels, so the source image size is not required. Each +// row of the source image starts |sourceByteRowStride| after the previous +// one (this allows you to have rows with some padding at the end). +// +// The result will be put into the given output buffer. The destination image +// size will be xfilter.numValues() * yfilter.numValues() pixels. It will be +// in rows of exactly xfilter.numValues() * 4 bytes. +// +// |sourceHasAlpha| is a hint that allows us to avoid doing computations on +// the alpha channel if the image is opaque. If you don't know, set this to +// true and it will work properly, but setting this to false will be a few +// percent faster if you know the image is opaque. +// +// The layout in memory is assumed to be 4-bytes per pixel in B-G-R-A order +// (this is ARGB when loaded into 32-bit words on a little-endian machine). +SK_API void BGRAConvolve2D(const unsigned char* sourceData, + int sourceByteRowStride, + bool sourceHasAlpha, + const SkConvolutionFilter1D& xfilter, + const SkConvolutionFilter1D& yfilter, + int outputByteRowStride, + unsigned char* output, + const SkConvolutionProcs&, + bool useSimdIfPossible); + +#endif // SK_CONVOLVER_H diff --git a/gfx/skia/src/core/SkCordic.cpp b/gfx/skia/trunk/src/core/SkCordic.cpp similarity index 96% rename from gfx/skia/src/core/SkCordic.cpp rename to gfx/skia/trunk/src/core/SkCordic.cpp index 00dd76ebb548..3adc92faa108 100644 --- a/gfx/skia/src/core/SkCordic.cpp +++ b/gfx/skia/trunk/src/core/SkCordic.cpp @@ -203,7 +203,7 @@ void SkCordic_UnitTest() float val; for (float angle = -720; angle < 720; angle += 30) { float radian = angle * 3.1415925358f / 180.0f; - SkFixed f_angle = (int) (radian * 65536.0f); + SkFixed f_angle = SkFloatToFixed(radian); // sincos float sine = sinf(radian); float cosine = cosf(radian); @@ -226,7 +226,7 @@ void SkCordic_UnitTest() SkDebugf("tan error : angle = %g ; tan = %g ; cordic = %g\n", angle, _tan, tan2); } for (val = -1; val <= 1; val += .1f) { - SkFixed f_val = (int) (val * 65536.0f); + SkFixed f_val = SkFloatToFixed(val); // asin float arcsine = asinf(val); SkFixed f_arcsine = SkCordicASin(f_val); @@ -240,7 +240,7 @@ void SkCordic_UnitTest() #else val = .5; { #endif - SkFixed f_val = (int) (val * 65536.0f); + SkFixed f_val = SkFloatToFixed(val); // acos float arccos = acosf(val); SkFixed f_arccos = SkCordicACos(f_val); @@ -257,8 +257,8 @@ void SkCordic_UnitTest() val = 0; { float val2 = -1000; { #endif - SkFixed f_val = (int) (val * 65536.0f); - SkFixed f_val2 = (int) (val2 * 65536.0f); + 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; @@ -273,7 +273,7 @@ void SkCordic_UnitTest() #else val = .5; { #endif - SkFixed f_val = (int) (val * 65536.0f); + SkFixed f_val = SkFloatToFixed(val); // acos float log = logf(val); SkFixed f_log = SkCordicLog(f_val); diff --git a/gfx/skia/src/core/SkCordic.h b/gfx/skia/trunk/src/core/SkCordic.h similarity index 100% rename from gfx/skia/src/core/SkCordic.h rename to gfx/skia/trunk/src/core/SkCordic.h diff --git a/gfx/skia/src/core/SkCoreBlitters.h b/gfx/skia/trunk/src/core/SkCoreBlitters.h similarity index 90% rename from gfx/skia/src/core/SkCoreBlitters.h rename to gfx/skia/trunk/src/core/SkCoreBlitters.h index 823cb41b0d64..1605a5273dcd 100644 --- a/gfx/skia/src/core/SkCoreBlitters.h +++ b/gfx/skia/trunk/src/core/SkCoreBlitters.h @@ -40,6 +40,17 @@ private: /////////////////////////////////////////////////////////////////////////////// +class SkA8_Coverage_Blitter : public SkRasterBlitter { +public: + SkA8_Coverage_Blitter(const SkBitmap& device, const SkPaint& paint); + virtual void blitH(int x, int y, int width) SK_OVERRIDE; + virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) SK_OVERRIDE; + virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE; + virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE; + virtual void blitMask(const SkMask&, const SkIRect&) SK_OVERRIDE; + virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE; +}; + class SkA8_Blitter : public SkRasterBlitter { public: SkA8_Blitter(const SkBitmap& device, const SkPaint& paint); @@ -151,22 +162,6 @@ private: /////////////////////////////////////////////////////////////////////////////// -class SkA1_Blitter : public SkRasterBlitter { -public: - SkA1_Blitter(const SkBitmap& device, const SkPaint& paint); - virtual void blitH(int x, int y, int width); - -private: - uint8_t fSrcA; - - // illegal - SkA1_Blitter& operator=(const SkA1_Blitter&); - - typedef SkRasterBlitter INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - /* These return the correct subclass of blitter for their device config. Currently, they make the following assumptions about the state of the @@ -180,10 +175,6 @@ private: SkBlitter::Choose(...) */ -extern SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device, - const SkPaint& paint, - void* storage, size_t storageSize); - extern SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint, void* storage, size_t storageSize); diff --git a/gfx/skia/src/core/SkCubicClipper.cpp b/gfx/skia/trunk/src/core/SkCubicClipper.cpp similarity index 94% rename from gfx/skia/src/core/SkCubicClipper.cpp rename to gfx/skia/trunk/src/core/SkCubicClipper.cpp index aed681b9f301..81ef18de7afa 100644 --- a/gfx/skia/src/core/SkCubicClipper.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkCubicClipper.h b/gfx/skia/trunk/src/core/SkCubicClipper.h similarity index 100% rename from gfx/skia/src/core/SkCubicClipper.h rename to gfx/skia/trunk/src/core/SkCubicClipper.h diff --git a/gfx/skia/trunk/src/core/SkData.cpp b/gfx/skia/trunk/src/core/SkData.cpp new file mode 100644 index 000000000000..2f0791406777 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkData.cpp @@ -0,0 +1,162 @@ +/* + * 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 "SkData.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" +#include "SkOSFile.h" +#include "SkOnce.h" + +SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { + fPtr = ptr; + fSize = size; + fReleaseProc = proc; + fReleaseProcContext = context; +} + +SkData::~SkData() { + if (fReleaseProc) { + fReleaseProc(fPtr, fSize, fReleaseProcContext); + } +} + +bool SkData::equals(const SkData* other) const { + if (NULL == other) { + return false; + } + + return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize); +} + +size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const { + size_t available = fSize; + if (offset >= available || 0 == length) { + return 0; + } + available -= offset; + if (length > available) { + length = available; + } + SkASSERT(length > 0); + + memcpy(buffer, this->bytes() + offset, length); + return length; +} + +/////////////////////////////////////////////////////////////////////////////// + +static SkData* gEmptyDataRef = NULL; +static void cleanup_gEmptyDataRef() { gEmptyDataRef->unref(); } + +void SkData::NewEmptyImpl(int) { + gEmptyDataRef = new SkData(NULL, 0, NULL, NULL); +} + +SkData* SkData::NewEmpty() { + SK_DECLARE_STATIC_ONCE(once); + SkOnce(&once, SkData::NewEmptyImpl, 0, cleanup_gEmptyDataRef); + gEmptyDataRef->ref(); + return gEmptyDataRef; +} + +// assumes fPtr was allocated via sk_malloc +static void sk_free_releaseproc(const void* ptr, size_t, void*) { + sk_free((void*)ptr); +} + +SkData* SkData::NewFromMalloc(const void* data, size_t length) { + return new SkData(data, length, sk_free_releaseproc, NULL); +} + +SkData* SkData::NewWithCopy(const void* data, size_t length) { + if (0 == length) { + return SkData::NewEmpty(); + } + + void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc + memcpy(copy, data, length); + return new SkData(copy, length, sk_free_releaseproc, NULL); +} + +SkData* SkData::NewWithProc(const void* data, size_t length, + ReleaseProc proc, void* context) { + return new SkData(data, length, proc, context); +} + +// assumes fPtr was allocated with sk_fmmap +static void sk_mmap_releaseproc(const void* addr, size_t length, void*) { + sk_fmunmap(addr, length); +} + +SkData* SkData::NewFromFILE(SkFILE* f) { + size_t size; + void* addr = sk_fmmap(f, &size); + if (NULL == addr) { + return NULL; + } + + return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); +} + +SkData* SkData::NewFromFileName(const char path[]) { + SkFILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : NULL; + if (NULL == f) { + return NULL; + } + SkData* data = NewFromFILE(f); + sk_fclose(f); + return data; +} + +SkData* SkData::NewFromFD(int fd) { + size_t size; + void* addr = sk_fdmmap(fd, &size); + if (NULL == addr) { + return NULL; + } + + return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); +} + +// assumes context is a SkData +static void sk_dataref_releaseproc(const void*, size_t, void* context) { + SkData* src = reinterpret_cast(context); + src->unref(); +} + +SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) { + /* + We could, if we wanted/need to, just make a deep copy of src's data, + rather than referencing it. This would duplicate the storage (of the + subset amount) but would possibly allow src to go out of scope sooner. + */ + + size_t available = src->size(); + if (offset >= available || 0 == length) { + return SkData::NewEmpty(); + } + available -= offset; + if (length > available) { + length = available; + } + SkASSERT(length > 0); + + src->ref(); // this will be balanced in sk_dataref_releaseproc + return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc, + const_cast(src)); +} + +SkData* SkData::NewWithCString(const char cstr[]) { + size_t size; + if (NULL == cstr) { + cstr = ""; + size = 1; + } else { + size = strlen(cstr) + 1; + } + return NewWithCopy(cstr, size); +} diff --git a/gfx/skia/trunk/src/core/SkDataTable.cpp b/gfx/skia/trunk/src/core/SkDataTable.cpp new file mode 100644 index 000000000000..e2644a05c98d --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDataTable.cpp @@ -0,0 +1,188 @@ +/* + * 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 "SkData.h" +#include "SkDataTable.h" + +static void malloc_freeproc(void* context) { + sk_free(context); +} + +// Makes empty table +SkDataTable::SkDataTable() { + fCount = 0; + fElemSize = 0; // 0 signals that we use fDir instead of fElems + fU.fDir = NULL; + fFreeProc = NULL; + fFreeProcContext = NULL; +} + +SkDataTable::SkDataTable(const void* array, size_t elemSize, int count, + FreeProc proc, void* context) { + SkASSERT(count > 0); + + fCount = count; + fElemSize = elemSize; // non-zero signals we use fElems instead of fDir + fU.fElems = (const char*)array; + fFreeProc = proc; + fFreeProcContext = context; +} + +SkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { + SkASSERT(count > 0); + + fCount = count; + fElemSize = 0; // 0 signals that we use fDir instead of fElems + fU.fDir = dir; + fFreeProc = proc; + fFreeProcContext = ctx; +} + +SkDataTable::~SkDataTable() { + if (fFreeProc) { + fFreeProc(fFreeProcContext); + } +} + +size_t SkDataTable::atSize(int index) const { + SkASSERT((unsigned)index < (unsigned)fCount); + + if (fElemSize) { + return fElemSize; + } else { + return fU.fDir[index].fSize; + } +} + +const void* SkDataTable::at(int index, size_t* size) const { + SkASSERT((unsigned)index < (unsigned)fCount); + + if (fElemSize) { + if (size) { + *size = fElemSize; + } + return fU.fElems + index * fElemSize; + } else { + if (size) { + *size = fU.fDir[index].fSize; + } + return fU.fDir[index].fPtr; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +SkDataTable* SkDataTable::NewEmpty() { + static SkDataTable* gEmpty; + if (NULL == gEmpty) { + gEmpty = SkNEW(SkDataTable); + } + gEmpty->ref(); + return gEmpty; +} + +SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs, + const size_t sizes[], int count) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + + size_t dataSize = 0; + for (int i = 0; i < count; ++i) { + dataSize += sizes[i]; + } + + size_t bufferSize = count * sizeof(Dir) + dataSize; + void* buffer = sk_malloc_throw(bufferSize); + + Dir* dir = (Dir*)buffer; + char* elem = (char*)(dir + count); + for (int i = 0; i < count; ++i) { + dir[i].fPtr = elem; + dir[i].fSize = sizes[i]; + memcpy(elem, ptrs[i], sizes[i]); + elem += sizes[i]; + } + + return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer)); +} + +SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize, + int count) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + + size_t bufferSize = elemSize * count; + void* buffer = sk_malloc_throw(bufferSize); + memcpy(buffer, array, bufferSize); + + return SkNEW_ARGS(SkDataTable, + (buffer, elemSize, count, malloc_freeproc, buffer)); +} + +SkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize, + int count, FreeProc proc, void* ctx) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx)); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void chunkalloc_freeproc(void* context) { + SkDELETE((SkChunkAlloc*)context); +} + +SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize) + : fHeap(NULL) + , fMinChunkSize(minChunkSize) {} + +SkDataTableBuilder::~SkDataTableBuilder() { this->reset(); } + +void SkDataTableBuilder::reset(size_t minChunkSize) { + fMinChunkSize = minChunkSize; + fDir.reset(); + if (fHeap) { + SkDELETE(fHeap); + fHeap = NULL; + } +} + +void SkDataTableBuilder::append(const void* src, size_t size) { + if (NULL == fHeap) { + fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize)); + } + + void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType); + memcpy(dst, src, size); + + SkDataTable::Dir* dir = fDir.append(); + dir->fPtr = dst; + dir->fSize = size; +} + +SkDataTable* SkDataTableBuilder::detachDataTable() { + const int count = fDir.count(); + if (0 == count) { + return SkDataTable::NewEmpty(); + } + + // Copy the dir into the heap; + void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir), + SkChunkAlloc::kThrow_AllocFailType); + memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir)); + + SkDataTable* table = SkNEW_ARGS(SkDataTable, + ((SkDataTable::Dir*)dir, count, + chunkalloc_freeproc, fHeap)); + // we have to detach our fHeap, since we are giving that to the table + fHeap = NULL; + fDir.reset(); + return table; +} diff --git a/gfx/skia/src/core/SkDebug.cpp b/gfx/skia/trunk/src/core/SkDebug.cpp similarity index 61% rename from gfx/skia/src/core/SkDebug.cpp rename to gfx/skia/trunk/src/core/SkDebug.cpp index a10d443f78a8..d484f5eaffe2 100644 --- a/gfx/skia/src/core/SkDebug.cpp +++ b/gfx/skia/trunk/src/core/SkDebug.cpp @@ -11,40 +11,44 @@ #ifdef SK_DEBUG -int8_t SkToS8(long x) -{ +int8_t SkToS8(intmax_t x) { SkASSERT((int8_t)x == x); return (int8_t)x; } -uint8_t SkToU8(size_t x) -{ +uint8_t SkToU8(uintmax_t x) { SkASSERT((uint8_t)x == x); return (uint8_t)x; } -int16_t SkToS16(long x) -{ +int16_t SkToS16(intmax_t x) { SkASSERT((int16_t)x == x); return (int16_t)x; } -uint16_t SkToU16(size_t x) -{ +uint16_t SkToU16(uintmax_t x) { SkASSERT((uint16_t)x == x); return (uint16_t)x; } -int32_t SkToS32(long x) -{ +int32_t SkToS32(intmax_t x) { SkASSERT((int32_t)x == x); return (int32_t)x; } -uint32_t SkToU32(size_t x) -{ +uint32_t SkToU32(uintmax_t x) { SkASSERT((uint32_t)x == 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; +} + #endif diff --git a/gfx/skia/src/core/SkDeque.cpp b/gfx/skia/trunk/src/core/SkDeque.cpp similarity index 100% rename from gfx/skia/src/core/SkDeque.cpp rename to gfx/skia/trunk/src/core/SkDeque.cpp diff --git a/gfx/skia/src/core/SkDescriptor.h b/gfx/skia/trunk/src/core/SkDescriptor.h similarity index 98% rename from gfx/skia/src/core/SkDescriptor.h rename to gfx/skia/trunk/src/core/SkDescriptor.h index 79b086f614f5..e71ff41b5c54 100644 --- a/gfx/skia/src/core/SkDescriptor.h +++ b/gfx/skia/trunk/src/core/SkDescriptor.h @@ -159,6 +159,7 @@ private: SkDescriptor* fDesc; uint32_t fStorage[(kStorageSize + 3) >> 2]; }; +#define SkAutoDescriptor(...) SK_REQUIRE_LOCAL_VAR(SkAutoDescriptor) #endif diff --git a/gfx/skia/trunk/src/core/SkDevice.cpp b/gfx/skia/trunk/src/core/SkDevice.cpp new file mode 100644 index 000000000000..9ce8b6b5df2e --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDevice.cpp @@ -0,0 +1,119 @@ +/* + * 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 "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 + , fAttachedToCanvas(false) +#endif +{ + fOrigin.setZero(); + fMetaData = NULL; +} + +SkBaseDevice::SkBaseDevice(const SkDeviceProperties& deviceProperties) + : fLeakyProperties(deviceProperties) +#ifdef SK_DEBUG + , fAttachedToCanvas(false) +#endif +{ + fOrigin.setZero(); + fMetaData = NULL; +} + +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::createCompatibleDeviceForSaveLayer(SkBitmap::Config config, + int width, int height, + bool isOpaque) { + return this->onCreateCompatibleDevice(config, width, height, + isOpaque, kSaveLayer_Usage); +} + +SkMetaData& SkBaseDevice::getMetaData() { + // metadata users are rare, so we lazily allocate it. If that changes we + // can decide to just make it a field in the device (rather than a ptr) + if (NULL == fMetaData) { + fMetaData = new SkMetaData; + } + return *fMetaData; +} + +const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) { + const SkBitmap& bitmap = this->onAccessBitmap(); + if (changePixels) { + bitmap.notifyPixelsChanged(); + } + 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; + } + + const SkBitmap& src = this->accessBitmap(false); + + SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(), + bitmap->height()); + SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height()); + if (!srcRect.intersect(devbounds)) { + return false; + } + + SkBitmap tmp; + SkBitmap* bmp; + if (bitmap->isNull()) { + if (!tmp.allocPixels(SkImageInfo::MakeN32Premul(bitmap->width(), + bitmap->height()))) { + return false; + } + bmp = &tmp; + } else { + bmp = bitmap; + } + + 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); + } + return result; +} + +SkSurface* SkBaseDevice::newSurface(const SkImageInfo&) { return NULL; } diff --git a/gfx/skia/src/core/SkDeviceImageFilterProxy.h b/gfx/skia/trunk/src/core/SkDeviceImageFilterProxy.h similarity index 70% rename from gfx/skia/src/core/SkDeviceImageFilterProxy.h rename to gfx/skia/trunk/src/core/SkDeviceImageFilterProxy.h index 98a120cd0d78..800e42c1f62d 100644 --- a/gfx/skia/src/core/SkDeviceImageFilterProxy.h +++ b/gfx/skia/trunk/src/core/SkDeviceImageFilterProxy.h @@ -12,23 +12,23 @@ class SkDeviceImageFilterProxy : public SkImageFilter::Proxy { public: - SkDeviceImageFilterProxy(SkDevice* device) : fDevice(device) {} + SkDeviceImageFilterProxy(SkBaseDevice* device) : fDevice(device) {} - virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE { + virtual SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE { return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config, w, h, false); } - 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, + virtual bool filterImage(const SkImageFilter* filter, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { return fDevice->filterImage(filter, src, ctm, result, offset); } private: - SkDevice* fDevice; + SkBaseDevice* fDevice; }; #endif diff --git a/gfx/skia/trunk/src/core/SkDeviceLooper.cpp b/gfx/skia/trunk/src/core/SkDeviceLooper.cpp new file mode 100644 index 000000000000..9346465dfc9f --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDeviceLooper.cpp @@ -0,0 +1,131 @@ +/* + * 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 "SkDeviceLooper.h" + +SkDeviceLooper::SkDeviceLooper(const SkBitmap& base, + const SkRasterClip& rc, + const SkIRect& bounds, bool aa) +: fBaseBitmap(base) +, fBaseRC(rc) +, fDelta(aa ? kAA_Delta : kBW_Delta) +{ + // sentinels that next() has not yet been called, and so our mapper functions + // should not be called either. + fCurrBitmap = NULL; + fCurrRC = NULL; + + if (!rc.isEmpty()) { + // clip must be contained by the bitmap + SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds())); + } + + if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) { + fState = kDone_State; + } else if (this->fitsInDelta(fClippedBounds)) { + fState = kSimple_State; + } else { + // back up by 1 DX, so that next() will put us in a correct starting + // position. + fCurrOffset.set(fClippedBounds.left() - fDelta, + fClippedBounds.top()); + fState = kComplex_State; + } +} + +SkDeviceLooper::~SkDeviceLooper() { +} + +void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const { + SkASSERT(kDone_State != fState); + SkASSERT(fCurrBitmap); + SkASSERT(fCurrRC); + + *dst = src; + dst->offset(SkIntToScalar(-fCurrOffset.fX), + SkIntToScalar(-fCurrOffset.fY)); +} + +void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const { + SkASSERT(kDone_State != fState); + SkASSERT(fCurrBitmap); + SkASSERT(fCurrRC); + + *dst = src; + dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), + SkIntToScalar(-fCurrOffset.fY)); +} + +bool SkDeviceLooper::computeCurrBitmapAndClip() { + SkASSERT(kComplex_State == fState); + + SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(), + fDelta, fDelta); + if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) { + fSubsetRC.setEmpty(); + } else { + fSubsetBitmap.lockPixels(); + fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC); + (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), + SkRegion::kIntersect_Op); + } + + fCurrBitmap = &fSubsetBitmap; + fCurrRC = &fSubsetRC; + return !fCurrRC->isEmpty(); +} + +static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) { + // can we move to the right? + if (offset->x() + delta < boundary.right()) { + offset->fX += delta; + return true; + } + + // reset to the left, but move down a row + offset->fX = boundary.left(); + if (offset->y() + delta < boundary.bottom()) { + offset->fY += delta; + return true; + } + + // offset is now outside of boundary, so we're done + return false; +} + +bool SkDeviceLooper::next() { + switch (fState) { + case kDone_State: + // in theory, we should not get called here, since we must have + // previously returned false, but we check anyway. + break; + + case kSimple_State: + // first time for simple + if (NULL == fCurrBitmap) { + fCurrBitmap = &fBaseBitmap; + fCurrRC = &fBaseRC; + fCurrOffset.set(0, 0); + return true; + } + // 2nd time for simple, we are done + break; + + case kComplex_State: + // need to propogate fCurrOffset through clippedbounds + // left to right, until we wrap around and move down + + while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) { + if (this->computeCurrBitmapAndClip()) { + return true; + } + } + break; + } + fState = kDone_State; + return false; +} diff --git a/gfx/skia/trunk/src/core/SkDeviceLooper.h b/gfx/skia/trunk/src/core/SkDeviceLooper.h new file mode 100644 index 000000000000..a218345ae8b6 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDeviceLooper.h @@ -0,0 +1,96 @@ +/* + * 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 SkDeviceLooper_DEFINED +#define SkDeviceLooper_DEFINED + +#include "SkBitmap.h" +#include "SkMatrix.h" +#include "SkRasterClip.h" + +/** + * Helper class to manage "tiling" a large coordinate space into managable + * chunks, where managable means areas that are <= some max critical coordinate + * size. + * + * The constructor takes an antialiasing bool, which affects what this maximum + * allowable size is: If we're drawing BW, then we need coordinates to stay + * safely within fixed-point range (we use +- 16K, to give ourselves room to + * add/subtract two fixed values and still be in range. If we're drawing AA, + * then we reduce that size by the amount that the supersampler scan converter + * needs (at the moment, that is 4X, so the "safe" range is +- 4K). + * + * For performance reasons, the class first checks to see if any help is needed + * at all, and if not (i.e. the specified bounds and base bitmap area already + * in the safe-zone, then the class does nothing (effectively). + */ +class SkDeviceLooper { +public: + SkDeviceLooper(const SkBitmap& base, const SkRasterClip&, + const SkIRect& bounds, bool aa); + ~SkDeviceLooper(); + + const SkBitmap& getBitmap() const { + SkASSERT(kDone_State != fState); + SkASSERT(fCurrBitmap); + return *fCurrBitmap; + } + + const SkRasterClip& getRC() const { + SkASSERT(kDone_State != fState); + SkASSERT(fCurrRC); + return *fCurrRC; + } + + void mapRect(SkRect* dst, const SkRect& src) const; + void mapMatrix(SkMatrix* dst, const SkMatrix& src) const; + + /** + * Call next to setup the looper to return a valid coordinate chunk. + * Each time this returns true, it is safe to call mapRect() and + * mapMatrix(), to convert from "global" coordinate values to ones that + * are local to this chunk. + * + * When next() returns false, the list of chunks is done, and mapRect() + * and mapMatrix() should no longer be called. + */ + bool next(); + +private: + const SkBitmap& fBaseBitmap; + const SkRasterClip& fBaseRC; + + enum State { + kDone_State, // iteration is complete, getters will assert + kSimple_State, // no translate/clip mods needed + kComplex_State + }; + + // storage for our tiled versions. Perhaps could use SkTLazy + SkBitmap fSubsetBitmap; + SkRasterClip fSubsetRC; + + const SkBitmap* fCurrBitmap; + const SkRasterClip* fCurrRC; + SkIRect fClippedBounds; + SkIPoint fCurrOffset; + int fDelta; + State fState; + + enum Delta { + kBW_Delta = 1 << 14, // 16K, gives room to spare for fixedpoint + kAA_Delta = kBW_Delta >> 2 // supersample 4x + }; + + bool fitsInDelta(const SkIRect& r) const { + return r.right() < fDelta && r.bottom() < fDelta; + } + + bool computeCurrBitmapAndClip(); +}; + +#endif diff --git a/gfx/skia/src/core/SkDeviceProfile.cpp b/gfx/skia/trunk/src/core/SkDeviceProfile.cpp similarity index 97% rename from gfx/skia/src/core/SkDeviceProfile.cpp rename to gfx/skia/trunk/src/core/SkDeviceProfile.cpp index ce3e566397e8..8d60151f6f29 100644 --- a/gfx/skia/src/core/SkDeviceProfile.cpp +++ b/gfx/skia/trunk/src/core/SkDeviceProfile.cpp @@ -7,8 +7,7 @@ #include "SkDeviceProfile.h" - -SK_DEFINE_INST_COUNT(SkDeviceProfile) +#include "SkThread.h" #define DEFAULT_GAMMAEXP 2.2f #define DEFAULT_CONTRASTSCALE 0.5f @@ -45,7 +44,7 @@ SkDeviceProfile* SkDeviceProfile::Create(float gammaExp, return SkNEW_ARGS(SkDeviceProfile, (gammaExp, contrast, config, level)); } -static SkMutex gMutex; +SK_DECLARE_STATIC_MUTEX(gMutex); static SkDeviceProfile* gDefaultProfile; static SkDeviceProfile* gGlobalProfile; diff --git a/gfx/skia/src/core/SkDeviceProfile.h b/gfx/skia/trunk/src/core/SkDeviceProfile.h similarity index 100% rename from gfx/skia/src/core/SkDeviceProfile.h rename to gfx/skia/trunk/src/core/SkDeviceProfile.h diff --git a/gfx/skia/trunk/src/core/SkDiscardableMemory.h b/gfx/skia/trunk/src/core/SkDiscardableMemory.h new file mode 100644 index 000000000000..f3159fe2af0c --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDiscardableMemory.h @@ -0,0 +1,65 @@ +/* + * 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 SkDiscardableMemory_DEFINED +#define SkDiscardableMemory_DEFINED + +#include "SkRefCnt.h" +#include "SkTypes.h" + +/** + * Interface for discardable memory. Implementation is provided by the + * embedder. + */ +class SK_API SkDiscardableMemory { +public: + /** + * Factory method that creates, initializes and locks an SkDiscardableMemory + * object. If either of these steps fails, a NULL pointer will be returned. + */ + static SkDiscardableMemory* Create(size_t bytes); + + /** + * Factory class that creates, initializes and locks an SkDiscardableMemory + * object. If either of these steps fails, a NULL pointer will be returned. + */ + class Factory : public SkRefCnt { + public: + virtual SkDiscardableMemory* create(size_t bytes) = 0; + private: + typedef SkRefCnt INHERITED; + }; + + /** Must not be called while locked. + */ + virtual ~SkDiscardableMemory() {} + + /** + * Locks the memory, prevent it from being discarded. Once locked. you may + * obtain a pointer to that memory using the data() method. + * + * lock() may return false, indicating that the underlying memory was + * discarded and that the lock failed. + * + * Nested calls to lock are not allowed. + */ + virtual bool lock() = 0; + + /** + * Returns the current pointer for the discardable memory. This call is ONLY + * valid when the discardable memory object is locked. + */ + virtual void* data() = 0; + + /** + * Unlock the memory so that it can be purged by the system. Must be called + * after every successful lock call. + */ + virtual void unlock() = 0; +}; + +#endif diff --git a/gfx/skia/src/core/SkDither.cpp b/gfx/skia/trunk/src/core/SkDither.cpp similarity index 100% rename from gfx/skia/src/core/SkDither.cpp rename to gfx/skia/trunk/src/core/SkDither.cpp diff --git a/gfx/skia/src/core/SkDraw.cpp b/gfx/skia/trunk/src/core/SkDraw.cpp similarity index 89% rename from gfx/skia/src/core/SkDraw.cpp rename to gfx/skia/trunk/src/core/SkDraw.cpp index 3c3e3a34fd36..5f81073068b9 100644 --- a/gfx/skia/src/core/SkDraw.cpp +++ b/gfx/skia/trunk/src/core/SkDraw.cpp @@ -5,19 +5,20 @@ * found in the LICENSE file. */ - #include "SkDraw.h" #include "SkBlitter.h" #include "SkBounder.h" #include "SkCanvas.h" #include "SkColorPriv.h" #include "SkDevice.h" +#include "SkDeviceLooper.h" #include "SkFixed.h" #include "SkMaskFilter.h" #include "SkPaint.h" #include "SkPathEffect.h" #include "SkRasterClip.h" #include "SkRasterizer.h" +#include "SkRRect.h" #include "SkScan.h" #include "SkShader.h" #include "SkString.h" @@ -43,12 +44,18 @@ public: fBlitter = NULL; } SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix, - const SkPaint& paint) { + const SkPaint& paint, bool drawCoverage = false) { fBlitter = SkBlitter::Choose(device, matrix, paint, - fStorage, sizeof(fStorage)); + fStorage, sizeof(fStorage), drawCoverage); } - ~SkAutoBlitterChoose(); + ~SkAutoBlitterChoose() { + if ((void*)fBlitter == (void*)fStorage) { + fBlitter->~SkBlitter(); + } else { + SkDELETE(fBlitter); + } + } SkBlitter* operator->() { return fBlitter; } SkBlitter* get() const { return fBlitter; } @@ -64,14 +71,7 @@ private: SkBlitter* fBlitter; uint32_t fStorage[kBlitterStorageLongCount]; }; - -SkAutoBlitterChoose::~SkAutoBlitterChoose() { - if ((void*)fBlitter == (void*)fStorage) { - fBlitter->~SkBlitter(); - } else { - SkDELETE(fBlitter); - } -} +#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose) /** * Since we are providing the storage for the shader (to avoid the perf cost @@ -111,6 +111,7 @@ private: SkPaint fPaint; // copy of caller's paint (which we then modify) uint32_t fStorage[kBlitterStorageLongCount]; }; +#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall) /////////////////////////////////////////////////////////////////////////////// @@ -150,11 +151,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) { @@ -206,12 +207,6 @@ static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap, } // SkDebugf("--- D32_Src_BitmapXferProc\n"); return D32_Src_BitmapXferProc; - case SkBitmap::kARGB_4444_Config: - if (data) { - *data = SkPixel32ToPixel4444(pmc); - } -// SkDebugf("--- D16_Src_BitmapXferProc\n"); - return D16_Src_BitmapXferProc; case SkBitmap::kRGB_565_Config: if (data) { *data = SkPixel32ToPixel16(pmc); @@ -242,7 +237,6 @@ static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect, case SkBitmap::kARGB_8888_Config: shiftPerPixel = 2; break; - case SkBitmap::kARGB_4444_Config: case SkBitmap::kRGB_565_Config: shiftPerPixel = 1; break; @@ -389,8 +383,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); } @@ -559,7 +553,7 @@ static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode, SkRect bounds; SkScalar inset = paint.getStrokeWidth(); - bounds.set(pts, count); + bounds.set(pts, SkToInt(count)); bounds.inset(-inset, -inset); matrix.mapRect(&bounds); @@ -616,14 +610,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; @@ -864,48 +858,56 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { } // look for the quick exit, before we build a blitter - if (true) { - SkIRect ir; - devRect.roundOut(&ir); - if (paint.getStyle() != SkPaint::kFill_Style) { - // extra space for hairlines - ir.inset(-1, -1); - } - if (fRC->quickReject(ir)) - return; + SkIRect ir; + devRect.roundOut(&ir); + if (paint.getStyle() != SkPaint::kFill_Style) { + // extra space for hairlines + ir.inset(-1, -1); + } + if (fRC->quickReject(ir)) { + return; } - SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint); - const SkRasterClip& clip = *fRC; - SkBlitter* blitter = blitterStorage.get(); + SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias()); + while (looper.next()) { + SkRect localDevRect; + looper.mapRect(&localDevRect, devRect); + SkMatrix localMatrix; + looper.mapMatrix(&localMatrix, matrix); - // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter - // case we are also hairline (if we've gotten to here), which devolves to - // effectively just kFill - switch (rtype) { - case kFill_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiFillRect(devRect, clip, blitter); - } else { - SkScan::FillRect(devRect, clip, blitter); - } - break; - case kStroke_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter); - } else { - SkScan::FrameRect(devRect, strokeSize, clip, blitter); - } - break; - case kHair_RectType: - if (paint.isAntiAlias()) { - SkScan::AntiHairRect(devRect, clip, blitter); - } else { - SkScan::HairRect(devRect, clip, blitter); - } - break; - default: - SkDEBUGFAIL("bad rtype"); + SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, + paint); + const SkRasterClip& clip = looper.getRC(); + SkBlitter* blitter = blitterStorage.get(); + + // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter + // case we are also hairline (if we've gotten to here), which devolves to + // effectively just kFill + switch (rtype) { + case kFill_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFillRect(localDevRect, clip, blitter); + } else { + SkScan::FillRect(localDevRect, clip, blitter); + } + break; + case kStroke_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); + } else { + SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); + } + break; + case kHair_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiHairRect(localDevRect, clip, blitter); + } else { + SkScan::HairRect(localDevRect, clip, blitter); + } + break; + default: + SkDEBUGFAIL("bad rtype"); + } } } @@ -970,24 +972,11 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { } } -bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, - SkScalar* coverage) { - SkASSERT(coverage); - if (SkPaint::kStroke_Style != paint.getStyle()) { - return false; - } - SkScalar strokeWidth = paint.getStrokeWidth(); - if (0 == strokeWidth) { - *coverage = SK_Scalar1; - return true; - } +bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, + SkScalar* coverage) { + SkASSERT(strokeWidth > 0); + // We need to try to fake a thick-stroke with a modulated hairline. - // if we get here, we need to try to fake a thick-stroke with a modulated - // hairline - - if (!paint.isAntiAlias()) { - return false; - } if (matrix.hasPerspective()) { return false; } @@ -999,14 +988,62 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, SkScalar len0 = fast_len(dst[0]); SkScalar len1 = fast_len(dst[1]); if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { - *coverage = SkScalarAve(len0, len1); + if (NULL != coverage) { + *coverage = SkScalarAve(len0, len1); + } return true; } return false; } +void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { + SkDEBUGCODE(this->validate()); + + if (fRC->isEmpty()) { + return; + } + + { + // TODO: Investigate optimizing these options. They are in the same + // order as SkDraw::drawPath, which handles each case. It may be + // that there is no way to optimize for these using the SkRRect path. + SkScalar coverage; + if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { + goto DRAW_PATH; + } + + if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { + goto DRAW_PATH; + } + + if (paint.getRasterizer()) { + goto DRAW_PATH; + } + } + + if (paint.getMaskFilter()) { + // Transform the rrect into device space. + SkRRect devRRect; + if (rrect.transform(*fMatrix, &devRRect)) { + SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); + if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, + fBounder, blitter.get(), + SkPaint::kFill_Style)) { + return; // filterRRect() called the blitter, so we're done + } + } + } + +DRAW_PATH: + // Now fall back to the default case of using a path. + SkPath path; + path.addRRect(rrect); + this->drawPath(path, paint, NULL, true); +} + void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, - const SkMatrix* prePathMatrix, bool pathIsMutable) const { + const SkMatrix* prePathMatrix, bool pathIsMutable, + bool drawCoverage) const { SkDEBUGCODE(this->validate();) // nothing to draw @@ -1095,7 +1132,7 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, // transform the path into device space pathPtr->transform(*matrix, devPathPtr); - SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint); + SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage); if (paint->getMaskFilter()) { SkPaint::Style style = doFill ? SkPaint::kFill_Style : @@ -1139,11 +1176,11 @@ static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, const SkPaint& paint) const { - SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config); + SkASSERT(bitmap.config() == SkBitmap::kA8_Config); 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()) { @@ -1247,17 +1284,10 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, // nothing to draw if (fRC->isEmpty() || bitmap.width() == 0 || bitmap.height() == 0 || - bitmap.getConfig() == SkBitmap::kNo_Config) { + bitmap.config() == SkBitmap::kNo_Config) { return; } -#ifndef SK_ALLOW_OVER_32K_BITMAPS - // run away on too-big bitmaps for now (exceed 16.16) - if (bitmap.width() > 32767 || bitmap.height() > 32767) { - return; - } -#endif - SkPaint paint(origPaint); paint.setStyle(SkPaint::kFill_Style); @@ -1272,15 +1302,15 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, if (fBounder && just_translate(matrix, bitmap)) { SkIRect ir; - int32_t ix = SkScalarRound(matrix.getTranslateX()); - int32_t iy = SkScalarRound(matrix.getTranslateY()); + int32_t ix = SkScalarRoundToInt(matrix.getTranslateX()); + int32_t iy = SkScalarRoundToInt(matrix.getTranslateY()); ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); if (!fBounder->doIRect(ir)) { return; } } - if (bitmap.getConfig() != SkBitmap::kA8_Config && + if (bitmap.config() != SkBitmap::kA8_Config && just_translate(matrix, bitmap)) { // // It is safe to call lock pixels now, since we know the matrix is @@ -1290,8 +1320,8 @@ 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, @@ -1313,7 +1343,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, SkDraw draw(*this); draw.fMatrix = &matrix; - if (bitmap.getConfig() == SkBitmap::kA8_Config) { + if (bitmap.config() == SkBitmap::kA8_Config) { draw.drawBitmapAsMask(bitmap, paint); } else { SkAutoBitmapShaderInstall install(bitmap, paint); @@ -1333,7 +1363,7 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, // nothing to draw if (fRC->isEmpty() || bitmap.width() == 0 || bitmap.height() == 0 || - bitmap.getConfig() == SkBitmap::kNo_Config) { + bitmap.config() == SkBitmap::kNo_Config) { return; } @@ -1412,6 +1442,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 { @@ -1451,8 +1496,8 @@ 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); + 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) || @@ -1489,14 +1534,14 @@ static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, mask.fRowBytes = glyph.rowBytes(); mask.fFormat = static_cast(glyph.fMaskFormat); mask.fImage = aa; - state.fBlitter->blitMask(mask, *bounds); + 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); + int left = SkFixedFloorToInt(fx); + int top = SkFixedFloorToInt(fy); SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); SkASSERT(!state.fClip->isRect()); SkASSERT(NULL == state.fBounder); @@ -1523,7 +1568,7 @@ static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, mask.fFormat = static_cast(glyph.fMaskFormat); mask.fImage = (uint8_t*)aa; do { - state.fBlitter->blitMask(mask, cr); + state.blitMask(mask, cr); clipper.next(); } while (!clipper.done()); } @@ -1532,8 +1577,8 @@ 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); + int left = SkFixedFloorToInt(fx); + int top = SkFixedFloorToInt(fy); SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); SkMask mask; @@ -1563,7 +1608,7 @@ static void D1G_Bounder(const SkDraw1Glyph& state, mask.fFormat = static_cast(glyph.fMaskFormat); mask.fImage = (uint8_t*)aa; do { - state.fBlitter->blitMask(mask, cr); + state.blitMask(mask, cr); clipper.next(); } while (!clipper.done()); } @@ -1573,8 +1618,8 @@ static void D1G_Bounder(const SkDraw1Glyph& state, static void D1G_Bounder_AAClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) { - int left = SkFixedFloor(fx); - int top = SkFixedFloor(fy); + int left = SkFixedFloorToInt(fx); + int top = SkFixedFloorToInt(fy); SkIRect bounds; bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); @@ -1592,11 +1637,12 @@ static bool needsRasterTextBlit(const SkDraw& draw) { } SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, - SkGlyphCache* cache) { + SkGlyphCache* cache, const SkPaint& pnt) { fDraw = draw; fBounder = draw->fBounder; fBlitter = blitter; fCache = cache; + fPaint = &pnt; if (cache->isSubpixel()) { fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); @@ -1636,6 +1682,17 @@ SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, } } +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); + + fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint); +} + /////////////////////////////////////////////////////////////////////////////// void SkDraw::drawText(const char text[], size_t byteLength, @@ -1651,9 +1708,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, // SkScalarRec doesn't currently have a way of representing hairline stroke and // will fill if its frame-width is 0. - if (/*paint.isLinearText() ||*/ - (fMatrix->hasPerspective()) || - (0 == paint.getStrokeWidth() && SkPaint::kStroke_Style == paint.getStyle())) { + if (ShouldDrawTextAsPaths(paint, *fMatrix)) { this->drawText_asPaths(text, byteLength, x, y, paint); return; } @@ -1704,7 +1759,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, SkAutoKern autokern; SkDraw1Glyph d1g; - SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache); + SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); SkFixed fxMask = ~0; SkFixed fyMask = ~0; @@ -1730,6 +1785,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, if (glyph.fWidth) { proc(d1g, fx, fy, glyph); } + fx += glyph.fAdvanceX; fy += glyph.fAdvanceY; } @@ -1740,19 +1796,16 @@ void SkDraw::drawText(const char text[], size_t byteLength, // 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) { +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) { +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) { +static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) { dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, SkScalarToFixed(loc.fY) - glyph.fAdvanceY); } @@ -1767,6 +1820,32 @@ static AlignProc pick_align_proc(SkPaint::Align align) { 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; @@ -1827,6 +1906,48 @@ TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) { ////////////////////////////////////////////////////////////////////////////// +void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, + const SkScalar pos[], SkScalar constY, + int scalarsPerPosition, + const SkPaint& origPaint) const { + // setup our std paint, in hopes of getting hits in the cache + SkPaint paint(origPaint); + SkScalar matrixScale = paint.setupForAsPaths(); + + SkMatrix matrix; + matrix.setScale(matrixScale, matrixScale); + + 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); + + 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 loc; + alignProc(tms.fLoc, glyph, &loc); + + matrix[SkMatrix::kMTransX] = loc.fX; + matrix[SkMatrix::kMTransY] = loc.fY; + if (fDevice) { + fDevice->drawPath(*this, *path, paint, &matrix, false); + } else { + this->drawPath(*path, paint, &matrix, false); + } + } + } + pos += scalarsPerPosition; + } +} + void SkDraw::drawPosText(const char text[], size_t byteLength, const SkScalar pos[], SkScalar constY, int scalarsPerPosition, const SkPaint& paint) const { @@ -1840,10 +1961,9 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, return; } - if (/*paint.isLinearText() ||*/ - (fMatrix->hasPerspective())) { - // TODO !!!! -// this->drawText_asPaths(text, byteLength, x, y, paint); + if (ShouldDrawTextAsPaths(paint, *fMatrix)) { + this->drawPosText_asPaths(text, byteLength, pos, constY, + scalarsPerPosition, paint); return; } @@ -1866,7 +1986,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, const char* stop = text + byteLength; AlignProc alignProc = pick_align_proc(paint.getTextAlign()); SkDraw1Glyph d1g; - SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache); + SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); TextMapState tms(*fMatrix, constY); TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); @@ -1891,7 +2011,6 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, if (SkPaint::kLeft_Align == paint.getTextAlign()) { while (text < stop) { tmsProc(tms, pos); - SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; @@ -2102,69 +2221,6 @@ void SkDraw::drawTextOnPath(const char text[], size_t byteLength, } } -#ifdef SK_BUILD_FOR_ANDROID -void SkDraw::drawPosTextOnPath(const char text[], size_t byteLength, - const SkPoint pos[], const SkPaint& paint, - const SkPath& path, const SkMatrix* matrix) const { - // nothing to draw - if (text == NULL || byteLength == 0 || fRC->isEmpty()) { - return; - } - - SkMatrix scaledMatrix; - SkPathMeasure meas(path, false); - - SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc( - SkPaint::kForward_TextBufferDirection, true); - - // Copied (modified) from SkTextToPathIter constructor to setup paint - SkPaint tempPaint(paint); - - tempPaint.setLinearText(true); - tempPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup - - if (tempPaint.getPathEffect() == NULL && !(tempPaint.getStrokeWidth() > 0 - && tempPaint.getStyle() != SkPaint::kFill_Style)) { - tempPaint.setStyle(SkPaint::kFill_Style); - tempPaint.setPathEffect(NULL); - } - // End copied from SkTextToPathIter constructor - - // detach cache - SkGlyphCache* cache = tempPaint.detachCache(NULL, NULL); - - // Must set scale, even if 1 - SkScalar scale = SK_Scalar1; - scaledMatrix.setScale(scale, scale); - - // Loop over all glyph ids - for (const char* stop = text + byteLength; text < stop; pos++) { - - const SkGlyph& glyph = glyphCacheProc(cache, &text); - SkPath tmp; - - const SkPath* glyphPath = cache->findPath(glyph); - if (glyphPath == NULL) { - continue; - } - - SkMatrix m(scaledMatrix); - m.postTranslate(pos->fX, 0); - - if (matrix) { - m.postConcat(*matrix); - } - - morphpath(&tmp, *glyphPath, meas, m); - this->drawPath(tmp, tempPaint); - - } - - // re-attach cache - SkGlyphCache::AttachCache(cache); -} -#endif - /////////////////////////////////////////////////////////////////////////////// struct VertState { @@ -2326,7 +2382,7 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) protected: - SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {} + SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {} private: SkMatrix fDstToUnit; @@ -2473,7 +2529,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, if (releaseMode) { xmode->unref(); } - shader = compose; } } @@ -2611,16 +2666,16 @@ bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1, if (v0 > v1) { SkTSwap(v0, v1); } - r.fLeft = SkScalarFloor(v0); - r.fRight = SkScalarCeil(v1); + r.fLeft = SkScalarFloorToInt(v0); + r.fRight = SkScalarCeilToInt(v1); v0 = pt0.fY; v1 = pt1.fY; if (v0 > v1) { SkTSwap(v0, v1); } - r.fTop = SkScalarFloor(v0); - r.fBottom = SkScalarCeil(v1); + r.fTop = SkScalarFloorToInt(v0); + r.fBottom = SkScalarCeilToInt(v1); if (paint.isAntiAlias()) { r.inset(-1, -1); diff --git a/gfx/skia/trunk/src/core/SkDrawLooper.cpp b/gfx/skia/trunk/src/core/SkDrawLooper.cpp new file mode 100644 index 000000000000..bac2d969c050 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkDrawLooper.cpp @@ -0,0 +1,56 @@ +/* + * 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 "SkDrawLooper.h" +#include "SkCanvas.h" +#include "SkMatrix.h" +#include "SkPaint.h" +#include "SkRect.h" + +bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) { + SkCanvas canvas; + + this->init(&canvas); + for (;;) { + SkPaint p(paint); + if (this->next(&canvas, &p)) { + p.setLooper(NULL); + if (!p.canComputeFastBounds()) { + return false; + } + } else { + break; + } + } + return true; +} + +void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src, + SkRect* dst) { + SkCanvas canvas; + + *dst = src; // catch case where there are no loops + this->init(&canvas); + for (bool firstTime = true;; firstTime = false) { + SkPaint p(paint); + if (this->next(&canvas, &p)) { + SkRect r(src); + + p.setLooper(NULL); + p.computeFastBounds(r, &r); + canvas.getTotalMatrix().mapRect(&r); + + if (firstTime) { + *dst = r; + } else { + dst->join(r); + } + } else { + break; + } + } +} diff --git a/gfx/skia/src/core/SkDrawProcs.h b/gfx/skia/trunk/src/core/SkDrawProcs.h similarity index 55% rename from gfx/skia/src/core/SkDrawProcs.h rename to gfx/skia/trunk/src/core/SkDrawProcs.h index 68cc9ff08cd1..44532298f004 100644 --- a/gfx/skia/src/core/SkDrawProcs.h +++ b/gfx/skia/trunk/src/core/SkDrawProcs.h @@ -8,6 +8,7 @@ #ifndef SkDrawProcs_DEFINED #define SkDrawProcs_DEFINED +#include "SkBlitter.h" #include "SkDraw.h" class SkAAClip; @@ -20,6 +21,7 @@ struct SkDraw1Glyph { const SkAAClip* fAAClip; SkBlitter* fBlitter; SkGlyphCache* fCache; + const SkPaint* fPaint; SkIRect fClipBounds; /** Half the sampling frequency of the rasterized glyph in x. */ SkFixed fHalfSampleX; @@ -35,19 +37,54 @@ struct SkDraw1Glyph { */ typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&); - Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache); + Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, + const SkPaint&); + + // call this instead of fBlitter->blitMask() since this wrapper will handle + // the case when the mask is ARGB32_Format + // + void blitMask(const SkMask& mask, const SkIRect& clip) const { + if (SkMask::kARGB32_Format == mask.fFormat) { + this->blitMaskAsSprite(mask); + } else { + fBlitter->blitMask(mask, clip); + } + } + + // mask must be kARGB32_Format + void blitMaskAsSprite(const SkMask& mask) const; }; struct SkDrawProcs { SkDraw1Glyph::Proc fD1GProc; }; +bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&, + SkScalar* coverage); + /** * If the current paint is set to stroke and the stroke-width when applied to * the matrix is <= 1.0, then this returns true, and sets coverage (simulating * a stroke by drawing a hairline with partial coverage). If any of these * conditions are false, then this returns false and coverage is ignored. */ -bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage); +inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, + SkScalar* coverage) { + if (SkPaint::kStroke_Style != paint.getStyle()) { + return false; + } + + SkScalar strokeWidth = paint.getStrokeWidth(); + if (0 == strokeWidth) { + *coverage = SK_Scalar1; + return true; + } + + if (!paint.isAntiAlias()) { + return false; + } + + return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage); +} #endif diff --git a/gfx/skia/src/core/SkEdge.cpp b/gfx/skia/trunk/src/core/SkEdge.cpp similarity index 94% rename from gfx/skia/src/core/SkEdge.cpp rename to gfx/skia/trunk/src/core/SkEdge.cpp index 8904ca727b99..9ce255843f66 100644 --- a/gfx/skia/src/core/SkEdge.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkEdge.h b/gfx/skia/trunk/src/core/SkEdge.h similarity index 94% rename from gfx/skia/src/core/SkEdge.h rename to gfx/skia/trunk/src/core/SkEdge.h index ea7c84f78d2e..091223631fed 100644 --- a/gfx/skia/src/core/SkEdge.h +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkEdgeBuilder.cpp b/gfx/skia/trunk/src/core/SkEdgeBuilder.cpp similarity index 80% rename from gfx/skia/src/core/SkEdgeBuilder.cpp rename to gfx/skia/trunk/src/core/SkEdgeBuilder.cpp index 608a83c7c73f..c3f5dafe8d7e 100644 --- a/gfx/skia/src/core/SkEdgeBuilder.cpp +++ b/gfx/skia/trunk/src/core/SkEdgeBuilder.cpp @@ -150,7 +150,15 @@ 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]) { + SkPoint monoX[5]; + int n = SkChopQuadAtYExtrema(pts, monoX); + for (int i = 0; i <= n; i++) { + builder->addQuad(&monoX[i * 2]); + } } int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, @@ -159,6 +167,8 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, fList.reset(); fShiftUp = shiftUp; + SkScalar conicTol = SK_ScalarHalf * (1 << shiftUp); + if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { return this->buildPoly(path, iclip, shiftUp); } @@ -192,6 +202,24 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, this->addClipper(&clipper); } break; + case SkPath::kConic_Verb: { + const int MAX_POW2 = 4; + const int MAX_QUADS = 1 << MAX_POW2; + const int MAX_QUAD_PTS = 1 + 2 * MAX_QUADS; + SkPoint storage[MAX_QUAD_PTS]; + + SkConic conic; + conic.set(pts, iter.conicWeight()); + int pow2 = conic.computeQuadPOW2(conicTol); + pow2 = SkMin32(pow2, MAX_POW2); + int quadCount = conic.chopIntoQuadsPOW2(storage, pow2); + SkASSERT(quadCount <= MAX_QUADS); + for (int i = 0; i < quadCount; ++i) { + if (clipper.clipQuad(&storage[i * 2], clip)) { + this->addClipper(&clipper); + } + } + } break; case SkPath::kCubic_Verb: if (clipper.clipCubic(pts, clip)) { this->addClipper(&clipper); @@ -214,13 +242,25 @@ int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, this->addLine(pts); break; case SkPath::kQuad_Verb: { - SkPoint monoX[5]; - int n = SkChopQuadAtYExtrema(pts, monoX); - for (int i = 0; i <= n; i++) { - this->addQuad(&monoX[i * 2]); - } + handle_quad(this, pts); break; } + case SkPath::kConic_Verb: { + const int MAX_POW2 = 4; + const int MAX_QUADS = 1 << MAX_POW2; + const int MAX_QUAD_PTS = 1 + 2 * MAX_QUADS; + SkPoint storage[MAX_QUAD_PTS]; + + SkConic conic; + conic.set(pts, iter.conicWeight()); + int pow2 = conic.computeQuadPOW2(conicTol); + pow2 = SkMin32(pow2, MAX_POW2); + int quadCount = conic.chopIntoQuadsPOW2(storage, pow2); + SkASSERT(quadCount <= MAX_QUADS); + for (int i = 0; i < quadCount; ++i) { + handle_quad(this, &storage[i * 2]); + } + } break; case SkPath::kCubic_Verb: { SkPoint monoY[10]; int n = SkChopCubicAtYExtrema(pts, monoY); diff --git a/gfx/skia/src/core/SkEdgeBuilder.h b/gfx/skia/trunk/src/core/SkEdgeBuilder.h similarity index 99% rename from gfx/skia/src/core/SkEdgeBuilder.h rename to gfx/skia/trunk/src/core/SkEdgeBuilder.h index b296f773c1b1..f9e5976e17f6 100644 --- a/gfx/skia/src/core/SkEdgeBuilder.h +++ b/gfx/skia/trunk/src/core/SkEdgeBuilder.h @@ -40,6 +40,7 @@ private: int fShiftUp; +public: void addLine(const SkPoint pts[]); void addQuad(const SkPoint pts[]); void addCubic(const SkPoint pts[]); diff --git a/gfx/skia/src/core/SkEdgeClipper.cpp b/gfx/skia/trunk/src/core/SkEdgeClipper.cpp similarity index 97% rename from gfx/skia/src/core/SkEdgeClipper.cpp rename to gfx/skia/trunk/src/core/SkEdgeClipper.cpp index b166bc67f08f..00a1dd2494bf 100644 --- a/gfx/skia/src/core/SkEdgeClipper.cpp +++ b/gfx/skia/trunk/src/core/SkEdgeClipper.cpp @@ -283,11 +283,12 @@ static void chop_cubic_in_Y(SkPoint pts[4], const SkRect& clip) { SkPoint tmp[7]; SkChopCubicAt(pts, tmp, t); - // tmp[3, 4].fY should all be to the below clip.fTop, and - // still be monotonic in Y. Since we can't trust the numerics of + // tmp[3, 4, 5].fY should all be to the below clip.fTop. + // Since we can't trust the numerics of // the chopper, we force those conditions now tmp[3].fY = clip.fTop; clamp_ge(tmp[4].fY, clip.fTop); + clamp_ge(tmp[5].fY, clip.fTop); pts[0] = tmp[3]; pts[1] = tmp[4]; @@ -361,12 +362,12 @@ void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { SkChopCubicAt(pts, tmp, t); this->appendVLine(clip.fLeft, tmp[0].fY, tmp[3].fY, reverse); - // tmp[3, 4, 5].fX should all be to the right of clip.fLeft, and - // still be monotonic in X. Since we can't trust the numerics of + // tmp[3, 4, 5].fX should all be to the right of clip.fLeft. + // Since we can't trust the numerics of // the chopper, we force those conditions now tmp[3].fX = clip.fLeft; clamp_ge(tmp[4].fX, clip.fLeft); - clamp_ge(tmp[5].fX, tmp[4].fX); + clamp_ge(tmp[5].fX, clip.fLeft); pts[0] = tmp[3]; pts[1] = tmp[4]; @@ -387,7 +388,7 @@ void SkEdgeClipper::clipMonoCubic(const SkPoint src[4], const SkRect& clip) { SkChopCubicAt(pts, tmp, t); tmp[3].fX = clip.fRight; clamp_le(tmp[2].fX, clip.fRight); - clamp_le(tmp[1].fX, tmp[2].fX); + clamp_le(tmp[1].fX, clip.fRight); this->appendCubic(tmp, reverse); this->appendVLine(clip.fRight, tmp[3].fY, tmp[6].fY, reverse); @@ -412,12 +413,9 @@ bool SkEdgeClipper::clipCubic(const SkPoint srcPts[4], const SkRect& clip) { SkPoint monoY[10]; int countY = SkChopCubicAtYExtrema(srcPts, monoY); for (int y = 0; y <= countY; y++) { - // sk_assert_monotonic_y(&monoY[y * 3], 4); SkPoint monoX[10]; int countX = SkChopCubicAtXExtrema(&monoY[y * 3], monoX); for (int x = 0; x <= countX; x++) { - // sk_assert_monotonic_y(&monoX[x * 3], 4); - // sk_assert_monotonic_x(&monoX[x * 3], 4); this->clipMonoCubic(&monoX[x * 3], clip); SkASSERT(fCurrVerb - fVerbs < kMaxVerbs); SkASSERT(fCurrPoint - fPoints <= kMaxPoints); diff --git a/gfx/skia/src/core/SkEdgeClipper.h b/gfx/skia/trunk/src/core/SkEdgeClipper.h similarity index 100% rename from gfx/skia/src/core/SkEdgeClipper.h rename to gfx/skia/trunk/src/core/SkEdgeClipper.h diff --git a/gfx/skia/trunk/src/core/SkError.cpp b/gfx/skia/trunk/src/core/SkError.cpp new file mode 100644 index 000000000000..9e8ff2ddef01 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkError.cpp @@ -0,0 +1,143 @@ + +/* + * 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 "SkTLS.h" +#include "SkTypes.h" +#include "SkError.h" +#include "SkErrorInternals.h" + +#include +#include + +namespace { + void *CreateThreadError() { + return SkNEW_ARGS(SkError, (kNoError_SkError)); + } + void DeleteThreadError(void* v) { + SkDELETE(reinterpret_cast(v)); + } + #define THREAD_ERROR \ + (*reinterpret_cast(SkTLS::Get(CreateThreadError, DeleteThreadError))) + + void *CreateThreadErrorCallback() { + return SkNEW_ARGS(SkErrorCallbackFunction, (SkErrorInternals::DefaultErrorCallback)); + } + void DeleteThreadErrorCallback(void* v) { + SkDELETE(reinterpret_cast(v)); + } + + #define THREAD_ERROR_CALLBACK \ + *(reinterpret_cast(SkTLS::Get(CreateThreadErrorCallback, \ + DeleteThreadErrorCallback))) + + void *CreateThreadErrorContext() { + return SkNEW_ARGS(void **, (NULL)); + } + void DeleteThreadErrorContext(void* v) { + SkDELETE(reinterpret_cast(v)); + } + #define THREAD_ERROR_CONTEXT \ + (*reinterpret_cast(SkTLS::Get(CreateThreadErrorContext, DeleteThreadErrorContext))) + + #define ERROR_STRING_LENGTH 2048 + + void *CreateThreadErrorString() { + return SkNEW_ARRAY(char, (ERROR_STRING_LENGTH)); + } + void DeleteThreadErrorString(void* v) { + SkDELETE_ARRAY(reinterpret_cast(v)); + } + #define THREAD_ERROR_STRING \ + (reinterpret_cast(SkTLS::Get(CreateThreadErrorString, DeleteThreadErrorString))) +} + +SkError SkGetLastError() { + return SkErrorInternals::GetLastError(); +} +void SkClearLastError() { + SkErrorInternals::ClearError(); +} +void SkSetErrorCallback(SkErrorCallbackFunction cb, void *context) { + SkErrorInternals::SetErrorCallback(cb, context); +} +const char *SkGetLastErrorString() { + return SkErrorInternals::GetLastErrorString(); +} + +// ------------ Private Error functions --------- + +void SkErrorInternals::SetErrorCallback(SkErrorCallbackFunction cb, void *context) { + if (cb == NULL) { + THREAD_ERROR_CALLBACK = SkErrorInternals::DefaultErrorCallback; + } else { + THREAD_ERROR_CALLBACK = cb; + } + THREAD_ERROR_CONTEXT = context; +} + +void SkErrorInternals::DefaultErrorCallback(SkError code, void *context) { + SkDebugf("Skia Error: %s\n", SkGetLastErrorString()); +} + +void SkErrorInternals::ClearError() { + SkErrorInternals::SetError( kNoError_SkError, "All is well" ); +} + +SkError SkErrorInternals::GetLastError() { + return THREAD_ERROR; +} + +const char *SkErrorInternals::GetLastErrorString() { + return THREAD_ERROR_STRING; +} + +void SkErrorInternals::SetError(SkError code, const char *fmt, ...) { + THREAD_ERROR = code; + va_list args; + + char *str = THREAD_ERROR_STRING; + const char *error_name = NULL; + switch( code ) { + case kNoError_SkError: + error_name = "No Error"; + break; + case kInvalidArgument_SkError: + error_name = "Invalid Argument"; + break; + case kInvalidOperation_SkError: + error_name = "Invalid Operation"; + break; + case kInvalidHandle_SkError: + error_name = "Invalid Handle"; + break; + case kInvalidPaint_SkError: + error_name = "Invalid Paint"; + break; + case kOutOfMemory_SkError: + error_name = "Out Of Memory"; + break; + case kParseError_SkError: + error_name = "Parse Error"; + break; + default: + error_name = "Unknown error"; + break; + } + + sprintf( str, "%s: ", error_name ); + int string_left = SkToInt(ERROR_STRING_LENGTH - strlen(str)); + str += strlen(str); + + va_start( args, fmt ); + vsnprintf( str, string_left, fmt, args ); + va_end( args ); + SkErrorCallbackFunction fn = THREAD_ERROR_CALLBACK; + if (fn && code != kNoError_SkError) { + fn(code, THREAD_ERROR_CONTEXT); + } +} diff --git a/gfx/skia/trunk/src/core/SkErrorInternals.h b/gfx/skia/trunk/src/core/SkErrorInternals.h new file mode 100644 index 000000000000..65ff231821d2 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkErrorInternals.h @@ -0,0 +1,27 @@ + +/* + * 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 SkErrorInternals_DEFINED +#define SkErrorInternals_DEFINED + +#include "SkError.h" + +class SkErrorInternals { + +public: + static void ClearError(); + static void SetError(SkError code, const char *fmt, ...); + static SkError GetLastError(); + static const char *GetLastErrorString(); + static void SetErrorCallback(SkErrorCallbackFunction cb, void *context); + static void DefaultErrorCallback(SkError code, void *context); +}; + + + +#endif /* SkErrorInternals_DEFINED */ diff --git a/gfx/skia/src/core/SkFDot6.h b/gfx/skia/trunk/src/core/SkFDot6.h similarity index 79% rename from gfx/skia/src/core/SkFDot6.h rename to gfx/skia/trunk/src/core/SkFDot6.h index a88ea9250127..5a0ec57f5954 100644 --- a/gfx/skia/src/core/SkFDot6.h +++ b/gfx/skia/trunk/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) * SkFloatToScalar(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/gfx/skia/src/core/SkFP.h b/gfx/skia/trunk/src/core/SkFP.h similarity index 100% rename from gfx/skia/src/core/SkFP.h rename to gfx/skia/trunk/src/core/SkFP.h diff --git a/gfx/skia/src/core/SkFilterProc.cpp b/gfx/skia/trunk/src/core/SkFilterProc.cpp similarity index 100% rename from gfx/skia/src/core/SkFilterProc.cpp rename to gfx/skia/trunk/src/core/SkFilterProc.cpp diff --git a/gfx/skia/src/core/SkFilterProc.h b/gfx/skia/trunk/src/core/SkFilterProc.h similarity index 100% rename from gfx/skia/src/core/SkFilterProc.h rename to gfx/skia/trunk/src/core/SkFilterProc.h diff --git a/gfx/skia/src/core/SkColorFilter.cpp b/gfx/skia/trunk/src/core/SkFilterShader.cpp similarity index 64% rename from gfx/skia/src/core/SkColorFilter.cpp rename to gfx/skia/trunk/src/core/SkFilterShader.cpp index 383397dbcae5..feea75b48b18 100644 --- a/gfx/skia/src/core/SkColorFilter.cpp +++ b/gfx/skia/trunk/src/core/SkFilterShader.cpp @@ -1,61 +1,30 @@ /* - * Copyright 2006 The Android Open Source Project + * 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 "SkColorFilter.h" #include "SkFilterShader.h" -#include "SkFlattenableBuffers.h" + +#include "SkColorFilter.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" #include "SkShader.h" -#include "SkUnPreMultiply.h" #include "SkString.h" -SK_DEFINE_INST_COUNT(SkColorFilter) - -bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const { - return false; -} - -bool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const { - return false; -} - -bool SkColorFilter::asComponentTable(SkBitmap*) const { - return false; -} - -void SkColorFilter::filterSpan16(const uint16_t s[], int count, uint16_t d[]) const { - SkASSERT(this->getFlags() & SkColorFilter::kHasFilter16_Flag); - SkDEBUGFAIL("missing implementation of SkColorFilter::filterSpan16"); - - if (d != s) { - memcpy(d, s, count * sizeof(uint16_t)); - } -} - -SkColor SkColorFilter::filterColor(SkColor c) const { - SkPMColor dst, src = SkPreMultiplyColor(c); - this->filterSpan(&src, 1, &dst); - return SkUnPreMultiply::PMColorToColor(dst); -} - -GrEffectRef* SkColorFilter::asNewEffect(GrContext*) const { - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - SkFilterShader::SkFilterShader(SkShader* shader, SkColorFilter* filter) { - fShader = shader; shader->ref(); - fFilter = filter; filter->ref(); + fShader = shader; + shader->ref(); + + fFilter = filter; + filter->ref(); } -SkFilterShader::SkFilterShader(SkFlattenableReadBuffer& buffer) : - INHERITED(buffer) { - fShader = buffer.readFlattenableT(); - fFilter = buffer.readFlattenableT(); +SkFilterShader::SkFilterShader(SkReadBuffer& buffer) + : INHERITED(buffer) { + fShader = buffer.readShader(); + fFilter = buffer.readColorFilter(); } SkFilterShader::~SkFilterShader() { @@ -63,7 +32,7 @@ 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); diff --git a/gfx/skia/src/core/SkFilterShader.h b/gfx/skia/trunk/src/core/SkFilterShader.h similarity index 89% rename from gfx/skia/src/core/SkFilterShader.h rename to gfx/skia/trunk/src/core/SkFilterShader.h index be19640d0e29..abb516557889 100644 --- a/gfx/skia/src/core/SkFilterShader.h +++ b/gfx/skia/trunk/src/core/SkFilterShader.h @@ -28,8 +28,8 @@ public: 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; private: SkShader* fShader; diff --git a/gfx/skia/src/core/SkFlate.cpp b/gfx/skia/trunk/src/core/SkFlate.cpp similarity index 97% rename from gfx/skia/src/core/SkFlate.cpp rename to gfx/skia/trunk/src/core/SkFlate.cpp index 8258cdcd1d5c..2b4e36d7271e 100644 --- a/gfx/skia/src/core/SkFlate.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkFlattenable.cpp b/gfx/skia/trunk/src/core/SkFlattenable.cpp similarity index 64% rename from gfx/skia/src/core/SkFlattenable.cpp rename to gfx/skia/trunk/src/core/SkFlattenable.cpp index b4efe9100484..410fe0d97495 100644 --- a/gfx/skia/src/core/SkFlattenable.cpp +++ b/gfx/skia/trunk/src/core/SkFlattenable.cpp @@ -8,11 +8,9 @@ #include "SkFlattenable.h" #include "SkPtrRecorder.h" -SK_DEFINE_INST_COUNT(SkFlattenable) - /////////////////////////////////////////////////////////////////////////////// -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() @@ -63,64 +61,84 @@ void SkRefCntSet::decPtr(void* ptr) { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#define MAX_PAIR_COUNT 1024 +#define MAX_ENTRY_COUNT 1024 -struct Pair { +struct Entry { const char* fName; SkFlattenable::Factory fFactory; + SkFlattenable::Type fType; }; static int gCount; -static Pair gPairs[MAX_PAIR_COUNT]; +static Entry gEntries[MAX_ENTRY_COUNT]; -void SkFlattenable::Register(const char name[], Factory factory) { +void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) { SkASSERT(name); SkASSERT(factory); - static bool gOnce; + static bool gOnce = false; if (!gOnce) { gCount = 0; gOnce = true; } - SkASSERT(gCount < MAX_PAIR_COUNT); + SkASSERT(gCount < MAX_ENTRY_COUNT); - gPairs[gCount].fName = name; - gPairs[gCount].fFactory = factory; + gEntries[gCount].fName = name; + gEntries[gCount].fFactory = factory; + gEntries[gCount].fType = type; gCount += 1; } #ifdef SK_DEBUG static void report_no_entries(const char* functionName) { if (!gCount) { - SkDebugf("%s has no registered name/factory pairs." - " Call SkGraphics::Init() at process initialization time.", + SkDebugf("%s has no registered name/factory/type entries." + " Call SkFlattenable::InitializeFlattenablesIfNeeded() before using gEntries", functionName); } } #endif SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { + InitializeFlattenablesIfNeeded(); #ifdef SK_DEBUG report_no_entries(__FUNCTION__); #endif - const Pair* pairs = gPairs; + const Entry* entries = gEntries; for (int i = gCount - 1; i >= 0; --i) { - if (strcmp(pairs[i].fName, name) == 0) { - return pairs[i].fFactory; + if (strcmp(entries[i].fName, name) == 0) { + return entries[i].fFactory; } } return NULL; } -const char* SkFlattenable::FactoryToName(Factory fact) { +bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) { + SkASSERT(NULL != type); + InitializeFlattenablesIfNeeded(); #ifdef SK_DEBUG report_no_entries(__FUNCTION__); #endif - const Pair* pairs = gPairs; + const Entry* entries = gEntries; for (int i = gCount - 1; i >= 0; --i) { - if (pairs[i].fFactory == fact) { - return pairs[i].fName; + if (strcmp(entries[i].fName, name) == 0) { + *type = entries[i].fType; + return true; + } + } + return false; +} + +const char* SkFlattenable::FactoryToName(Factory fact) { + InitializeFlattenablesIfNeeded(); +#ifdef SK_DEBUG + report_no_entries(__FUNCTION__); +#endif + const Entry* entries = gEntries; + for (int i = gCount - 1; i >= 0; --i) { + if (entries[i].fFactory == fact) { + return entries[i].fName; } } return NULL; diff --git a/gfx/skia/trunk/src/core/SkFlattenableBuffers.cpp b/gfx/skia/trunk/src/core/SkFlattenableBuffers.cpp new file mode 100644 index 000000000000..9da4dd9ee486 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkFlattenableBuffers.cpp @@ -0,0 +1,116 @@ + +/* + * 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 T* SkFlattenableReadBuffer::readFlattenableT() { + return static_cast(this->readFlattenable(T::GetFlattenableType())); +} + +SkColorFilter* SkFlattenableReadBuffer::readColorFilter() { + return this->readFlattenableT(); +} + +SkDrawLooper* SkFlattenableReadBuffer::readDrawLooper() { + return this->readFlattenableT(); +} + +SkImageFilter* SkFlattenableReadBuffer::readImageFilter() { + return this->readFlattenableT(); +} + +SkMaskFilter* SkFlattenableReadBuffer::readMaskFilter() { + return this->readFlattenableT(); +} + +SkPathEffect* SkFlattenableReadBuffer::readPathEffect() { + return this->readFlattenableT(); +} + +SkPixelRef* SkFlattenableReadBuffer::readPixelRef() { + return this->readFlattenableT(); +} + +SkRasterizer* SkFlattenableReadBuffer::readRasterizer() { + return this->readFlattenableT(); +} + +SkShader* SkFlattenableReadBuffer::readShader() { + return this->readFlattenableT(); +} + +SkUnitMapper* SkFlattenableReadBuffer::readUnitMapper() { + return this->readFlattenableT(); +} + +SkXfermode* SkFlattenableReadBuffer::readXfermode() { + return this->readFlattenableT(); +} + +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/gfx/skia/trunk/src/core/SkFlattenableSerialization.cpp b/gfx/skia/trunk/src/core/SkFlattenableSerialization.cpp new file mode 100644 index 000000000000..b33bca6dbbe4 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkFlattenableSerialization.cpp @@ -0,0 +1,27 @@ +/* + * 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 "SkFlattenableSerialization.h" + +#include "SkData.h" +#include "SkValidatingReadBuffer.h" +#include "SkWriteBuffer.h" + +SkData* SkValidatingSerializeFlattenable(SkFlattenable* flattenable) { + SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); + writer.writeFlattenable(flattenable); + size_t size = writer.bytesWritten(); + void* data = sk_malloc_throw(size); + writer.writeToMemory(data); + return SkData::NewFromMalloc(data, size); +} + +SkFlattenable* SkValidatingDeserializeFlattenable(const void* data, size_t size, + SkFlattenable::Type type) { + SkValidatingReadBuffer buffer(data, size); + return buffer.readFlattenable(type); +} diff --git a/gfx/skia/src/core/SkFloat.cpp b/gfx/skia/trunk/src/core/SkFloat.cpp similarity index 97% rename from gfx/skia/src/core/SkFloat.cpp rename to gfx/skia/trunk/src/core/SkFloat.cpp index 721d8ec53e31..9ec0a7a081b3 100644 --- a/gfx/skia/src/core/SkFloat.cpp +++ b/gfx/skia/trunk/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; @@ -291,7 +285,7 @@ void SkFloat::UnitTest() d.setAdd(c, b); SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt()); - SkMWCRandom rand; + SkRandom rand; int i; for (i = 0; i < 1000; i++) diff --git a/gfx/skia/src/core/SkFloat.h b/gfx/skia/trunk/src/core/SkFloat.h similarity index 96% rename from gfx/skia/src/core/SkFloat.h rename to gfx/skia/trunk/src/core/SkFloat.h index 74cd19e542fa..0d4f9b41a744 100644 --- a/gfx/skia/src/core/SkFloat.h +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkFloatBits.cpp b/gfx/skia/trunk/src/core/SkFloatBits.cpp similarity index 100% rename from gfx/skia/src/core/SkFloatBits.cpp rename to gfx/skia/trunk/src/core/SkFloatBits.cpp diff --git a/gfx/skia/src/core/SkFontDescriptor.cpp b/gfx/skia/trunk/src/core/SkFontDescriptor.cpp similarity index 97% rename from gfx/skia/src/core/SkFontDescriptor.cpp rename to gfx/skia/trunk/src/core/SkFontDescriptor.cpp index 7679d92a146a..5088ed7687bc 100644 --- a/gfx/skia/src/core/SkFontDescriptor.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkFontDescriptor.h b/gfx/skia/trunk/src/core/SkFontDescriptor.h similarity index 100% rename from gfx/skia/src/core/SkFontDescriptor.h rename to gfx/skia/trunk/src/core/SkFontDescriptor.h diff --git a/gfx/skia/trunk/src/core/SkFontHost.cpp b/gfx/skia/trunk/src/core/SkFontHost.cpp new file mode 100644 index 000000000000..fa20b47e10e7 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkFontHost.cpp @@ -0,0 +1,250 @@ +/* + * 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 "SkFontLCDConfig.h" +#include "SkOnce.h" + +static SkFontLCDConfig::LCDOrientation gLCDOrientation = SkFontLCDConfig::kHorizontal_LCDOrientation; +static SkFontLCDConfig::LCDOrder gLCDOrder = SkFontLCDConfig::kRGB_LCDOrder; + +SkFontLCDConfig::LCDOrientation SkFontLCDConfig::GetSubpixelOrientation() { + return gLCDOrientation; +} + +void SkFontLCDConfig::SetSubpixelOrientation(LCDOrientation orientation) { + gLCDOrientation = orientation; +} + +SkFontLCDConfig::LCDOrder SkFontLCDConfig::GetSubpixelOrder() { + return gLCDOrder; +} + +void SkFontLCDConfig::SetSubpixelOrder(LCDOrder order) { + gLCDOrder = order; +} + +/////////////////////////////////////////////////////////////////////////////// +// Legacy wrappers : remove from SkFontHost when webkit switches to new API + +#include "SkFontHost.h" + +SkFontHost::LCDOrientation SkFontHost::GetSubpixelOrientation() { + return (SkFontHost::LCDOrientation)SkFontLCDConfig::GetSubpixelOrientation(); +} + +void SkFontHost::SetSubpixelOrientation(LCDOrientation orientation) { + SkFontLCDConfig::SetSubpixelOrientation((SkFontLCDConfig::LCDOrientation)orientation); +} + +SkFontHost::LCDOrder SkFontHost::GetSubpixelOrder() { + return (SkFontHost::LCDOrder)SkFontLCDConfig::GetSubpixelOrder(); +} + +void SkFontHost::SetSubpixelOrder(LCDOrder order) { + SkFontLCDConfig::SetSubpixelOrder((SkFontLCDConfig::LCDOrder)order); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#include "SkFontStyle.h" + +SkFontStyle::SkFontStyle() { + fUnion.fU32 = 0; + fUnion.fR.fWeight = kNormal_Weight; + fUnion.fR.fWidth = kNormal_Width; + fUnion.fR.fSlant = kUpright_Slant; +} + +SkFontStyle::SkFontStyle(int weight, int width, Slant slant) { + fUnion.fU32 = 0; + fUnion.fR.fWeight = SkPin32(weight, kThin_Weight, kBlack_Weight); + fUnion.fR.fWidth = SkPin32(width, kUltraCondensed_Width, kUltaExpanded_Width); + fUnion.fR.fSlant = SkPin32(slant, kUpright_Slant, kItalic_Slant); +} + +#include "SkFontMgr.h" + +class SkEmptyFontStyleSet : public SkFontStyleSet { +public: + virtual int count() SK_OVERRIDE { return 0; } + virtual void getStyle(int, SkFontStyle*, SkString*) SK_OVERRIDE { + SkDEBUGFAIL("SkFontStyleSet::getStyle called on empty set"); + } + virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { + SkDEBUGFAIL("SkFontStyleSet::createTypeface called on empty set"); + return NULL; + } + virtual SkTypeface* matchStyle(const SkFontStyle&) SK_OVERRIDE { + return NULL; + } +}; + +SkFontStyleSet* SkFontStyleSet::CreateEmpty() { + return SkNEW(SkEmptyFontStyleSet); +} + +/////////////////////////////////////////////////////////////////////////////// + +class SkEmptyFontMgr : public SkFontMgr { +protected: + virtual int onCountFamilies() const SK_OVERRIDE { + return 0; + } + virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { + SkDEBUGFAIL("onGetFamilyName called with bad index"); + } + virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { + SkDEBUGFAIL("onCreateStyleSet called with bad index"); + return NULL; + } + virtual SkFontStyleSet* onMatchFamily(const char[]) const SK_OVERRIDE { + return SkFontStyleSet::CreateEmpty(); + } + + virtual SkTypeface* onMatchFamilyStyle(const char[], + const SkFontStyle&) const SK_OVERRIDE { + return NULL; + } + virtual SkTypeface* onMatchFaceStyle(const SkTypeface*, + const SkFontStyle&) const SK_OVERRIDE { + return NULL; + } + virtual SkTypeface* onCreateFromData(SkData*, int) const SK_OVERRIDE { + return NULL; + } + virtual SkTypeface* onCreateFromStream(SkStream*, int) const SK_OVERRIDE { + return NULL; + } + virtual SkTypeface* onCreateFromFile(const char[], int) const SK_OVERRIDE { + return NULL; + } + virtual SkTypeface* onLegacyCreateTypeface(const char [], unsigned) const SK_OVERRIDE { + return NULL; + } +}; + +static SkFontStyleSet* emptyOnNull(SkFontStyleSet* fsset) { + if (NULL == fsset) { + fsset = SkFontStyleSet::CreateEmpty(); + } + return fsset; +} + +int SkFontMgr::countFamilies() const { + return this->onCountFamilies(); +} + +void SkFontMgr::getFamilyName(int index, SkString* familyName) const { + this->onGetFamilyName(index, familyName); +} + +SkFontStyleSet* SkFontMgr::createStyleSet(int index) const { + return emptyOnNull(this->onCreateStyleSet(index)); +} + +SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) const { + return emptyOnNull(this->onMatchFamily(familyName)); +} + +SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[], + const SkFontStyle& fs) const { + return this->onMatchFamilyStyle(familyName, fs); +} + +SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face, + const SkFontStyle& fs) const { + return this->onMatchFaceStyle(face, fs); +} + +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) const { + if (NULL == stream) { + return NULL; + } + return this->onCreateFromStream(stream, ttcIndex); +} + +SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) const { + if (NULL == path) { + return NULL; + } + return this->onCreateFromFile(path, ttcIndex); +} + +SkTypeface* SkFontMgr::legacyCreateTypeface(const char familyName[], + 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::RefDefault() { + static SkFontMgr* gFM = NULL; + SK_DECLARE_STATIC_ONCE(once); + SkOnce(&once, set_up_default, &gFM); + return SkRef(gFM); +} + +////////////////////////////////////////////////////////////////////////// + +#ifndef SK_FONTHOST_DOES_NOT_USE_FONTMGR + +#if 0 +static SkFontStyle TypefaceStyleBitsToFontStyle(SkTypeface::Style styleBits) { + SkFontStyle::Weight weight = (styleBits & SkTypeface::kBold) ? + SkFontStyle::kBold_Weight : + SkFontStyle::kNormal_Weight; + SkFontStyle::Width width = SkFontStyle::kNormal_Width; + SkFontStyle::Slant slant = (styleBits & SkTypeface::kItalic) ? + SkFontStyle::kUpright_Slant : + SkFontStyle::kItalic_Slant; + return SkFontStyle(weight, width, slant); +} +#endif + +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, + const char familyName[], + SkTypeface::Style style) { + SkAutoTUnref fm(SkFontMgr::RefDefault()); + if (familyFace) { + bool bold = style & SkTypeface::kBold; + bool italic = style & SkTypeface::kItalic; + SkFontStyle newStyle = SkFontStyle(bold ? SkFontStyle::kBold_Weight + : SkFontStyle::kNormal_Weight, + SkFontStyle::kNormal_Width, + italic ? SkFontStyle::kItalic_Slant + : SkFontStyle::kUpright_Slant); + return fm->matchFaceStyle(familyFace, newStyle); + } else { + return fm->legacyCreateTypeface(familyName, style); + } +} + +SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { + SkAutoTUnref fm(SkFontMgr::RefDefault()); + return fm->createFromFile(path); +} + +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { + SkAutoTUnref fm(SkFontMgr::RefDefault()); + return fm->createFromStream(stream); +} + +#endif diff --git a/gfx/skia/src/core/SkFontStream.cpp b/gfx/skia/trunk/src/core/SkFontStream.cpp similarity index 100% rename from gfx/skia/src/core/SkFontStream.cpp rename to gfx/skia/trunk/src/core/SkFontStream.cpp diff --git a/gfx/skia/src/core/SkFontStream.h b/gfx/skia/trunk/src/core/SkFontStream.h similarity index 100% rename from gfx/skia/src/core/SkFontStream.h rename to gfx/skia/trunk/src/core/SkFontStream.h diff --git a/gfx/skia/src/core/SkGeometry.cpp b/gfx/skia/trunk/src/core/SkGeometry.cpp similarity index 74% rename from gfx/skia/src/core/SkGeometry.cpp rename to gfx/skia/trunk/src/core/SkGeometry.cpp index 0d4a9c79d16f..574954019eb8 100644 --- a/gfx/skia/src/core/SkGeometry.cpp +++ b/gfx/skia/trunk/src/core/SkGeometry.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,9 +5,7 @@ * 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) { @@ -68,32 +65,18 @@ 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(float a, float b, float c) { + float ab = a - b; + float bc = b - c; + if (ab < 0) { + bc = -bc; } - - 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; - } -#endif + return ab == 0 || bc < 0; +} //////////////////////////////////////////////////////////////////////// @@ -141,23 +124,11 @@ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) SkScalar* r = roots; -#ifdef SK_SCALAR_IS_FLOAT float 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 SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2; r += valid_unit_divide(Q, A, r); @@ -172,25 +143,8 @@ 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) { @@ -297,11 +251,7 @@ 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]) @@ -394,57 +344,30 @@ int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5]) // // t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2) // -int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) -{ +float 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; + return t; +} - 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 - - if (t == 0) - { +int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) +{ + SkScalar t = SkFindQuadMaxCurvature(src); + if (t == 0) { memcpy(dst, src, 3 * sizeof(SkPoint)); return 1; - } - else - { + } else { SkChopQuadAt(src, dst, t); return 2; } } -#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; @@ -552,11 +475,6 @@ void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tan */ 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 - // we divide A,B,C by 3 to simplify SkScalar A = d - a + 3*(b - c); SkScalar B = 2*(a - b - b + c); @@ -746,29 +664,8 @@ int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[]) 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]) @@ -798,8 +695,6 @@ template 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) @@ -892,9 +787,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 sk_float_pow(x, 0.3333333f); +} /* Solve coeff(t) == 0, returning the number of roots that lie withing 0 < t < 1. @@ -903,44 +798,35 @@ 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]) +static int solve_cubic_polynomial(const SkScalar 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 { 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 + if (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); @@ -964,18 +850,17 @@ 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); + SkScalar A = SkScalarAbs(R) + SkScalarSqrt(R2MinusQ3); + A = SkScalarCubeRoot(A); + if (R > 0) + A = -A; if (A != 0) - A = SkFPAdd(A, SkFPDiv(Q, A)); - r = SkFPToScalar(SkFPSub(A, adiv3)); + A += Q / A; + r = A - adiv3; if (is_unit_interval(r)) *roots++ = r; } @@ -994,21 +879,16 @@ 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 @@ -1028,14 +908,14 @@ static void formulate_F1DotF2(const SkScalar src[], SkFP coeff[4]) */ int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]) { - SkFP coeffX[4], coeffY[4]; - int i; + 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]); + coeffX[i] += coeffY[i]; SkScalar t[3]; int count = solve_cubic_polynomial(coeffX, t); @@ -1061,8 +941,7 @@ int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tV int count = SkFindCubicMaxCurvature(src, tValues); - if (dst) - { + if (dst) { if (count == 0) memcpy(dst, src, 4 * sizeof(SkPoint)); else @@ -1134,9 +1013,9 @@ bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool* // instead of down if (cubic[3].fY > cubic[0].fY) { upper_t = SK_Scalar1; - lower_t = SkFloatToScalar(0); + lower_t = 0; } else { - upper_t = SkFloatToScalar(0); + upper_t = 0; lower_t = SK_Scalar1; } do { @@ -1185,7 +1064,6 @@ int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], bool* a } return num_crossings; } - //////////////////////////////////////////////////////////////////////////////// /* Find t value for quadratic [a, b, c] = d. @@ -1205,11 +1083,12 @@ static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d) return count == 1 ? roots[0] : 0; } -/* given a quad-curve and a point (x,y), chop the quad at that point and return - the new quad's offCurve point. Should only return false if the computed pos - is the start of the curve (i.e. root == 0) +/* given a quad-curve and a point (x,y), chop the quad at that point and place + the new off-curve point and endpoint into 'dest'. + Should only return false if the computed pos is the start of the curve + (i.e. root == 0) */ -static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* offCurve) +static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* dest) { const SkScalar* base; SkScalar value; @@ -1230,7 +1109,8 @@ static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo { SkPoint tmp[5]; SkChopQuadAt(quad, tmp, t); - *offCurve = tmp[1]; + dest[0] = tmp[1]; + dest[1].set(x, y); return true; } else { /* t == 0 means either the value triggered a root outside of [0, 1) @@ -1247,56 +1127,42 @@ static bool quad_pt2OffCurve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPo if ((base[0] < base[4] && value > base[2]) || (base[0] > base[4] && value < base[2])) // should root have been 1 { - *offCurve = quad[1]; + dest[0] = quad[1]; + dest[1].set(x, y); return true; } } return false; } -#ifdef SK_SCALAR_IS_FLOAT - -// Due to floating point issues (i.e., 1.0f - SK_ScalarRoot2Over2 != -// SK_ScalarRoot2Over2 - SK_ScalarTanPIOver8) a cruder root2over2 -// approximation is required to make the quad circle points convex. The -// root of the problem is that with the root2over2 value in SkScalar.h -// the arcs really are ever so slightly concave. Some alternative fixes -// to this problem (besides just arbitrarily pushing out the mid-point as -// is done here) are: -// Adjust all the points (not just the middle) to both better approximate -// the curve and remain convex -// Switch over to using cubics rather then quads -// Use a different method to create the mid-point (e.g., compute -// the two side points, average them, then move it out as needed -#define SK_ScalarRoot2Over2_QuadCircle 0.7072f - -#else - #define SK_ScalarRoot2Over2_QuadCircle SK_FixedRoot2Over2 -#endif - - static const SkPoint gQuadCirclePts[kSkBuildQuadArcStorage] = { - { SK_Scalar1, 0 }, - { SK_Scalar1, SK_ScalarTanPIOver8 }, - { SK_ScalarRoot2Over2_QuadCircle, SK_ScalarRoot2Over2_QuadCircle }, - { SK_ScalarTanPIOver8, SK_Scalar1 }, +// 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 + { SK_Scalar1, 0 }, + { SK_Scalar1, SK_ScalarTanPIOver8 }, + { SK_MID_RRECT_OFFSET, SK_MID_RRECT_OFFSET }, + { SK_ScalarTanPIOver8, SK_Scalar1 }, - { 0, SK_Scalar1 }, - { -SK_ScalarTanPIOver8, SK_Scalar1 }, - { -SK_ScalarRoot2Over2_QuadCircle, SK_ScalarRoot2Over2_QuadCircle }, - { -SK_Scalar1, SK_ScalarTanPIOver8 }, + { 0, SK_Scalar1 }, + { -SK_ScalarTanPIOver8, SK_Scalar1 }, + { -SK_MID_RRECT_OFFSET, SK_MID_RRECT_OFFSET }, + { -SK_Scalar1, SK_ScalarTanPIOver8 }, - { -SK_Scalar1, 0 }, - { -SK_Scalar1, -SK_ScalarTanPIOver8 }, - { -SK_ScalarRoot2Over2_QuadCircle, -SK_ScalarRoot2Over2_QuadCircle }, - { -SK_ScalarTanPIOver8, -SK_Scalar1 }, + { -SK_Scalar1, 0 }, + { -SK_Scalar1, -SK_ScalarTanPIOver8 }, + { -SK_MID_RRECT_OFFSET, -SK_MID_RRECT_OFFSET }, + { -SK_ScalarTanPIOver8, -SK_Scalar1 }, - { 0, -SK_Scalar1 }, - { SK_ScalarTanPIOver8, -SK_Scalar1 }, - { SK_ScalarRoot2Over2_QuadCircle, -SK_ScalarRoot2Over2_QuadCircle }, - { SK_Scalar1, -SK_ScalarTanPIOver8 }, + { 0, -SK_Scalar1 }, + { SK_ScalarTanPIOver8, -SK_Scalar1 }, + { SK_MID_RRECT_OFFSET, -SK_MID_RRECT_OFFSET }, + { SK_Scalar1, -SK_ScalarTanPIOver8 }, - { SK_Scalar1, 0 } + { SK_Scalar1, 0 } +#undef SK_MID_RRECT_OFFSET }; int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop, @@ -1360,9 +1226,8 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop, memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint)); const SkPoint* arc = &gQuadCirclePts[wholeCount]; - if (quad_pt2OffCurve(arc, x, y, &quadPoints[wholeCount + 1])) + if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1])) { - quadPoints[wholeCount + 2].set(x, y); wholeCount += 2; } pointCount = wholeCount + 1; @@ -1380,3 +1245,284 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop, matrix.mapPoints(quadPoints, pointCount); return pointCount; } + +/////////////////////////////////////////////////////////////////////////////// + +// F = (A (1 - t)^2 + C t^2 + 2 B (1 - t) t w) +// ------------------------------------------ +// ((1 - t)^2 + t^2 + 2 (1 - t) t w) +// +// = {t^2 (P0 + P2 - 2 P1 w), t (-2 P0 + 2 P1 w), P0} +// ------------------------------------------------ +// {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); + + SkScalar src2w = SkScalarMul(src[2], w); + SkScalar C = src[0]; + SkScalar A = src[4] - 2 * src2w + C; + SkScalar B = 2 * (src2w - C); + SkScalar numer = SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); + + B = 2 * (w - SK_Scalar1); + C = SK_Scalar1; + A = -B; + SkScalar denom = SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); + + return SkScalarDiv(numer, denom); +} + +// F' = 2 (C t (1 + t (-1 + w)) - A (-1 + t) (t (-1 + w) - w) + B (1 - 2 t) w) +// +// t^2 : (2 P0 - 2 P2 - 2 P0 w + 2 P2 w) +// t^1 : (-2 P0 + 2 P2 + 4 P0 w - 4 P1 w) +// t^0 : -2 P0 w + 2 P1 w +// +// We disregard magnitude, so we can freely ignore the denominator of F', and +// divide the numerator by 2 +// +// coeff[0] for t^2 +// coeff[1] for t^1 +// coeff[2] for t^0 +// +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; + coeff[0] = w * P20 - P20; + coeff[1] = P20 - 2 * wP10; + coeff[2] = wP10; +} + +static SkScalar conic_eval_tan(const SkScalar coord[], SkScalar w, SkScalar t) { + SkScalar coeff[3]; + conic_deriv_coeff(coord, w, coeff); + return t * (t * coeff[0] + coeff[1]) + coeff[2]; +} + +static bool conic_find_extrema(const SkScalar src[], SkScalar w, SkScalar* t) { + SkScalar coeff[3]; + conic_deriv_coeff(src, w, coeff); + + SkScalar tValues[2]; + int roots = SkFindUnitQuadRoots(coeff[0], coeff[1], coeff[2], tValues); + SkASSERT(0 == roots || 1 == roots); + + if (1 == roots) { + *t = tValues[0]; + return true; + } + return false; +} + +struct SkP3D { + SkScalar fX, fY, fZ; + + void set(SkScalar x, SkScalar y, SkScalar z) { + fX = x; fY = y; fZ = z; + } + + void projectDown(SkPoint* dst) const { + dst->set(fX / fZ, fY / fZ); + } +}; + +// 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; + dst[3] = SkScalarInterp(ab, bc, t); + dst[6] = bc; +} + +static void ratquad_mapTo3D(const SkPoint src[3], SkScalar w, SkP3D dst[]) { + dst[0].set(src[0].fX * 1, src[0].fY * 1, 1); + dst[1].set(src[1].fX * w, src[1].fY * w, w); + dst[2].set(src[2].fX * 1, src[2].fY * 1, 1); +} + +void SkConic::evalAt(SkScalar t, SkPoint* pt, SkVector* tangent) const { + SkASSERT(t >= 0 && t <= SK_Scalar1); + + if (pt) { + pt->set(conic_eval_pos(&fPts[0].fX, fW, t), + conic_eval_pos(&fPts[0].fY, fW, t)); + } + if (tangent) { + tangent->set(conic_eval_tan(&fPts[0].fX, fW, t), + conic_eval_tan(&fPts[0].fY, fW, t)); + } +} + +void SkConic::chopAt(SkScalar t, SkConic dst[2]) const { + SkP3D tmp[3], tmp2[3]; + + ratquad_mapTo3D(fPts, fW, tmp); + + p3d_interp(&tmp[0].fX, &tmp2[0].fX, t); + p3d_interp(&tmp[0].fY, &tmp2[0].fY, t); + p3d_interp(&tmp[0].fZ, &tmp2[0].fZ, t); + + dst[0].fPts[0] = fPts[0]; + tmp2[0].projectDown(&dst[0].fPts[1]); + tmp2[1].projectDown(&dst[0].fPts[2]); dst[1].fPts[0] = dst[0].fPts[2]; + tmp2[2].projectDown(&dst[1].fPts[1]); + dst[1].fPts[2] = fPts[2]; + + // to put in "standard form", where w0 and w2 are both 1, we compute the + // new w1 as sqrt(w1*w1/w0*w2) + // or + // w1 /= sqrt(w0*w2) + // + // 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; + dst[1].fW = tmp2[2].fZ / root; +} + +static SkScalar subdivide_w_value(SkScalar w) { + return SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf); +} + +void SkConic::chop(SkConic dst[2]) const { + SkScalar scale = SkScalarInvert(SK_Scalar1 + fW); + SkScalar p1x = fW * fPts[1].fX; + SkScalar p1y = fW * fPts[1].fY; + SkScalar mx = (fPts[0].fX + 2 * p1x + fPts[2].fX) * scale * SK_ScalarHalf; + SkScalar my = (fPts[0].fY + 2 * p1y + fPts[2].fY) * scale * SK_ScalarHalf; + + dst[0].fPts[0] = fPts[0]; + dst[0].fPts[1].set((fPts[0].fX + p1x) * scale, + (fPts[0].fY + p1y) * scale); + dst[0].fPts[2].set(mx, my); + + dst[1].fPts[0].set(mx, my); + dst[1].fPts[1].set((p1x + fPts[2].fX) * scale, + (p1y + fPts[2].fY) * scale); + dst[1].fPts[2] = fPts[2]; + + dst[0].fW = dst[1].fW = subdivide_w_value(fW); +} + +/* + * "High order approximation of conic sections by quadratic splines" + * by Michael Floater, 1993 + */ +#define AS_QUAD_ERROR_SETUP \ + SkScalar a = fW - 1; \ + SkScalar k = a / (4 * (2 + a)); \ + SkScalar x = k * (fPts[0].fX - 2 * fPts[1].fX + fPts[2].fX); \ + SkScalar y = k * (fPts[0].fY - 2 * fPts[1].fY + fPts[2].fY); + +void SkConic::computeAsQuadError(SkVector* err) const { + AS_QUAD_ERROR_SETUP + err->set(x, y); +} + +bool SkConic::asQuadTol(SkScalar tol) const { + AS_QUAD_ERROR_SETUP + return (x * x + y * y) <= tol * tol; +} + +int SkConic::computeQuadPOW2(SkScalar tol) const { + AS_QUAD_ERROR_SETUP + SkScalar error = SkScalarSqrt(x * x + y * y) - tol; + + if (error <= 0) { + return 0; + } + uint32_t ierr = (uint32_t)error; + return (34 - SkCLZ(ierr)) >> 1; +} + +static SkPoint* subdivide(const SkConic& src, SkPoint pts[], int level) { + SkASSERT(level >= 0); + + if (0 == level) { + memcpy(pts, &src.fPts[1], 2 * sizeof(SkPoint)); + return pts + 2; + } else { + SkConic dst[2]; + src.chop(dst); + --level; + pts = subdivide(dst[0], pts, level); + return subdivide(dst[1], pts, level); + } +} + +int SkConic::chopIntoQuadsPOW2(SkPoint pts[], int pow2) const { + SkASSERT(pow2 >= 0); + *pts = fPts[0]; + SkDEBUGCODE(SkPoint* endPts =) subdivide(*this, pts + 1, pow2); + SkASSERT(endPts - pts == (2 * (1 << pow2) + 1)); + return 1 << pow2; +} + +bool SkConic::findXExtrema(SkScalar* t) const { + return conic_find_extrema(&fPts[0].fX, fW, t); +} + +bool SkConic::findYExtrema(SkScalar* t) const { + return conic_find_extrema(&fPts[0].fY, fW, t); +} + +bool SkConic::chopAtXExtrema(SkConic dst[2]) const { + SkScalar t; + if (this->findXExtrema(&t)) { + this->chopAt(t, dst); + // now clean-up the middle, since we know t was meant to be at + // an X-extrema + SkScalar value = dst[0].fPts[2].fX; + dst[0].fPts[1].fX = value; + dst[1].fPts[0].fX = value; + dst[1].fPts[1].fX = value; + return true; + } + return false; +} + +bool SkConic::chopAtYExtrema(SkConic dst[2]) const { + SkScalar t; + if (this->findYExtrema(&t)) { + this->chopAt(t, dst); + // now clean-up the middle, since we know t was meant to be at + // an Y-extrema + SkScalar value = dst[0].fPts[2].fY; + dst[0].fPts[1].fY = value; + dst[1].fPts[0].fY = value; + dst[1].fPts[1].fY = value; + return true; + } + return false; +} + +void SkConic::computeTightBounds(SkRect* bounds) const { + SkPoint pts[4]; + pts[0] = fPts[0]; + pts[1] = fPts[2]; + int count = 2; + + SkScalar t; + if (this->findXExtrema(&t)) { + this->evalAt(t, &pts[count++]); + } + if (this->findYExtrema(&t)) { + this->evalAt(t, &pts[count++]); + } + bounds->set(pts, count); +} + +void SkConic::computeFastBounds(SkRect* bounds) const { + bounds->set(fPts, 3); +} diff --git a/gfx/skia/src/core/SkGlyph.h b/gfx/skia/trunk/src/core/SkGlyph.h similarity index 100% rename from gfx/skia/src/core/SkGlyph.h rename to gfx/skia/trunk/src/core/SkGlyph.h diff --git a/gfx/skia/src/core/SkGlyphCache.cpp b/gfx/skia/trunk/src/core/SkGlyphCache.cpp similarity index 69% rename from gfx/skia/src/core/SkGlyphCache.cpp rename to gfx/skia/trunk/src/core/SkGlyphCache.cpp index d33a13f4bc9b..2b1b62b83964 100644 --- a/gfx/skia/src/core/SkGlyphCache.cpp +++ b/gfx/skia/trunk/src/core/SkGlyphCache.cpp @@ -8,6 +8,7 @@ #include "SkGlyphCache.h" +#include "SkGlyphCache_Globals.h" #include "SkGraphics.h" #include "SkPaint.h" #include "SkPath.h" @@ -16,11 +17,24 @@ #include "SkTypeface.h" //#define SPEW_PURGE_STATUS -//#define USE_CACHE_HASH //#define RECORD_HASH_EFFICIENCY bool gSkSuppressFontCachePurgeSpew; +// 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; +} + +// Returns the TLS globals (if set), or the shared globals +static SkGlyphCache_Globals& getGlobals() { + SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); + return tls ? *tls : getSharedGlobals(); +} + /////////////////////////////////////////////////////////////////////////////// #ifdef RECORD_HASH_EFFICIENCY @@ -48,37 +62,59 @@ bool gSkSuppressFontCachePurgeSpew; /////////////////////////////////////////////////////////////////////////////// -#define kMinGlphAlloc (sizeof(SkGlyph) * 64) -#define kMinImageAlloc (24 * 64) // should be pointsize-dependent +// so we don't grow our arrays a lot +#define kMinGlyphCount 16 +#define kMinGlyphImageSize (16*2) +#define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphCount) -#define METRICS_RESERVE_COUNT 128 // so we don't grow this array a lot - -SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) - : fGlyphAlloc(kMinGlphAlloc) - , fImageAlloc(kMinImageAlloc) { +SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkScalerContext* ctx) + : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) { SkASSERT(typeface); + SkASSERT(desc); + SkASSERT(ctx); fPrev = fNext = NULL; fDesc = desc->copy(); - fScalerContext = typeface->createScalerContext(desc); - fScalerContext->getFontMetrics(NULL, &fFontMetricsY); + fScalerContext->getFontMetrics(&fFontMetrics); // init to 0 so that all of the pointers will be null memset(fGlyphHash, 0, sizeof(fGlyphHash)); // init with 0xFF so that the charCode field will be -1, which is invalid memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash)); - fMemoryUsed = sizeof(*this) + kMinGlphAlloc + kMinImageAlloc; + fMemoryUsed = sizeof(*this); - fGlyphArray.setReserve(METRICS_RESERVE_COUNT); + fGlyphArray.setReserve(kMinGlyphCount); - fMetricsCount = 0; - fAdvanceCount = 0; fAuxProcList = NULL; } SkGlyphCache::~SkGlyphCache() { +#if 0 + { + size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); + size_t glyphAlloc = fGlyphAlloc.totalCapacity(); + size_t glyphHashUsed = 0; + size_t uniHashUsed = 0; + for (int i = 0; i < kHashCount; ++i) { + glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0; + uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharToGlyphHash[0]) : 0; + } + size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); + size_t imageUsed = 0; + for (int i = 0; i < fGlyphArray.count(); ++i) { + const SkGlyph& g = *fGlyphArray[i]; + if (g.fImage) { + imageUsed += g.fHeight * g.rowBytes(); + } + } + + printf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, glyphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n", + ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), glyphHashUsed, sizeof(fCharToGlyphHash), uniHashUsed); + + } +#endif SkGlyph** gptr = fGlyphArray.begin(); SkGlyph** stop = fGlyphArray.end(); while (gptr < stop) { @@ -282,11 +318,9 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { if (kJustAdvance_MetricsType == mtype) { fScalerContext->getAdvance(glyph); - fAdvanceCount += 1; } else { SkASSERT(kFull_MetricsType == mtype); fScalerContext->getMetrics(glyph); - fMetricsCount += 1; } return glyph; @@ -296,7 +330,7 @@ const void* SkGlyphCache::findImage(const SkGlyph& glyph) { if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { if (glyph.fImage == NULL) { size_t size = glyph.computeImageSize(); - const_cast(glyph).fImage = fImageAlloc.alloc(size, + const_cast(glyph).fImage = fGlyphAlloc.alloc(size, SkChunkAlloc::kReturnNil_AllocFailType); // check that alloc() actually succeeded if (glyph.fImage) { @@ -374,134 +408,38 @@ void SkGlyphCache::invokeAndRemoveAuxProcs() { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#ifndef SK_DEFAULT_FONT_CACHE_LIMIT - #define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024) -#endif - -#ifdef USE_CACHE_HASH - #define HASH_BITCOUNT 6 - #define HASH_COUNT (1 << HASH_BITCOUNT) - #define HASH_MASK (HASH_COUNT - 1) - - static unsigned desc_to_hashindex(const SkDescriptor* desc) - { - SkASSERT(HASH_MASK < 256); // since our munging reduces to 8 bits - - uint32_t n = *(const uint32_t*)desc; //desc->getChecksum(); - SkASSERT(n == desc->getChecksum()); - - // don't trust that the low bits of checksum vary enough, so... - n ^= (n >> 24) ^ (n >> 16) ^ (n >> 8) ^ (n >> 30); - - return n & HASH_MASK; - } -#endif - #include "SkThread.h" -class SkGlyphCache_Globals { -public: - enum UseMutex { - kNo_UseMutex, // thread-local cache - kYes_UseMutex // shared cache - }; - - SkGlyphCache_Globals(UseMutex um) { - fHead = NULL; - fTotalMemoryUsed = 0; - fFontCacheLimit = SK_DEFAULT_FONT_CACHE_LIMIT; - fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL; - -#ifdef USE_CACHE_HASH - sk_bzero(fHash, sizeof(fHash)); -#endif - } - - ~SkGlyphCache_Globals() { - SkGlyphCache* cache = fHead; - while (cache) { - SkGlyphCache* next = cache->fNext; - SkDELETE(cache); - cache = next; - } - - SkDELETE(fMutex); - } - - SkMutex* fMutex; - SkGlyphCache* fHead; - size_t fTotalMemoryUsed; -#ifdef USE_CACHE_HASH - SkGlyphCache* fHash[HASH_COUNT]; -#endif - -#ifdef SK_DEBUG - void validate() const; -#else - void validate() const {} -#endif - - size_t getFontCacheLimit() const { return fFontCacheLimit; } - size_t setFontCacheLimit(size_t limit); - void purgeAll(); // does not change budget - - // can return NULL - static SkGlyphCache_Globals* FindTLS() { - return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS); - } - - static SkGlyphCache_Globals& GetTLS() { - return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS); - } - - static void DeleteTLS() { SkTLS::Delete(CreateTLS); } - -private: - size_t fFontCacheLimit; - - static void* CreateTLS() { - return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex)); - } - - static void DeleteTLS(void* ptr) { - SkDELETE((SkGlyphCache_Globals*)ptr); - } -}; - -size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) { +size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { static const size_t minLimit = 256 * 1024; if (newLimit < minLimit) { newLimit = minLimit; } - size_t prevLimit = fFontCacheLimit; - fFontCacheLimit = newLimit; + SkAutoMutexAcquire ac(fMutex); - size_t currUsed = fTotalMemoryUsed; - if (currUsed > newLimit) { - SkAutoMutexAcquire ac(fMutex); - SkGlyphCache::InternalFreeCache(this, currUsed - newLimit); - } + size_t prevLimit = fCacheSizeLimit; + fCacheSizeLimit = newLimit; + this->internalPurge(); return prevLimit; } +int SkGlyphCache_Globals::setCacheCountLimit(int newCount) { + if (newCount < 0) { + newCount = 0; + } + + SkAutoMutexAcquire ac(fMutex); + + int prevCount = fCacheCountLimit; + fCacheCountLimit = newCount; + this->internalPurge(); + return prevCount; +} + void SkGlyphCache_Globals::purgeAll() { SkAutoMutexAcquire ac(fMutex); - SkGlyphCache::InternalFreeCache(this, fTotalMemoryUsed); -} - -// 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; -} - -// Returns the TLS globals (if set), or the shared globals -static SkGlyphCache_Globals& getGlobals() { - SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); - return tls ? *tls : getSharedGlobals(); + this->internalPurge(fTotalMemoryUsed); } void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), @@ -512,7 +450,7 @@ void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), globals.validate(); - for (cache = globals.fHead; cache != NULL; cache = cache->fNext) { + for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { if (proc(cache, context)) { break; } @@ -543,19 +481,9 @@ SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, globals.validate(); -#ifdef USE_CACHE_HASH - SkGlyphCache** hash = globals.fHash; - unsigned index = desc_to_hashindex(desc); - cache = hash[index]; - if (cache && *cache->fDesc == *desc) { - cache->detach(&globals.fHead); - goto FOUND_IT; - } -#endif - - for (cache = globals.fHead; cache != NULL; cache = cache->fNext) { + for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { if (cache->fDesc->equals(*desc)) { - cache->detach(&globals.fHead); + globals.internalDetachCache(cache); goto FOUND_IT; } } @@ -566,28 +494,30 @@ SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, ac.release(); // release the mutex now insideMutex = false; // can't use globals anymore - cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc)); + // Check if we can create a scaler-context before creating the glyphcache. + // If not, we may have exhausted OS/font resources, so try purging the + // cache once and try again. + { + // pass true the first time, to notice if the scalercontext failed, + // so we can try the purge. + SkScalerContext* ctx = typeface->createScalerContext(desc, true); + if (!ctx) { + getSharedGlobals().purgeAll(); + ctx = typeface->createScalerContext(desc, false); + SkASSERT(ctx); + } + cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); + } FOUND_IT: AutoValidate av(cache); - if (proc(cache, context)) { // stay detached + if (!proc(cache, context)) { // need to reattach if (insideMutex) { - SkASSERT(globals.fTotalMemoryUsed >= cache->fMemoryUsed); - globals.fTotalMemoryUsed -= cache->fMemoryUsed; -#ifdef USE_CACHE_HASH - hash[index] = NULL; -#endif - } - } else { // reattach - if (insideMutex) { - cache->attachToHead(&globals.fHead); -#ifdef USE_CACHE_HASH - hash[index] = cache; -#endif + globals.internalAttachCacheToHead(cache); } else { - AttachCache(cache); + globals.attachCacheToHead(cache); } cache = NULL; } @@ -598,36 +528,23 @@ void SkGlyphCache::AttachCache(SkGlyphCache* cache) { SkASSERT(cache); SkASSERT(cache->fNext == NULL); - SkGlyphCache_Globals& globals = getGlobals(); - SkAutoMutexAcquire ac(globals.fMutex); - - globals.validate(); - cache->validate(); - - // if we have a fixed budget for our cache, do a purge here - { - size_t allocated = globals.fTotalMemoryUsed + cache->fMemoryUsed; - size_t budgeted = globals.getFontCacheLimit(); - if (allocated > budgeted) { - (void)InternalFreeCache(&globals, allocated - budgeted); - } - } - - cache->attachToHead(&globals.fHead); - globals.fTotalMemoryUsed += cache->fMemoryUsed; - -#ifdef USE_CACHE_HASH - unsigned index = desc_to_hashindex(cache->fDesc); - SkASSERT(globals.fHash[index] != cache); - globals.fHash[index] = cache; -#endif - - globals.validate(); + getGlobals().attachCacheToHead(cache); } /////////////////////////////////////////////////////////////////////////////// -SkGlyphCache* SkGlyphCache::FindTail(SkGlyphCache* cache) { +void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { + SkAutoMutexAcquire ac(fMutex); + + this->validate(); + cache->validate(); + + this->internalAttachCacheToHead(cache); + this->internalPurge(); +} + +SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { + SkGlyphCache* cache = fHead; if (cache) { while (cache->fNext) { cache = cache->fNext; @@ -636,70 +553,92 @@ SkGlyphCache* SkGlyphCache::FindTail(SkGlyphCache* cache) { return cache; } -#ifdef SK_DEBUG -void SkGlyphCache_Globals::validate() const { - size_t computed = 0; +size_t SkGlyphCache_Globals::internalPurge(size_t minBytesNeeded) { + this->validate(); - const SkGlyphCache* head = fHead; - while (head != NULL) { - computed += head->fMemoryUsed; - head = head->fNext; + size_t bytesNeeded = 0; + if (fTotalMemoryUsed > fCacheSizeLimit) { + bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit; + } + bytesNeeded = SkTMax(bytesNeeded, minBytesNeeded); + if (bytesNeeded) { + // no small purges! + bytesNeeded = SkTMax(bytesNeeded, fTotalMemoryUsed >> 2); } - if (fTotalMemoryUsed != computed) { - printf("total %d, computed %d\n", (int)fTotalMemoryUsed, (int)computed); + int countNeeded = 0; + if (fCacheCount > fCacheCountLimit) { + countNeeded = fCacheCount - fCacheCountLimit; + // no small purges! + countNeeded = SkMax32(countNeeded, fCacheCount >> 2); } - SkASSERT(fTotalMemoryUsed == computed); -} -#endif -size_t SkGlyphCache::InternalFreeCache(SkGlyphCache_Globals* globals, - size_t bytesNeeded) { - globals->validate(); + // early exit + if (!countNeeded && !bytesNeeded) { + return 0; + } size_t bytesFreed = 0; - int count = 0; + int countFreed = 0; - // don't do any "small" purges - size_t minToPurge = globals->fTotalMemoryUsed >> 2; - if (bytesNeeded < minToPurge) - bytesNeeded = minToPurge; - - SkGlyphCache* cache = FindTail(globals->fHead); - while (cache != NULL && bytesFreed < bytesNeeded) { + // we start at the tail and proceed backwards, as the linklist is in LRU + // order, with unimportant entries at the tail. + SkGlyphCache* cache = this->internalGetTail(); + while (cache != NULL && + (bytesFreed < bytesNeeded || countFreed < countNeeded)) { SkGlyphCache* prev = cache->fPrev; bytesFreed += cache->fMemoryUsed; + countFreed += 1; -#ifdef USE_CACHE_HASH - unsigned index = desc_to_hashindex(cache->fDesc); - if (cache == globals->fHash[index]) { - globals->fHash[index] = NULL; - } -#endif - - cache->detach(&globals->fHead); + this->internalDetachCache(cache); SkDELETE(cache); cache = prev; - count += 1; } - SkASSERT(bytesFreed <= globals->fTotalMemoryUsed); - globals->fTotalMemoryUsed -= bytesFreed; - globals->validate(); + this->validate(); #ifdef SPEW_PURGE_STATUS - if (count && !gSkSuppressFontCachePurgeSpew) { + if (countFreed && !gSkSuppressFontCachePurgeSpew) { SkDebugf("purging %dK from font cache [%d entries]\n", - (int)(bytesFreed >> 10), count); + (int)(bytesFreed >> 10), countFreed); } #endif return bytesFreed; } +void SkGlyphCache_Globals::internalAttachCacheToHead(SkGlyphCache* cache) { + SkASSERT(NULL == cache->fPrev && NULL == cache->fNext); + if (fHead) { + fHead->fPrev = cache; + cache->fNext = fHead; + } + fHead = cache; + + fCacheCount += 1; + fTotalMemoryUsed += cache->fMemoryUsed; +} + +void SkGlyphCache_Globals::internalDetachCache(SkGlyphCache* cache) { + SkASSERT(fCacheCount > 0); + fCacheCount -= 1; + fTotalMemoryUsed -= cache->fMemoryUsed; + + if (cache->fPrev) { + cache->fPrev->fNext = cache->fNext; + } else { + fHead = cache->fNext; + } + if (cache->fNext) { + cache->fNext->fPrev = cache->fPrev; + } + cache->fPrev = cache->fNext = NULL; +} + /////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG + void SkGlyphCache::validate() const { #ifdef SK_DEBUG_GLYPH_CACHE int count = fGlyphArray.count(); @@ -708,11 +647,27 @@ void SkGlyphCache::validate() const { SkASSERT(glyph); SkASSERT(fGlyphAlloc.contains(glyph)); if (glyph->fImage) { - SkASSERT(fImageAlloc.contains(glyph->fImage)); + SkASSERT(fGlyphAlloc.contains(glyph->fImage)); } } #endif } + +void SkGlyphCache_Globals::validate() const { + size_t computedBytes = 0; + int computedCount = 0; + + const SkGlyphCache* head = fHead; + while (head != NULL) { + computedBytes += head->fMemoryUsed; + computedCount += 1; + head = head->fNext; + } + + SkASSERT(fTotalMemoryUsed == computedBytes); + SkASSERT(fCacheCount == computedCount); +} + #endif /////////////////////////////////////////////////////////////////////////////// @@ -721,15 +676,27 @@ void SkGlyphCache::validate() const { #include "SkTypefaceCache.h" size_t SkGraphics::GetFontCacheLimit() { - return getSharedGlobals().getFontCacheLimit(); + return getSharedGlobals().getCacheSizeLimit(); } size_t SkGraphics::SetFontCacheLimit(size_t bytes) { - return getSharedGlobals().setFontCacheLimit(bytes); + return getSharedGlobals().setCacheSizeLimit(bytes); } size_t SkGraphics::GetFontCacheUsed() { - return getSharedGlobals().fTotalMemoryUsed; + return getSharedGlobals().getTotalMemoryUsed(); +} + +int SkGraphics::GetFontCacheCountLimit() { + return getSharedGlobals().getCacheCountLimit(); +} + +int SkGraphics::SetFontCacheCountLimit(int count) { + return getSharedGlobals().setCacheCountLimit(count); +} + +int SkGraphics::GetFontCacheCountUsed() { + return getSharedGlobals().getCacheCountUsed(); } void SkGraphics::PurgeFontCache() { @@ -739,13 +706,13 @@ void SkGraphics::PurgeFontCache() { size_t SkGraphics::GetTLSFontCacheLimit() { const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); - return tls ? tls->getFontCacheLimit() : 0; + return tls ? tls->getCacheSizeLimit() : 0; } void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { if (0 == bytes) { SkGlyphCache_Globals::DeleteTLS(); } else { - SkGlyphCache_Globals::GetTLS().setFontCacheLimit(bytes); + SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); } } diff --git a/gfx/skia/src/core/SkGlyphCache.h b/gfx/skia/trunk/src/core/SkGlyphCache.h similarity index 87% rename from gfx/skia/src/core/SkGlyphCache.h rename to gfx/skia/trunk/src/core/SkGlyphCache.h index 39a1c389c2f4..7b2ebb844e21 100644 --- a/gfx/skia/src/core/SkGlyphCache.h +++ b/gfx/skia/trunk/src/core/SkGlyphCache.h @@ -95,8 +95,8 @@ public: /** Return the vertical metrics for this strike. */ - const SkPaint::FontMetrics& getFontMetricsY() const { - return fFontMetricsY; + const SkPaint::FontMetrics& getFontMetrics() const { + return fFontMetrics; } const SkDescriptor& getDescriptor() const { return *fDesc; } @@ -185,7 +185,8 @@ public: }; private: - SkGlyphCache(SkTypeface*, const SkDescriptor*); + // we take ownership of the scalercontext + SkGlyphCache(SkTypeface*, const SkDescriptor*, SkScalerContext*); ~SkGlyphCache(); enum MetricsType { @@ -196,43 +197,19 @@ private: SkGlyph* lookupMetrics(uint32_t id, MetricsType); static bool DetachProc(const SkGlyphCache*, void*) { return true; } - void detach(SkGlyphCache** head) { - if (fPrev) { - fPrev->fNext = fNext; - } else { - *head = fNext; - } - if (fNext) { - fNext->fPrev = fPrev; - } - fPrev = fNext = NULL; - } - - void attachToHead(SkGlyphCache** head) { - SkASSERT(NULL == fPrev && NULL == fNext); - if (*head) { - (*head)->fPrev = this; - fNext = *head; - } - *head = this; - } - SkGlyphCache* fNext, *fPrev; SkDescriptor* fDesc; SkScalerContext* fScalerContext; - SkPaint::FontMetrics fFontMetricsY; + SkPaint::FontMetrics fFontMetrics; enum { - kHashBits = 12, + kHashBits = 8, kHashCount = 1 << kHashBits, kHashMask = kHashCount - 1 }; SkGlyph* fGlyphHash[kHashCount]; SkTDArray fGlyphArray; SkChunkAlloc fGlyphAlloc; - SkChunkAlloc fImageAlloc; - - int fMetricsCount, fAdvanceCount; struct CharGlyphRec { uint32_t fID; // unichar + subpixel @@ -241,15 +218,10 @@ private: // no reason to use the same kHashCount as fGlyphHash, but we do for now CharGlyphRec fCharToGlyphHash[kHashCount]; - enum { - // shift so that the top bits fall into kHashBits region - kShiftForHashIndex = SkGlyph::kSubShift + - SkGlyph::kSubBits*2 - - kHashBits - }; - static inline unsigned ID2HashIndex(uint32_t id) { - return (id ^ (id >> kShiftForHashIndex)) & kHashMask; + id ^= id >> 16; + id ^= id >> 8; + return id & kHashMask; } // used to track (approx) how much ram is tied-up in this cache @@ -263,9 +235,6 @@ private: AuxProcRec* fAuxProcList; void invokeAndRemoveAuxProcs(); - // This relies on the caller to have already acquired the mutex to access the global cache - static size_t InternalFreeCache(SkGlyphCache_Globals*, size_t bytesNeeded); - inline static SkGlyphCache* FindTail(SkGlyphCache* head); friend class SkGlyphCache_Globals; @@ -302,5 +271,6 @@ private: static bool DetachProc(const SkGlyphCache*, void*); }; +#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache) #endif diff --git a/gfx/skia/trunk/src/core/SkGlyphCache_Globals.h b/gfx/skia/trunk/src/core/SkGlyphCache_Globals.h new file mode 100644 index 000000000000..4bd607c59803 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkGlyphCache_Globals.h @@ -0,0 +1,122 @@ +/* + * 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 SkGlyphCache_Globals_DEFINED +#define SkGlyphCache_Globals_DEFINED + +#include "SkGlyphCache.h" +#include "SkTLS.h" + +#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT + #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048 +#endif + +#ifndef SK_DEFAULT_FONT_CACHE_LIMIT + #define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024) +#endif + +/////////////////////////////////////////////////////////////////////////////// + +class SkMutex; + +class SkGlyphCache_Globals { +public: + enum UseMutex { + kNo_UseMutex, // thread-local cache + kYes_UseMutex // shared cache + }; + + SkGlyphCache_Globals(UseMutex um) { + fHead = NULL; + fTotalMemoryUsed = 0; + fCacheSizeLimit = SK_DEFAULT_FONT_CACHE_LIMIT; + fCacheCount = 0; + fCacheCountLimit = SK_DEFAULT_FONT_CACHE_COUNT_LIMIT; + + fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL; + } + + ~SkGlyphCache_Globals() { + SkGlyphCache* cache = fHead; + while (cache) { + SkGlyphCache* next = cache->fNext; + SkDELETE(cache); + cache = next; + } + + SkDELETE(fMutex); + } + + SkMutex* fMutex; + + SkGlyphCache* internalGetHead() const { return fHead; } + SkGlyphCache* internalGetTail() const; + + size_t getTotalMemoryUsed() const { return fTotalMemoryUsed; } + int getCacheCountUsed() const { return fCacheCount; } + +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif + + int getCacheCountLimit() const { return fCacheCountLimit; } + int setCacheCountLimit(int limit); + + size_t getCacheSizeLimit() const { return fCacheSizeLimit; } + size_t setCacheSizeLimit(size_t limit); + + // returns true if this cache is over-budget either due to size limit + // or count limit. + bool isOverBudget() const { + return fCacheCount > fCacheCountLimit || + fTotalMemoryUsed > fCacheSizeLimit; + } + + void purgeAll(); // does not change budget + + // call when a glyphcache is available for caching (i.e. not in use) + void attachCacheToHead(SkGlyphCache*); + + // can only be called when the mutex is already held + void internalDetachCache(SkGlyphCache*); + void internalAttachCacheToHead(SkGlyphCache*); + + // can return NULL + static SkGlyphCache_Globals* FindTLS() { + return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS); + } + + static SkGlyphCache_Globals& GetTLS() { + return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS); + } + + static void DeleteTLS() { SkTLS::Delete(CreateTLS); } + +private: + SkGlyphCache* fHead; + size_t fTotalMemoryUsed; + size_t fCacheSizeLimit; + int32_t fCacheCountLimit; + int32_t fCacheCount; + + // Checkout budgets, modulated by the specified min-bytes-needed-to-purge, + // and attempt to purge caches to match. + // Returns number of bytes freed. + size_t internalPurge(size_t minBytesNeeded = 0); + + static void* CreateTLS() { + return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex)); + } + + static void DeleteTLS(void* ptr) { + SkDELETE((SkGlyphCache_Globals*)ptr); + } +}; + +#endif diff --git a/gfx/skia/src/core/SkGraphics.cpp b/gfx/skia/trunk/src/core/SkGraphics.cpp similarity index 95% rename from gfx/skia/src/core/SkGraphics.cpp rename to gfx/skia/trunk/src/core/SkGraphics.cpp index 8e7c7cd31db1..95a8166dfcfe 100644 --- a/gfx/skia/src/core/SkGraphics.cpp +++ b/gfx/skia/trunk/src/core/SkGraphics.cpp @@ -9,7 +9,6 @@ #include "SkGraphics.h" -#include "Sk64.h" #include "SkBlitter.h" #include "SkCanvas.h" #include "SkFloat.h" @@ -55,11 +54,12 @@ 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 - SkFlattenable::InitializeFlattenables(); #ifdef BUILD_EMBOSS_TABLE SkEmbossMask_BuildTable(); #endif @@ -129,6 +129,7 @@ void SkGraphics::Init() { void SkGraphics::Term() { PurgeFontCache(); SkPaint::Term(); + SkXfermode::Term(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/gfx/skia/trunk/src/core/SkImageFilter.cpp b/gfx/skia/trunk/src/core/SkImageFilter.cpp new file mode 100644 index 000000000000..cd7c01b4e67e --- /dev/null +++ b/gfx/skia/trunk/src/core/SkImageFilter.cpp @@ -0,0 +1,244 @@ +/* + * 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. + */ + +#include "SkImageFilter.h" + +#include "SkBitmap.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" +#include "SkRect.h" +#include "SkValidationUtils.h" +#if SK_SUPPORT_GPU +#include "GrContext.h" +#include "GrTexture.h" +#include "SkImageFilterUtils.h" +#endif + +SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect) + : fInputCount(inputCount), + fInputs(new SkImageFilter*[inputCount]), + fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { + for (int i = 0; i < inputCount; ++i) { + fInputs[i] = inputs[i]; + SkSafeRef(fInputs[i]); + } +} + +SkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect) + : fInputCount(1), + fInputs(new SkImageFilter*[1]), + fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { + fInputs[0] = input; + SkSafeRef(fInputs[0]); +} + +SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect) + : fInputCount(2), fInputs(new SkImageFilter*[2]), + fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) { + fInputs[0] = input1; + fInputs[1] = input2; + SkSafeRef(fInputs[0]); + SkSafeRef(fInputs[1]); +} + +SkImageFilter::~SkImageFilter() { + for (int i = 0; i < fInputCount; i++) { + SkSafeUnref(fInputs[i]); + } + delete[] fInputs; +} + +SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) { + fInputCount = buffer.readInt(); + if (buffer.validate((fInputCount >= 0) && ((inputCount < 0) || (fInputCount == inputCount)))) { + fInputs = new SkImageFilter*[fInputCount]; + for (int i = 0; i < fInputCount; i++) { + if (buffer.readBool()) { + fInputs[i] = buffer.readImageFilter(); + } else { + fInputs[i] = NULL; + } + if (!buffer.isValid()) { + fInputCount = i; // Do not use fInputs past that point in the destructor + break; + } + } + SkRect rect; + buffer.readRect(&rect); + if (buffer.isValid() && buffer.validate(SkIsValidRect(rect))) { + uint32_t flags = buffer.readUInt(); + fCropRect = CropRect(rect, flags); + } + } else { + fInputCount = 0; + fInputs = NULL; + } +} + +void SkImageFilter::flatten(SkWriteBuffer& buffer) const { + buffer.writeInt(fInputCount); + for (int i = 0; i < fInputCount; i++) { + SkImageFilter* input = getInput(i); + buffer.writeBool(input != NULL); + if (input != NULL) { + buffer.writeFlattenable(input); + } + } + buffer.writeRect(fCropRect.rect()); + buffer.writeUInt(fCropRect.flags()); +} + +bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, + const SkMatrix& ctm, + SkBitmap* result, SkIPoint* offset) const { + SkASSERT(result); + SkASSERT(offset); + /* + * 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, offset)) || + this->onFilterImage(proxy, src, ctm, result, offset); +} + +bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, + SkIRect* dst) const { + SkASSERT(&src); + SkASSERT(dst); + return this->onFilterBounds(src, ctm, dst); +} + +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 SkMatrix&, + SkBitmap*, SkIPoint*) const { + return false; +} + +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) const { +#if SK_SUPPORT_GPU + SkBitmap input; + SkASSERT(fInputCount == 1); + SkIPoint srcOffset = SkIPoint::Make(0, 0); + if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, &srcOffset)) { + return false; + } + GrTexture* srcTexture = input.getTexture(); + SkIRect bounds; + src.getBounds(&bounds); + bounds.offset(srcOffset); + if (!this->applyCropRect(&bounds, ctm)) { + return false; + } + SkRect srcRect = SkRect::Make(bounds); + SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); + GrContext* context = srcTexture->getContext(); + + GrTextureDesc desc; + desc.fFlags = kRenderTarget_GrTextureFlagBit, + desc.fWidth = bounds.width(); + desc.fHeight = bounds.height(); + desc.fConfig = kRGBA_8888_GrPixelConfig; + + GrAutoScratchTexture dst(context, desc); + GrContext::AutoMatrix am; + am.setIdentity(context); + GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget()); + GrContext::AutoClip acs(context, dstRect); + GrEffectRef* effect; + offset->fX = bounds.left(); + offset->fY = bounds.top(); + bounds.offset(-srcOffset); + SkMatrix matrix(ctm); + matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); + this->asNewEffect(&effect, srcTexture, matrix, bounds); + SkASSERT(effect); + SkAutoUnref effectRef(effect); + GrPaint paint; + paint.addColorEffect(effect); + context->drawRectToRect(paint, dstRect, srcRect); + + SkAutoTUnref resultTex(dst.detach()); + SkImageFilterUtils::WrapTexture(resultTex, bounds.width(), bounds.height(), result); + return true; +#else + return false; +#endif +} + +bool SkImageFilter::applyCropRect(SkIRect* rect, const SkMatrix& matrix) const { + SkRect cropRect; + matrix.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); +} + +bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, + 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; +} + +bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&, const SkIRect&) const { + return false; +} + +bool SkImageFilter::asColorFilter(SkColorFilter**) const { + return false; +} diff --git a/gfx/skia/trunk/src/core/SkImageFilterUtils.cpp b/gfx/skia/trunk/src/core/SkImageFilterUtils.cpp new file mode 100644 index 000000000000..c6c534e71dfc --- /dev/null +++ b/gfx/skia/trunk/src/core/SkImageFilterUtils.cpp @@ -0,0 +1,55 @@ +/* + * 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 = SkImageInfo::MakeN32Premul(width, height); + result->setConfig(info); + result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref(); + return true; +} + +bool SkImageFilterUtils::GetInputResultGPU(const 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) { + offset->fX = offset->fY = 0; + *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/gfx/skia/trunk/src/core/SkImageInfo.cpp b/gfx/skia/trunk/src/core/SkImageInfo.cpp new file mode 100644 index 000000000000..27c457391f15 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkImageInfo.cpp @@ -0,0 +1,40 @@ +/* + * 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 "SkImageInfo.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" + +static bool alpha_type_is_valid(SkAlphaType alphaType) { + return (alphaType >= 0) && (alphaType <= kLastEnum_SkAlphaType); +} + +static bool color_type_is_valid(SkColorType colorType) { + return (colorType >= 0) && (colorType <= kLastEnum_SkColorType); +} + +void SkImageInfo::unflatten(SkReadBuffer& buffer) { + fWidth = buffer.read32(); + fHeight = buffer.read32(); + + uint32_t packed = buffer.read32(); + SkASSERT(0 == (packed >> 16)); + fAlphaType = (SkAlphaType)((packed >> 8) & 0xFF); + fColorType = (SkColorType)((packed >> 0) & 0xFF); + buffer.validate(alpha_type_is_valid(fAlphaType) && + color_type_is_valid(fColorType)); +} + +void SkImageInfo::flatten(SkWriteBuffer& buffer) const { + buffer.write32(fWidth); + buffer.write32(fHeight); + + SkASSERT(0 == (fAlphaType & ~0xFF)); + SkASSERT(0 == (fColorType & ~0xFF)); + uint32_t packed = (fAlphaType << 8) | fColorType; + buffer.write32(packed); +} diff --git a/gfx/skia/src/core/SkInstCnt.cpp b/gfx/skia/trunk/src/core/SkInstCnt.cpp similarity index 100% rename from gfx/skia/src/core/SkInstCnt.cpp rename to gfx/skia/trunk/src/core/SkInstCnt.cpp diff --git a/gfx/skia/src/core/SkLineClipper.cpp b/gfx/skia/trunk/src/core/SkLineClipper.cpp similarity index 94% rename from gfx/skia/src/core/SkLineClipper.cpp rename to gfx/skia/trunk/src/core/SkLineClipper.cpp index fc4e3d259285..1645917d70f5 100644 --- a/gfx/skia/src/core/SkLineClipper.cpp +++ b/gfx/skia/trunk/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 @@ -176,17 +165,15 @@ static bool is_between_unsorted(SkScalar value, static void sect_with_horizontal_test_for_pin_results() { const SkPoint pts[] = { { -540000, -720000 }, - { SkFloatToScalar(-9.10000017e-05f), SkFloatToScalar(9.99999996e-13f) } + { -9.10000017e-05f, 9.99999996e-13f } }; float x = sect_with_horizontal(pts, 0); 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; @@ -195,7 +182,6 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, gOnce = true; } } -#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/gfx/skia/trunk/src/core/SkMallocPixelRef.cpp b/gfx/skia/trunk/src/core/SkMallocPixelRef.cpp new file mode 100644 index 000000000000..aa7c4f745cd5 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMallocPixelRef.cpp @@ -0,0 +1,248 @@ +/* + * 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 "SkMallocPixelRef.h" +#include "SkBitmap.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 || + info.fHeight < 0 || + (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType || + (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType) + { + 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? +#if 0 + if (kIndex8_SkColorType == info.fColorType && NULL == ctable) { + return false; + } + if (kIndex8_SkColorType != info.fColorType && NULL != ctable) { + return false; + } +#endif + return true; +} + +SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info, + void* addr, + size_t rowBytes, + SkColorTable* ctable) { + if (!is_valid(info, ctable)) { + return NULL; + } + return SkNEW_ARGS(SkMallocPixelRef, + (info, addr, rowBytes, ctable, NULL, NULL)); +} + +SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info, + size_t requestedRowBytes, + SkColorTable* ctable) { + if (!is_valid(info, ctable)) { + return NULL; + } + + int32_t minRB = SkToS32(info.minRowBytes()); + if (minRB < 0) { + return NULL; // allocation will be too large + } + if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) { + return NULL; // cannot meet requested rowbytes + } + + int32_t rowBytes; + if (requestedRowBytes) { + rowBytes = SkToS32(requestedRowBytes); + } else { + rowBytes = minRB; + } + + int64_t bigSize = (int64_t)info.fHeight * rowBytes; + if (!sk_64_isS32(bigSize)) { + return NULL; + } + + 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, + 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(dataPtr))->unref(); +} + +SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info, + size_t rowBytes, + SkColorTable* ctable, + SkData* data, + size_t offset) { + SkASSERT(data != NULL); + SkASSERT(offset <= data->size()); + if (!is_valid(info, ctable)) { + return NULL; + } + if ((rowBytes < info.minRowBytes()) + || ((data->size() - offset) < info.getSafeSize(rowBytes))) { + return NULL; + } + data->ref(); + const void* ptr = static_cast(data->bytes() + offset); + SkMallocPixelRef* pr + = SkNEW_ARGS(SkMallocPixelRef, + (info, const_cast(ptr), rowBytes, ctable, + sk_data_releaseproc, static_cast(data))); + SkASSERT(pr != NULL); + // We rely on the immutability of the pixels to make the + // const_cast okay. + pr->setImmutable(); + return pr; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage, + size_t rowBytes, SkColorTable* ctable, + bool ownsPixels) + : INHERITED(info) + , 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()); + + if (kIndex_8_SkColorType != info.fColorType) { + ctable = NULL; + } + + fStorage = storage; + fCTable = ctable; + fRB = rowBytes; + SkSafeRef(ctable); + + this->setPreLocked(fStorage, rowBytes, fCTable); +} + + +SkMallocPixelRef::~SkMallocPixelRef() { + SkSafeUnref(fCTable); + if (fReleaseProc != NULL) { + fReleaseProc(fStorage, fReleaseProcContext); + } +} + +bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) { + rec->fPixels = fStorage; + rec->fRowBytes = fRB; + rec->fColorTable = fCTable; + return true; +} + +void SkMallocPixelRef::onUnlockPixels() { + // nothing to do +} + +size_t SkMallocPixelRef::getAllocatedSizeInBytes() const { + return this->info().getSafeSize(fRB); +} + +void SkMallocPixelRef::flatten(SkWriteBuffer& buffer) const { + this->INHERITED::flatten(buffer); + + 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) + size_t size = this->info().getSafeSize(fRB); + buffer.writeByteArray(fStorage, size); + buffer.writeBool(fCTable != NULL); + if (fCTable) { + fCTable->writeToBuffer(buffer); + } +} + +SkMallocPixelRef::SkMallocPixelRef(SkReadBuffer& buffer) + : INHERITED(buffer, NULL) + , fReleaseProc(sk_free_releaseproc) + , fReleaseProcContext(NULL) +{ + fRB = buffer.read32(); + size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0; + 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, fRB, fCTable); +} + +/////////////////////////////////////////////////////////////////////////////// + +SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, + SkColorTable* ctable) { + return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable); +} diff --git a/gfx/skia/src/core/SkMask.cpp b/gfx/skia/trunk/src/core/SkMask.cpp similarity index 91% rename from gfx/skia/src/core/SkMask.cpp rename to gfx/skia/trunk/src/core/SkMask.cpp index 09744194b9d6..929835717ba9 100644 --- a/gfx/skia/src/core/SkMask.cpp +++ b/gfx/skia/trunk/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/gfx/skia/src/core/SkMaskFilter.cpp b/gfx/skia/trunk/src/core/SkMaskFilter.cpp similarity index 72% rename from gfx/skia/src/core/SkMaskFilter.cpp rename to gfx/skia/trunk/src/core/SkMaskFilter.cpp index 9805bf9b054e..b96743d12953 100644 --- a/gfx/skia/src/core/SkMaskFilter.cpp +++ b/gfx/skia/trunk/src/core/SkMaskFilter.cpp @@ -12,9 +12,14 @@ #include "SkBounder.h" #include "SkDraw.h" #include "SkRasterClip.h" +#include "SkRRect.h" +#include "SkTypes.h" - -SK_DEFINE_INST_COUNT(SkMaskFilter) +#if SK_SUPPORT_GPU +#include "GrTexture.h" +#include "SkGr.h" +#include "SkGrPixelRef.h" +#endif bool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&, SkIPoint*) const { @@ -69,34 +74,42 @@ static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR, m.fBounds = mask.fBounds; m.fBounds.fRight = cx; m.fBounds.fBottom = cy; - extractMaskSubset(mask, &m); - m.fBounds.offsetTo(outerR.left(), outerR.top()); - blitClippedMask(blitter, m, m.fBounds, clipR); + if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { + extractMaskSubset(mask, &m); + m.fBounds.offsetTo(outerR.left(), outerR.top()); + blitClippedMask(blitter, m, m.fBounds, clipR); + } // top-right m.fBounds = mask.fBounds; m.fBounds.fLeft = cx + 1; m.fBounds.fBottom = cy; - extractMaskSubset(mask, &m); - m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top()); - blitClippedMask(blitter, m, m.fBounds, clipR); + if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { + extractMaskSubset(mask, &m); + m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top()); + blitClippedMask(blitter, m, m.fBounds, clipR); + } // bottom-left m.fBounds = mask.fBounds; m.fBounds.fRight = cx; m.fBounds.fTop = cy + 1; - extractMaskSubset(mask, &m); - m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height()); - blitClippedMask(blitter, m, m.fBounds, clipR); + if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { + extractMaskSubset(mask, &m); + m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height()); + blitClippedMask(blitter, m, m.fBounds, clipR); + } // bottom-right m.fBounds = mask.fBounds; m.fBounds.fLeft = cx + 1; m.fBounds.fTop = cy + 1; - extractMaskSubset(mask, &m); - m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), - outerR.bottom() - m.fBounds.height()); - blitClippedMask(blitter, m, m.fBounds, clipR); + if (m.fBounds.width() > 0 && m.fBounds.height() > 0) { + extractMaskSubset(mask, &m); + m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), + outerR.bottom() - m.fBounds.height()); + blitClippedMask(blitter, m, m.fBounds, clipR); + } SkIRect innerR; innerR.set(outerR.left() + cx - mask.fBounds.left(), @@ -190,6 +203,26 @@ static int countNestedRects(const SkPath& path, SkRect rects[2]) { return path.isRect(&rects[0]); } +bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix, + const SkRasterClip& clip, SkBounder* bounder, + 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. + NinePatch patch; + patch.fMask.fImage = NULL; + if (kTrue_FilterReturn != this->filterRRectToNine(devRRect, matrix, + clip.getBounds(), + &patch)) { + SkASSERT(NULL == patch.fMask.fImage); + return false; + } + draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, + bounder, 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 { @@ -252,16 +285,47 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix, return true; } +SkMaskFilter::FilterReturn +SkMaskFilter::filterRRectToNine(const SkRRect&, const SkMatrix&, + const SkIRect& clipBounds, NinePatch*) const { + return kUnimplemented_FilterReturn; +} + SkMaskFilter::FilterReturn SkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&, const SkIRect& clipBounds, NinePatch*) const { return kUnimplemented_FilterReturn; } -SkMaskFilter::BlurType SkMaskFilter::asABlur(BlurInfo*) const { - return kNone_BlurType; +#if SK_SUPPORT_GPU +bool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix&) const { + return false; } +bool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds, + const SkIRect& clipBounds, + const SkMatrix& ctm, + SkRect* maskRect) const { + return false; +} + + bool SkMaskFilter::directFilterMaskGPU(GrContext* context, + GrPaint* grp, + const SkStrokeRec& strokeRec, + const SkPath& path) const { + return false; +} + + +bool SkMaskFilter::filterMaskGPU(GrTexture* src, + const SkMatrix& ctm, + const SkRect& maskRect, + GrTexture** result, + bool canOverwriteSrc) const { + return false; +} +#endif + void SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { SkMask srcM, dstM; diff --git a/gfx/skia/src/core/SkMaskGamma.cpp b/gfx/skia/trunk/src/core/SkMaskGamma.cpp similarity index 90% rename from gfx/skia/src/core/SkMaskGamma.cpp rename to gfx/skia/trunk/src/core/SkMaskGamma.cpp index 9066fb7d9fe6..a305d7216288 100644 --- a/gfx/skia/src/core/SkMaskGamma.cpp +++ b/gfx/skia/trunk/src/core/SkMaskGamma.cpp @@ -36,21 +36,21 @@ class SkSRGBColorSpaceLuminance : public SkColorSpaceLuminance { SkASSERT(0 == gamma); //The magic numbers are derived from the sRGB specification. //See http://www.color.org/chardata/rgb/srgb.xalter . - if (luminance <= SkFloatToScalar(0.04045f)) { - return luminance / SkFloatToScalar(12.92f); + if (luminance <= 0.04045f) { + return luminance / 12.92f; } - return SkScalarPow((luminance + SkFloatToScalar(0.055f)) / SkFloatToScalar(1.055f), - SkFloatToScalar(2.4f)); + return SkScalarPow((luminance + 0.055f) / 1.055f, + 2.4f); } virtual SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const SK_OVERRIDE { SkASSERT(0 == gamma); //The magic numbers are derived from the sRGB specification. //See http://www.color.org/chardata/rgb/srgb.xalter . - if (luma <= SkFloatToScalar(0.0031308f)) { - return luma * SkFloatToScalar(12.92f); + if (luma <= 0.0031308f) { + return luma * 12.92f; } - return SkFloatToScalar(1.055f) * SkScalarPow(luma, SkScalarInvert(SkFloatToScalar(2.4f))) - - SkFloatToScalar(0.055f); + return 1.055f * SkScalarPow(luma, SkScalarInvert(2.4f)) + - 0.055f; } }; diff --git a/gfx/skia/src/core/SkMaskGamma.h b/gfx/skia/trunk/src/core/SkMaskGamma.h similarity index 95% rename from gfx/skia/src/core/SkMaskGamma.h rename to gfx/skia/trunk/src/core/SkMaskGamma.h index fafe4ac7761d..1f2b73caacd4 100644 --- a/gfx/skia/src/core/SkMaskGamma.h +++ b/gfx/skia/trunk/src/core/SkMaskGamma.h @@ -35,9 +35,9 @@ public: SkScalar r = luminance.toLuma(gamma, SkIntToScalar(SkColorGetR(c)) / 255); SkScalar g = luminance.toLuma(gamma, SkIntToScalar(SkColorGetG(c)) / 255); SkScalar b = luminance.toLuma(gamma, SkIntToScalar(SkColorGetB(c)) / 255); - SkScalar luma = r * SkFloatToScalar(SK_LUM_COEFF_R) + - g * SkFloatToScalar(SK_LUM_COEFF_G) + - b * SkFloatToScalar(SK_LUM_COEFF_B); + SkScalar luma = r * SK_LUM_COEFF_R + + g * SK_LUM_COEFF_G + + b * SK_LUM_COEFF_B; SkASSERT(luma <= SK_Scalar1); return SkScalarRoundToInt(luminance.fromLuma(gamma, luma) * 255); } @@ -92,8 +92,8 @@ void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar * @param B The number of luminance bits to use [1, 8] from the blue channel. */ template class SkTMaskGamma : public SkRefCnt { + SK_DECLARE_INST_COUNT(SkTMaskGamma) public: - SK_DECLARE_INST_COUNT_TEMPLATE(SkTMaskGamma) /** Creates a linear SkTMaskGamma. */ SkTMaskGamma() : fIsLinear(true) { } @@ -147,11 +147,6 @@ private: }; -#define MacroComma , -SK_DEFINE_INST_COUNT_TEMPLATE( - template , - SkTMaskGamma); - /** * SkTMaskPreBlend is a tear-off of SkTMaskGamma. It provides the tables to * convert a linear alpha value for a given channel to a gamma correcting alpha diff --git a/gfx/skia/src/core/SkMath.cpp b/gfx/skia/trunk/src/core/SkMath.cpp similarity index 55% rename from gfx/skia/src/core/SkMath.cpp rename to gfx/skia/trunk/src/core/SkMath.cpp index 0efedd727b08..25ac9aa93662 100644 --- a/gfx/skia/src/core/SkMath.cpp +++ b/gfx/skia/trunk/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; \ @@ -27,7 +23,6 @@ int SkCLZ_portable(uint32_t x) { return 32; } -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR int zeros = 31; if (x & 0xFFFF0000) { sub_shift(zeros, x, 16); @@ -44,24 +39,6 @@ int SkCLZ_portable(uint32_t x) { if (x & 0x2) { sub_shift(zeros, x, 1); } -#else - int zeros = ((x >> 16) - 1) >> 31 << 4; - x <<= zeros; - - int nonzero = ((x >> 24) - 1) >> 31 << 3; - zeros += nonzero; - x <<= nonzero; - - nonzero = ((x >> 28) - 1) >> 31 << 2; - zeros += nonzero; - x <<= nonzero; - - nonzero = ((x >> 30) - 1) >> 31 << 1; - zeros += nonzero; - x <<= nonzero; - - zeros += (~x) >> 31; -#endif return zeros; } @@ -69,70 +46,13 @@ int SkCLZ_portable(uint32_t x) { 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; - } + int64_t tmp = sk_64_mul(numer1, numer2) / denom; + return sk_64_asS32(tmp); } 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((SkLONGLONG)a * b >> 16); +#if defined(SkLONGLONG) + return static_cast((int64_t)a * b >> 16); #else int sa = SkExtractSign(a); int sb = SkExtractSign(b); @@ -151,103 +71,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((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) \ @@ -316,26 +139,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) { @@ -361,41 +164,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); @@ -411,7 +181,6 @@ float SkScalarSinCos(float radians, float* cosValue) { } return sinValue; } -#endif #define INTERP_SINTABLE #define BUILD_TABLE_AT_RUNTIMEx @@ -525,12 +294,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/gfx/skia/src/core/SkMathPriv.h b/gfx/skia/trunk/src/core/SkMathPriv.h similarity index 78% rename from gfx/skia/src/core/SkMathPriv.h rename to gfx/skia/trunk/src/core/SkMathPriv.h index 53cf43063d1e..f93ab610787b 100644 --- a/gfx/skia/src/core/SkMathPriv.h +++ b/gfx/skia/trunk/src/core/SkMathPriv.h @@ -33,30 +33,12 @@ static inline int32_t SkCopySign32(int32_t x, int32_t y) { @return max if value >= max, else value */ static inline unsigned SkClampUMax(unsigned value, unsigned max) { -#ifdef SK_CPU_HAS_CONDITIONAL_INSTR if (value > max) { value = max; } return value; -#else - int diff = max - value; - // clear diff if diff is positive - diff &= diff >> 31; - - return value + diff; -#endif } -/** 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/gfx/skia/src/core/SkMatrix.cpp b/gfx/skia/trunk/src/core/SkMatrix.cpp similarity index 58% rename from gfx/skia/src/core/SkMatrix.cpp rename to gfx/skia/trunk/src/core/SkMatrix.cpp index d9675f3979b4..33af64a41fe9 100644 --- a/gfx/skia/src/core/SkMatrix.cpp +++ b/gfx/skia/trunk/src/core/SkMatrix.cpp @@ -6,20 +6,28 @@ */ #include "SkMatrix.h" -#include "Sk64.h" #include "SkFloatBits.h" -#include "SkScalarCompare.h" +#include "SkOnce.h" #include "SkString.h" -#ifdef SK_SCALAR_IS_FLOAT - #define kMatrix22Elem SK_Scalar1 +// 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(x); - } -#else - #define kMatrix22Elem SK_Fract1 -#endif +static inline float SkDoubleToFloat(double x) { + return static_cast(x); +} /* [scale-x skew-x trans-x] [X] [X'] [skew-y scale-y trans-y] * [Y] = [Y'] @@ -27,11 +35,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,35 +52,19 @@ enum { kRectStaysRect_Shift }; -#ifdef SK_SCALAR_IS_FLOAT - static const int32_t kScalar1Int = 0x3f800000; - static const int32_t kPersp1Int = 0x3f800000; -#else - #define scalarAsInt(x) (x) - static const int32_t kScalar1Int = (1 << 16); - static const int32_t kPersp1Int = (1 << 30); -#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); } @@ -81,20 +72,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); @@ -103,7 +81,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]); @@ -155,8 +132,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; @@ -166,7 +141,14 @@ 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 +static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, + SkScalar skewY, SkScalar scaleY) { + SkScalar perp_dot = scaleX*scaleY - skewX*skewY; + return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); +} /////////////////////////////////////////////////////////////////////////////// @@ -189,9 +171,7 @@ bool SkMatrix::isSimilarity(SkScalar tol) const { SkScalar sx = fMat[kMSkewX]; SkScalar sy = fMat[kMSkewY]; - // degenerate matrix, non-similarity - if (SkScalarNearlyZero(mx) && SkScalarNearlyZero(my) - && SkScalarNearlyZero(sx) && SkScalarNearlyZero(sy)) { + if (is_degenerate_2x2(mx, sx, sy, my)) { return false; } @@ -202,20 +182,64 @@ bool SkMatrix::isSimilarity(SkScalar tol) const { return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), - SkScalarSquare(tol)); + SkScalarSquare(tol)); +} + +bool SkMatrix::preservesRightAngles(SkScalar tol) const { + TypeMask mask = this->getType(); + + if (mask <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { + // identity, translate and/or scale + return true; + } + if (mask & kPerspective_Mask) { + return false; + } + + SkASSERT(mask & kAffine_Mask); + + SkScalar mx = fMat[kMScaleX]; + SkScalar my = fMat[kMScaleY]; + SkScalar sx = fMat[kMSkewX]; + SkScalar sy = fMat[kMSkewY]; + + if (is_degenerate_2x2(mx, sx, sy, my)) { + return false; + } + + // it has scales and skews, but it could also be rotation, check it out. + SkVector vec[2]; + vec[0].set(mx, sx); + vec[1].set(sy, my); + + return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && + SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), + SkScalarSquare(tol)); } /////////////////////////////////////////////////////////////////////////////// +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 (SkScalarToCompareType(dx) || SkScalarToCompareType(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 { @@ -230,11 +254,9 @@ bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { return this->preConcat(m); } - if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { - fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) + - SkScalarMul(fMat[kMSkewX], dy); - fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) + - SkScalarMul(fMat[kMScaleY], dy); + if (dx || dy) { + fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy); + fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); } @@ -248,7 +270,7 @@ bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { return this->postConcat(m); } - if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { + if (dx || dy) { fMat[kMTransX] += dx; fMat[kMTransY] += dy; this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); @@ -259,14 +281,14 @@ bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { /////////////////////////////////////////////////////////////////////////////// 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; @@ -276,12 +298,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] = @@ -295,7 +317,7 @@ 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; } @@ -306,35 +328,29 @@ bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { } bool SkMatrix::preScale(SkScalar sx, SkScalar sy) { - if (SK_Scalar1 == sx && SK_Scalar1 == sy) { + if (1 == sx && 1 == sy) { return true; } -#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) { + if (1 == sx && 1 == sy) { return true; } SkMatrix m; @@ -343,7 +359,7 @@ bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { } bool SkMatrix::postScale(SkScalar sx, SkScalar sy) { - if (SK_Scalar1 == sx && SK_Scalar1 == sy) { + if (1 == sx && 1 == sy) { return true; } SkMatrix m; @@ -351,19 +367,6 @@ bool SkMatrix::postScale(SkScalar sx, SkScalar sy) { return 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) { @@ -371,15 +374,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; @@ -390,7 +384,6 @@ bool SkMatrix::postIDiv(int divx, int divy) { fMat[kMScaleY] *= invY; fMat[kMSkewY] *= invY; fMat[kMTransY] *= invY; -#endif this->setTypeMask(kUnknown_Mask); return true; @@ -400,18 +393,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); } @@ -426,7 +419,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); } @@ -470,31 +463,31 @@ bool SkMatrix::postRotate(SkScalar degrees) { //////////////////////////////////////////////////////////////////////////////////// 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); } @@ -537,8 +530,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) { @@ -550,15 +543,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) { @@ -580,7 +573,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) { @@ -589,80 +582,31 @@ 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[], +static inline int fixmuladdmul(float a, float b, float c, float d, float* result) { - *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; - return true; - } + *result = SkDoubleToFloat((double)a * b + (double)c * d); + 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 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 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 int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) { - SkFixed c = a + b; - result = c; - return (c ^ a) & (c ^ b); - } -#endif +static inline int negifaddoverflows(float& result, float a, float b) { + result = a + b; + return 0; +} 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]); } @@ -748,7 +692,7 @@ bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { } 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); @@ -776,94 +720,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; +static inline SkScalar scross_dscale(SkScalar a, SkScalar b, + SkScalar c, SkScalar d, double scale) { + return SkDoubleToScalar(scross(a, b, c, d) * scale); +} - 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 double dcross(double a, double b, double c, double d) { + return a * b - c * d; +} - // 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 inline SkScalar dcross_dscale(double a, double b, + double c, double d, double scale) { + return SkDoubleToScalar(dcross(a, b, c, d) * scale); +} + +static double sk_inv_determinant(const float mat[9], int isPerspective) { + double det; + + 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]); } - 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); - } - - int s = tmp1.getClzAbs(); - *shift = s; - - SkFixed denom; - if (s <= 32) { - denom = tmp1.getShiftRight(33 - s); - } else { - denom = (int32_t)tmp1.fLo << (s - 33); - } - - if (denom == 0) { - return 0; - } - /** This could perhaps be a special fractdiv function, since both of its - arguments are known to have bit 31 clear and bit 30 set (when they - are made positive), thus eliminating the need for calling clz() - */ - return SkFractDiv(SK_Fract1, denom); + // 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; } -#endif + 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; } @@ -908,9 +814,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 { @@ -925,9 +831,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; @@ -940,83 +845,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[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); - 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[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); - 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 + 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 -#ifdef SK_SCALAR_IS_FIXED - Sk64 tx, ty; - int clzNumer; + 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); - // 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[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); - set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]); - set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]); - // check tx,ty for overflow - clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi)); - if (shift - clzNumer > 14) { - return false; // overflow - } - - int fixedShift = 61 - shift; - int sk64shift = 44 - shift + clzNumer; - - inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift); - inv->fMat[kMSkewX] = SkMulShift(-fMat[kMSkewX], scale, fixedShift); - inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift); - - inv->fMat[kMSkewY] = SkMulShift(-fMat[kMSkewY], scale, fixedShift); - inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift); - inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift); -#else - inv->fMat[kMScaleX] = 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); @@ -1062,8 +913,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); @@ -1080,8 +931,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); @@ -1101,8 +952,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); } @@ -1123,8 +974,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); } @@ -1134,33 +990,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); } @@ -1179,15 +1027,45 @@ const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { }; void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const { - SkASSERT((dst && src && count > 0) || count == 0); + SkASSERT((dst && src && count > 0) || 0 == count); // no partial overlap - SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count); + SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); this->getMapPtsProc()(*this, dst, src, count); } /////////////////////////////////////////////////////////////////////////////// +void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const { + SkASSERT((dst && src && count > 0) || 0 == count); + // no partial overlap + SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3*count); + + if (count > 0) { + if (this->isIdentity()) { + memcpy(dst, src, 3*count*sizeof(SkScalar)); + return; + } + do { + SkScalar sx = src[0]; + SkScalar sy = src[1]; + SkScalar sw = src[2]; + src += 3; + + 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; + dst[2] = w; + dst += 3; + } while (--count); + } +} + +/////////////////////////////////////////////////////////////////////////////// + void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { if (this->hasPerspective()) { SkPoint origin; @@ -1237,7 +1115,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); } /////////////////////////////////////////////////////////////////////////////// @@ -1246,51 +1125,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 } @@ -1300,14 +1154,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 } @@ -1316,8 +1168,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, @@ -1327,8 +1179,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, @@ -1362,19 +1214,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]); } @@ -1382,17 +1228,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); } } } @@ -1454,143 +1295,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; } @@ -1617,8 +1321,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; } } @@ -1680,13 +1383,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) */ @@ -1695,27 +1398,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; @@ -1723,8 +1424,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 @@ -1778,54 +1477,82 @@ bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], /////////////////////////////////////////////////////////////////////////////// -SkScalar SkMatrix::getMaxStretch() const { - TypeMask mask = this->getType(); +enum MinOrMax { + kMin_MinOrMax, + kMax_MinOrMax +}; - if (this->hasPerspective()) { - return -SK_Scalar1; +template SkScalar get_stretch_factor(SkMatrix::TypeMask typeMask, + const SkScalar m[9]) { + if (typeMask & SkMatrix::kPerspective_Mask) { + return -1; } - if (this->isIdentity()) { - return SK_Scalar1; + if (SkMatrix::kIdentity_Mask == typeMask) { + return 1; } - if (!(mask & kAffine_Mask)) { - return SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), - SkScalarAbs(fMat[kMScaleY])); + if (!(typeMask & SkMatrix::kAffine_Mask)) { + if (kMin_MinOrMax == MIN_OR_MAX) { + return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), + SkScalarAbs(m[SkMatrix::kMScaleY])); + } else { + return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), + SkScalarAbs(m[SkMatrix::kMScaleY])); + } } // ignore the translation part of the matrix, just look at 2x2 portion. - // compute singular values, take largest abs value. + // compute singular values, take largest or smallest abs value. // [a b; b c] = A^T*A - SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + - SkScalarMul(fMat[kMSkewY], fMat[kMSkewY]); - SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) + - SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]); - SkScalar c = SkScalarMul(fMat[kMSkewX], fMat[kMSkewX]) + - SkScalarMul(fMat[kMScaleY], fMat[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 guaraunteed to be pos and real). - SkScalar largerRoot; - SkScalar bSqd = SkScalarMul(b,b); + // and roots are guaranteed to be pos and real). + SkScalar chosenRoot; + SkScalar bSqd = b * b; // if upper left 2x2 is orthogonal save some math if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { - largerRoot = SkMaxScalar(a, c); + if (kMin_MinOrMax == MIN_OR_MAX) { + chosenRoot = SkMinScalar(a, c); + } else { + chosenRoot = SkMaxScalar(a, c); + } } else { SkScalar aminusc = a - c; SkScalar apluscdiv2 = SkScalarHalf(a + c); - SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); - largerRoot = apluscdiv2 + x; + SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); + if (kMin_MinOrMax == MIN_OR_MAX) { + chosenRoot = apluscdiv2 - x; + } else { + chosenRoot = apluscdiv2 + x; + } } - return SkScalarSqrt(largerRoot); + SkASSERT(chosenRoot >= 0); + return SkScalarSqrt(chosenRoot); +} + +SkScalar SkMatrix::getMinStretch() const { + return get_stretch_factor(this->getType(), fMat); +} + +SkScalar SkMatrix::getMaxStretch() const { + return get_stretch_factor(this->getType(), fMat); +} + +static void reset_identity_matrix(SkMatrix* identity) { + identity->reset(); } const SkMatrix& SkMatrix::I() { + // If you can use C++11 now, you might consider replacing this with a constexpr constructor. static SkMatrix gIdentity; - static bool gOnce; - if (!gOnce) { - gIdentity.reset(); - gOnce = true; - } + SK_DECLARE_STATIC_ONCE(once); + SkOnce(&once, reset_identity_matrix, &gIdentity); return gIdentity; } @@ -1844,20 +1571,25 @@ const SkMatrix& SkMatrix::InvalidMatrix() { /////////////////////////////////////////////////////////////////////////////// -uint32_t SkMatrix::writeToMemory(void* buffer) const { +size_t SkMatrix::writeToMemory(void* buffer) const { // TODO write less for simple matrices + static const size_t sizeInMemory = 9 * sizeof(SkScalar); if (buffer) { - memcpy(buffer, fMat, 9 * sizeof(SkScalar)); + memcpy(buffer, fMat, sizeInMemory); } - return 9 * sizeof(SkScalar); + return sizeInMemory; } -uint32_t SkMatrix::readFromMemory(const void* buffer) { +size_t SkMatrix::readFromMemory(const void* buffer, size_t length) { + static const size_t sizeInMemory = 9 * sizeof(SkScalar); + if (length < sizeInMemory) { + return 0; + } if (buffer) { - memcpy(fMat, buffer, 9 * sizeof(SkScalar)); + memcpy(fMat, buffer, sizeInMemory); this->setTypeMask(kUnknown_Mask); } - return 9 * sizeof(SkScalar); + return sizeInMemory; } #ifdef SK_DEVELOPER @@ -1869,14 +1601,8 @@ void SkMatrix::dump() const { 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 @@ -1931,3 +1657,105 @@ bool SkTreatAsSprite(const SkMatrix& mat, int width, int height, dst.round(&idst); return isrc == idst; } + +// A square matrix M can be decomposed (via polar decomposition) into two matrices -- +// an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, +// where U is another orthogonal matrix and W is a scale matrix. These can be recombined +// to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. +// +// The one wrinkle is that traditionally Q may contain a reflection -- the +// calculation has been rejiggered to put that reflection into W. +bool SkDecomposeUpper2x2(const SkMatrix& matrix, + SkPoint* rotation1, + SkPoint* scale, + SkPoint* rotation2) { + + SkScalar A = matrix[SkMatrix::kMScaleX]; + SkScalar B = matrix[SkMatrix::kMSkewX]; + SkScalar C = matrix[SkMatrix::kMSkewY]; + SkScalar D = matrix[SkMatrix::kMScaleY]; + + if (is_degenerate_2x2(A, B, C, D)) { + return false; + } + + double w1, w2; + SkScalar cos1, sin1; + SkScalar cos2, sin2; + + // do polar decomposition (M = Q*S) + SkScalar cosQ, sinQ; + double Sa, Sb, Sd; + // if M is already symmetric (i.e., M = I*S) + if (SkScalarNearlyEqual(B, C)) { + cosQ = 1; + sinQ = 0; + + Sa = A; + Sb = B; + Sd = D; + } else { + cosQ = A + D; + sinQ = C - B; + SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ)); + cosQ *= reciplen; + sinQ *= reciplen; + + // S = Q^-1*M + // we don't calc Sc since it's symmetric + Sa = A*cosQ + C*sinQ; + Sb = B*cosQ + D*sinQ; + Sd = -B*sinQ + D*cosQ; + } + + // Now we need to compute eigenvalues of S (our scale factors) + // and eigenvectors (bases for our rotation) + // From this, should be able to reconstruct S as U*W*U^T + if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { + // already diagonalized + cos1 = 1; + sin1 = 0; + w1 = Sa; + w2 = Sd; + cos2 = cosQ; + sin2 = sinQ; + } else { + double diff = Sa - Sd; + double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); + double trace = Sa + Sd; + if (diff > 0) { + w1 = 0.5*(trace + discriminant); + w2 = 0.5*(trace - discriminant); + } else { + w1 = 0.5*(trace - discriminant); + w2 = 0.5*(trace + discriminant); + } + + cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); + SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1)); + cos1 *= reciplen; + sin1 *= reciplen; + + // rotation 2 is composition of Q and U + cos2 = cos1*cosQ - sin1*sinQ; + sin2 = sin1*cosQ + cos1*sinQ; + + // rotation 1 is U^T + sin1 = -sin1; + } + + if (NULL != scale) { + scale->fX = SkDoubleToScalar(w1); + scale->fY = SkDoubleToScalar(w2); + } + if (NULL != rotation1) { + rotation1->fX = cos1; + rotation1->fY = sin1; + } + if (NULL != rotation2) { + rotation2->fX = cos2; + rotation2->fY = sin2; + } + + return true; +} diff --git a/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.cpp b/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.cpp new file mode 100644 index 000000000000..4cf99bca97cd --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.cpp @@ -0,0 +1,292 @@ +/* + * 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; + newClip->fOffset = kInvalidJumpOffset; + return false; +} + +bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord* picRecord, + int regionID, + SkRegion::Op op, + int matrixID) { + // TODO: add a region dictionary so we don't have to copy the region in here + 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; + newClip->fOffset = kInvalidJumpOffset; + 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, + bool* overrideFirstOp) { + for (int i = 0; i < fClips.count(); ++i) { + ClipOp& curClip = fClips[i]; + + SkRegion::Op op = curClip.fOp; + if (*overrideFirstOp) { + op = SkRegion::kReplace_Op; + *overrideFirstOp = false; + } + + // 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; + + switch (curClip.fClipType) { + case kRect_ClipType: + curClip.fOffset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(), + op, curClip.fDoAA); + break; + case kRRect_ClipType: + curClip.fOffset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, op, + curClip.fDoAA); + break; + case kPath_ClipType: + curClip.fOffset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, op, + curClip.fDoAA); + break; + case kRegion_ClipType: { + const SkRegion* region = mgr->lookupRegion(curClip.fGeom.fRegionID); + curClip.fOffset = mgr->getPicRecord()->recordClipRegion(*region, op); + break; + } + default: + SkASSERT(0); + } + } +} + +// Fill in the skip offsets for all the clips written in the current block +void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::fillInSkips(SkWriter32* writer, + int32_t restoreOffset) { + for (int i = 0; i < fClips.count(); ++i) { + ClipOp& curClip = fClips[i]; + + if (-1 == curClip.fOffset) { + continue; + } +// SkDEBUGCODE(uint32_t peek = writer->read32At(curClip.fOffset);) +// SkASSERT(-1 == peek); + writer->overwriteTAt(curClip.fOffset, restoreOffset); + SkDEBUGCODE(curClip.fOffset = -1;) + } +} + +SkMatrixClipStateMgr::SkMatrixClipStateMgr() + : fPicRecord(NULL) + , fMatrixClipStack(sizeof(MatrixClipState), + fMatrixClipStackStorage, + sizeof(fMatrixClipStackStorage)) + , fCurOpenStateID(kIdentityWideOpenStateID) { + + // 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() +} + +SkMatrixClipStateMgr::~SkMatrixClipStateMgr() { + for (int i = 0; i < fRegionDict.count(); ++i) { + SkDELETE(fRegionDict[i]); + } +} + + +int SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) { + SkDEBUGCODE(this->validate();) + + MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back(); + new (newTop) MatrixClipState(fCurMCState, flags); // balanced in restore() + fCurMCState = newTop; + + SkDEBUGCODE(this->validate();) + + return fMatrixClipStack.count(); +} + +int SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint, + SkCanvas::SaveFlags flags) { + int result = this->save(flags); + ++fCurMCState->fLayerID; + fCurMCState->fIsSaveLayer = true; + + fCurMCState->fSaveLayerBracketed = this->call(kOther_CallType); + fCurMCState->fSaveLayerBaseStateID = fCurOpenStateID; + fPicRecord->recordSaveLayer(bounds, paint, + (SkCanvas::SaveFlags)(flags| SkCanvas::kMatrixClip_SaveFlag)); + return result; +} + +void SkMatrixClipStateMgr::restore() { + SkDEBUGCODE(this->validate();) + + if (fCurMCState->fIsSaveLayer) { + if (fCurMCState->fSaveLayerBaseStateID != fCurOpenStateID) { + fPicRecord->recordRestore(); // Close the open block + } + // 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 + + // Close the Save that brackets the saveLayer. TODO: this doesn't handle + // the skip offsets correctly + if (fCurMCState->fSaveLayerBracketed) { + fPicRecord->recordRestore(false); + } + + // MC states can be allowed to fuse across saveLayer/restore boundaries + fCurOpenStateID = kIdentityWideOpenStateID; + } + + fCurMCState->~MatrixClipState(); // balanced in save() + fMatrixClipStack.pop_back(); + fCurMCState = (MatrixClipState*)fMatrixClipStack.back(); + + 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::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) { + fPicRecord->recordRestore(); // Close the open block + } + + // Install the required MC state as the active one + fCurOpenStateID = fCurMCState->fMCStateID; + + fPicRecord->recordSave(SkCanvas::kMatrixClip_SaveFlag); + + // write out clips + SkDeque::F2BIter iter(fMatrixClipStack); + bool firstClip = true; + + int curMatID = kIdentityMatID; + for (const MatrixClipState* state = (const MatrixClipState*) iter.next(); + state != NULL; + state = (const MatrixClipState*) iter.next()) { + state->fClipInfo->writeClip(&curMatID, this, &firstClip); + } + + // write out matrix + 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; +} + +void SkMatrixClipStateMgr::finish() { + if (kIdentityWideOpenStateID != fCurOpenStateID) { + fPicRecord->recordRestore(); // Close the open block + fCurOpenStateID = kIdentityWideOpenStateID; + } +} + +#ifdef SK_DEBUG +void SkMatrixClipStateMgr::validate() { + if (fCurOpenStateID == fCurMCState->fMCStateID) { + // The current state is the active one so all its skip offsets should + // still be -1 + SkDeque::F2BIter iter(fMatrixClipStack); + + for (const MatrixClipState* state = (const MatrixClipState*) iter.next(); + state != NULL; + state = (const MatrixClipState*) iter.next()) { + state->fClipInfo->checkOffsetNotEqual(-1); + } + } +} +#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/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.h b/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.h new file mode 100644 index 000000000000..60f9fa001679 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMatrixClipStateMgr.h @@ -0,0 +1,403 @@ +/* + * 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 { + public: + class MatrixInfo { + public: + void reset() { + fMatrixID = kIdentityMatID; + fMatrix.reset(); + } + + bool preTranslate(SkScalar dx, SkScalar dy) { + fMatrixID = -1; + return fMatrix.preTranslate(dx, dy); + } + + bool preScale(SkScalar sx, SkScalar sy) { + fMatrixID = -1; + return fMatrix.preScale(sx, sy); + } + + bool preRotate(SkScalar degrees) { + fMatrixID = -1; + return fMatrix.preRotate(degrees); + } + + bool preSkew(SkScalar sx, SkScalar sy) { + fMatrixID = -1; + return fMatrix.preSkew(sx, sy); + } + + bool preConcat(const SkMatrix& matrix) { + fMatrixID = -1; + return 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; + }; + + class ClipInfo : public 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; + newClip->fOffset = kInvalidJumpOffset; + 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; + newClip->fOffset = kInvalidJumpOffset; + 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, + bool* overrideFirstOp); + void fillInSkips(SkWriter32* writer, int32_t restoreOffset); + +#ifdef SK_DEBUG + void checkOffsetNotEqual(int32_t offset) { + for (int i = 0; i < fClips.count(); ++i) { + ClipOp& curClip = fClips[i]; + SkASSERT(offset != curClip.fOffset); + } + } +#endif + private: + enum ClipType { + kRect_ClipType, + kRRect_ClipType, + kPath_ClipType, + kRegion_ClipType + }; + + static const int kInvalidJumpOffset = -1; + + class ClipOp { + public: + ClipType fClipType; + + union { + SkRRect fRRect; // also stores clipRect + int fPathID; + int fRegionID; + } fGeom; + + bool fDoAA; + SkRegion::Op fOp; + + // The CTM in effect when this clip call was issued + int fMatrixID; + + // The offset of this clipOp's "jump-to-offset" location in the skp. + // -1 means the offset hasn't been written. + int32_t fOffset; + }; + + SkTDArray fClips; + + typedef SkNoncopyable INHERITED; + }; + + MatrixClipState(MatrixClipState* prev, int flags) +#ifdef SK_DEBUG + : fPrev(prev) +#endif + { + 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; + } + 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; + } + + 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 two fields are only valid when fIsSaveLayer is set. + int32_t fSaveLayerBaseStateID; + bool fSaveLayerBracketed; + +#ifdef SK_DEBUG + MatrixClipState* fPrev; // 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(); + + bool translate(SkScalar dx, SkScalar dy) { + this->call(kMatrix_CallType); + return fCurMCState->fMatrixInfo->preTranslate(dx, dy); + } + + bool scale(SkScalar sx, SkScalar sy) { + this->call(kMatrix_CallType); + return fCurMCState->fMatrixInfo->preScale(sx, sy); + } + + bool rotate(SkScalar degrees) { + this->call(kMatrix_CallType); + return fCurMCState->fMatrixInfo->preRotate(degrees); + } + + bool skew(SkScalar sx, SkScalar sy) { + this->call(kMatrix_CallType); + return fCurMCState->fMatrixInfo->preSkew(sx, sy); + } + + bool concat(const SkMatrix& matrix) { + this->call(kMatrix_CallType); + return 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) { + // Since we write out the entire clip stack at each block start we + // need to update the skips for the entire stack each time too. + SkDeque::F2BIter iter(fMatrixClipStack); + + for (const MatrixClipState* state = (const MatrixClipState*) iter.next(); + state != NULL; + state = (const MatrixClipState*) iter.next()) { + state->fClipInfo->fillInSkips(writer, 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 fMatrixDict; + + SkTDArray fRegionDict; + + // The MCStateID of the state currently in effect in the byte stream. 0 if none. + int32_t fCurOpenStateID; + + SkDEBUGCODE(void validate();) + + 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]; + } +}; + +#endif diff --git a/gfx/skia/src/core/SkMatrixUtils.h b/gfx/skia/trunk/src/core/SkMatrixUtils.h similarity index 72% rename from gfx/skia/src/core/SkMatrixUtils.h rename to gfx/skia/trunk/src/core/SkMatrixUtils.h index 2074267b7df4..d1b6658d073b 100644 --- a/gfx/skia/src/core/SkMatrixUtils.h +++ b/gfx/skia/trunk/src/core/SkMatrixUtils.h @@ -40,4 +40,15 @@ static inline bool SkTreatAsSpriteFilter(const SkMatrix& matrix, return SkTreatAsSprite(matrix, width, height, kSkSubPixelBitsForBilerp); } +/** Decomposes the upper-left 2x2 of the matrix into a rotation (represented by + the cosine and sine of the rotation angle), followed by a non-uniform scale, + followed by another rotation. If there is a reflection, one of the scale + factors will be negative. + Returns true if successful. Returns false if the matrix is degenerate. + */ +bool SkDecomposeUpper2x2(const SkMatrix& matrix, + SkPoint* rotation1, + SkPoint* scale, + SkPoint* rotation2); + #endif diff --git a/gfx/skia/trunk/src/core/SkMessageBus.h b/gfx/skia/trunk/src/core/SkMessageBus.h new file mode 100644 index 000000000000..ddeac57ac12d --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMessageBus.h @@ -0,0 +1,116 @@ +/* + * 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 SkMessageBus_DEFINED +#define SkMessageBus_DEFINED + +#include "SkOnce.h" +#include "SkTDArray.h" +#include "SkThread.h" +#include "SkTypes.h" + +template +class SkMessageBus : SkNoncopyable { +public: + // Post a message to be received by all Inboxes for this Message type. Threadsafe. + static void Post(const Message& m); + + class Inbox { + public: + Inbox(); + ~Inbox(); + + // Overwrite out with all the messages we've received since the last call. Threadsafe. + void poll(SkTDArray* out); + + private: + SkTDArray fMessages; + SkMutex fMessagesMutex; + + friend class SkMessageBus; + void receive(const Message& m); // SkMessageBus is a friend only to call this. + }; + +private: + SkMessageBus(); + static SkMessageBus* Get(); + static void New(SkMessageBus**); + + SkTDArray 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* SkMessageBus::Get() { \ + static SkMessageBus* bus = NULL; \ + SK_DECLARE_STATIC_ONCE(once); \ + SkOnce(&once, &New, &bus); \ + SkASSERT(bus != NULL); \ + return bus; \ + } + +// ----------------------- Implementation of SkMessageBus::Inbox ----------------------- + +template +SkMessageBus::Inbox::Inbox() { + // Register ourselves with the corresponding message bus. + SkMessageBus* bus = SkMessageBus::Get(); + SkAutoMutexAcquire lock(bus->fInboxesMutex); + bus->fInboxes.push(this); +} + +template +SkMessageBus::Inbox::~Inbox() { + // Remove ourselves from the corresponding message bus. + SkMessageBus* bus = SkMessageBus::Get(); + SkAutoMutexAcquire lock(bus->fInboxesMutex); + // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter. + for (int i = 0; i < bus->fInboxes.count(); i++) { + if (this == bus->fInboxes[i]) { + bus->fInboxes.removeShuffle(i); + break; + } + } +} + +template +void SkMessageBus::Inbox::receive(const Message& m) { + SkAutoMutexAcquire lock(fMessagesMutex); + fMessages.push(m); +} + +template +void SkMessageBus::Inbox::poll(SkTDArray* messages) { + SkASSERT(NULL != messages); + messages->reset(); + SkAutoMutexAcquire lock(fMessagesMutex); + messages->swap(fMessages); +} + +// ----------------------- Implementation of SkMessageBus ----------------------- + +template +SkMessageBus::SkMessageBus() {} + +template +/*static*/ void SkMessageBus::New(SkMessageBus** bus) { + *bus = new SkMessageBus(); +} + +template +/*static*/ void SkMessageBus::Post(const Message& m) { + SkMessageBus* bus = SkMessageBus::Get(); + SkAutoMutexAcquire lock(bus->fInboxesMutex); + for (int i = 0; i < bus->fInboxes.count(); i++) { + bus->fInboxes[i]->receive(m); + } +} + +#endif // SkMessageBus_DEFINED diff --git a/gfx/skia/src/core/SkMetaData.cpp b/gfx/skia/trunk/src/core/SkMetaData.cpp similarity index 97% rename from gfx/skia/src/core/SkMetaData.cpp rename to gfx/skia/trunk/src/core/SkMetaData.cpp index 5a494b3511f5..dfc2a949018a 100644 --- a/gfx/skia/src/core/SkMetaData.cpp +++ b/gfx/skia/trunk/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/gfx/skia/trunk/src/core/SkMipMap.cpp b/gfx/skia/trunk/src/core/SkMipMap.cpp new file mode 100644 index 000000000000..ff62f4d59d53 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMipMap.cpp @@ -0,0 +1,256 @@ +/* + * 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 "SkMipMap.h" +#include "SkBitmap.h" +#include "SkColorPriv.h" + +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); +} + +SkMipMap::Level* SkMipMap::AllocLevels(int levelCount, size_t pixelSize) { + if (levelCount < 0) { + return NULL; + } + int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; + if (!sk_64_isS32(size)) { + return NULL; + } + 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: + proc = downsampleby2_proc32; + break; + case SkBitmap::kRGB_565_Config: + proc = downsampleby2_proc16; + break; + case SkBitmap::kARGB_4444_Config: + proc = downsampleby2_proc4444; + break; + case SkBitmap::kIndex8_Config: + case SkBitmap::kA8_Config: + default: + return NULL; // don't build mipmaps for these configs + } + + SkAutoLockPixels alp(src); + if (!src.readyToDraw()) { + return NULL; + } + + // whip through our loop to compute the exact size needed + size_t size = 0; + int countLevels = 0; + { + int width = src.width(); + int height = src.height(); + for (;;) { + width >>= 1; + height >>= 1; + if (0 == width || 0 == height) { + break; + } + size += SkBitmap::ComputeRowBytes(config, width) * height; + countLevels += 1; + } + } + if (0 == countLevels) { + return NULL; + } + + Level* levels = SkMipMap::AllocLevels(countLevels, size); + if (NULL == levels) { + return NULL; + } + + uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; + uint8_t* addr = baseAddr; + int width = src.width(); + int height = src.height(); + uint32_t rowBytes; + SkBitmap srcBM(src); + + for (int i = 0; i < countLevels; ++i) { + width >>= 1; + height >>= 1; + rowBytes = SkToU32(SkBitmap::ComputeRowBytes(config, width)); + + levels[i].fPixels = addr; + levels[i].fWidth = width; + levels[i].fHeight = height; + levels[i].fRowBytes = rowBytes; + levels[i].fScale = (float)width / src.width(); + + SkBitmap dstBM; + 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 == baseAddr + size); + + return SkNEW_ARGS(SkMipMap, (levels, countLevels, size)); +} + +/////////////////////////////////////////////////////////////////////////////// + +//static int gCounter; + +SkMipMap::SkMipMap(Level* levels, int count, size_t size) + : fSize(size), fLevels(levels), fCount(count) { + SkASSERT(levels); + SkASSERT(count > 0); +// SkDebugf("mips %d\n", ++gCounter); +} + +SkMipMap::~SkMipMap() { + sk_free(fLevels); +// SkDebugf("mips %d\n", --gCounter); +} + +static SkFixed compute_level(SkScalar scale) { + SkFixed s = SkAbs32(SkScalarToFixed(SkScalarInvert(scale))); + + if (s < SK_Fixed1) { + return 0; + } + int clz = SkCLZ(s); + SkASSERT(clz >= 1 && clz <= 15); + return SkIntToFixed(15 - clz) + ((unsigned)(s << (clz + 1)) >> 16); +} + +bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const { + if (scale >= SK_Scalar1) { + return false; + } + + int level = compute_level(scale) >> 16; + SkASSERT(level >= 0); + if (level <= 0) { + return false; + } + + if (level > fCount) { + level = fCount; + } + if (levelPtr) { + *levelPtr = fLevels[level - 1]; + } + return true; +} diff --git a/gfx/skia/trunk/src/core/SkMipMap.h b/gfx/skia/trunk/src/core/SkMipMap.h new file mode 100644 index 000000000000..ed912ba97695 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkMipMap.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 SkMipMap_DEFINED +#define SkMipMap_DEFINED + +#include "SkRefCnt.h" +#include "SkScalar.h" + +class SkBitmap; + +class SkMipMap : public SkRefCnt { +public: + static SkMipMap* Build(const SkBitmap& src); + + struct Level { + void* fPixels; + uint32_t fRowBytes; + uint32_t fWidth, fHeight; + float fScale; // < 1.0 + }; + + bool extractLevel(SkScalar scale, Level*) const; + + size_t getSize() const { return fSize; } + +private: + size_t fSize; + Level* fLevels; + int fCount; + + // we take ownership of levels, and will free it with sk_free() + SkMipMap(Level* levels, int count, size_t size); + virtual ~SkMipMap(); + + static Level* AllocLevels(int levelCount, size_t pixelSize); +}; + +#endif diff --git a/gfx/skia/trunk/src/core/SkOrderedReadBuffer.cpp b/gfx/skia/trunk/src/core/SkOrderedReadBuffer.cpp new file mode 100644 index 000000000000..31841182b9c4 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkOrderedReadBuffer.cpp @@ -0,0 +1,317 @@ + +/* + * 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 "SkBitmap.h" +#include "SkErrorInternals.h" +#include "SkOrderedReadBuffer.h" +#include "SkStream.h" +#include "SkTypeface.h" + +SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() { + fMemoryPtr = NULL; + + fBitmapStorage = NULL; + fTFArray = NULL; + fTFCount = 0; + + fFactoryTDArray = NULL; + fFactoryArray = NULL; + fFactoryCount = 0; + fBitmapDecoder = NULL; +#ifdef DEBUG_NON_DETERMINISTIC_ASSERT + fDecodedBitmapIndex = -1; +#endif // DEBUG_NON_DETERMINISTIC_ASSERT +} + +SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() { + fReader.setMemory(data, size); + fMemoryPtr = NULL; + + fBitmapStorage = NULL; + fTFArray = NULL; + fTFCount = 0; + + fFactoryTDArray = NULL; + fFactoryArray = NULL; + fFactoryCount = 0; + fBitmapDecoder = NULL; +#ifdef DEBUG_NON_DETERMINISTIC_ASSERT + fDecodedBitmapIndex = -1; +#endif // DEBUG_NON_DETERMINISTIC_ASSERT +} + +SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) { + const size_t length = stream->getLength(); + fMemoryPtr = sk_malloc_throw(length); + stream->read(fMemoryPtr, length); + fReader.setMemory(fMemoryPtr, length); + + fBitmapStorage = NULL; + fTFArray = NULL; + fTFCount = 0; + + fFactoryTDArray = NULL; + fFactoryArray = NULL; + fFactoryCount = 0; + fBitmapDecoder = NULL; +#ifdef DEBUG_NON_DETERMINISTIC_ASSERT + fDecodedBitmapIndex = -1; +#endif // DEBUG_NON_DETERMINISTIC_ASSERT +} + +SkOrderedReadBuffer::~SkOrderedReadBuffer() { + sk_free(fMemoryPtr); + SkSafeUnref(fBitmapStorage); +} + +bool SkOrderedReadBuffer::readBool() { + return fReader.readBool(); +} + +SkColor SkOrderedReadBuffer::readColor() { + return fReader.readInt(); +} + +SkFixed SkOrderedReadBuffer::readFixed() { + return fReader.readS32(); +} + +int32_t SkOrderedReadBuffer::readInt() { + return fReader.readInt(); +} + +SkScalar SkOrderedReadBuffer::readScalar() { + return fReader.readScalar(); +} + +uint32_t SkOrderedReadBuffer::readUInt() { + return fReader.readU32(); +} + +int32_t SkOrderedReadBuffer::read32() { + return fReader.readInt(); +} + +void SkOrderedReadBuffer::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) { + SkDEBUGCODE(int32_t encodingType = ) fReader.readInt(); + SkASSERT(encodingType == encoding); + *length = fReader.readInt(); + void* data = sk_malloc_throw(*length); + memcpy(data, fReader.skip(SkAlign4(*length)), *length); + return data; +} + +void SkOrderedReadBuffer::readPoint(SkPoint* point) { + point->fX = fReader.readScalar(); + point->fY = fReader.readScalar(); +} + +void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) { + fReader.readMatrix(matrix); +} + +void SkOrderedReadBuffer::readIRect(SkIRect* rect) { + memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect)); +} + +void SkOrderedReadBuffer::readRect(SkRect* rect) { + memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect)); +} + +void SkOrderedReadBuffer::readRegion(SkRegion* region) { + fReader.readRegion(region); +} + +void SkOrderedReadBuffer::readPath(SkPath* path) { + fReader.readPath(path); +} + +bool SkOrderedReadBuffer::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 + const size_t byteLength = count * elementSize; + memcpy(value, fReader.skip(SkAlign4(byteLength)), byteLength); + return true; + } + SkASSERT(false); + fReader.skip(fReader.available()); + return false; +} + +bool SkOrderedReadBuffer::readByteArray(void* value, size_t size) { + return readArray(static_cast(value), size, sizeof(unsigned char)); +} + +bool SkOrderedReadBuffer::readColorArray(SkColor* colors, size_t size) { + return readArray(colors, size, sizeof(SkColor)); +} + +bool SkOrderedReadBuffer::readIntArray(int32_t* values, size_t size) { + return readArray(values, size, sizeof(int32_t)); +} + +bool SkOrderedReadBuffer::readPointArray(SkPoint* points, size_t size) { + return readArray(points, size, sizeof(SkPoint)); +} + +bool SkOrderedReadBuffer::readScalarArray(SkScalar* values, size_t size) { + return readArray(values, size, sizeof(SkScalar)); +} + +uint32_t SkOrderedReadBuffer::getArrayCount() { + return *(uint32_t*)fReader.peek(); +} + +void SkOrderedReadBuffer::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 + // writing. + 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) + if (fBitmapStorage) { + *bitmap = *fBitmapStorage->getBitmap(index); + fBitmapStorage->releaseRef(index); + return; + } 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 " + "stored the SkBitmap in an SkBitmapHeap, but " + "SkOrderedReadBuffer has no SkBitmapHeapReader to " + "retrieve the SkBitmap."); + } + } else { + // The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap. + const size_t length = this->readUInt(); + if (length > 0) { +#ifdef DEBUG_NON_DETERMINISTIC_ASSERT + fDecodedBitmapIndex++; +#endif // DEBUG_NON_DETERMINISTIC_ASSERT + // 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(); + 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," + " 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", + fDecodedBitmapIndex, width, height, length, xOffset, + yOffset); + } +#endif // DEBUG_NON_DETERMINISTIC_ASSERT + // If the width and height match, there should be no offset. + SkASSERT(0 == xOffset && 0 == yOffset); + return; + } + + // This case can only be reached if extractSubset was called, so + // the recorded width and height must be smaller than (or equal to + // the encoded width and height. + 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; + } + } + // This bitmap was encoded when written, but we are unable to decode, possibly due to + // not having a decoder. + SkErrorInternals::SetError(kParseError_SkError, + "Could not decode bitmap. Resulting bitmap will be red."); + } else { + // A size of zero means the SkBitmap was simply flattened. + bitmap->unflatten(*this); + return; + } + } + // Could not read the SkBitmap. Use a placeholder bitmap. + bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); + bitmap->allocPixels(); + bitmap->eraseColor(SK_ColorRED); +} + +SkTypeface* SkOrderedReadBuffer::readTypeface() { + + uint32_t index = fReader.readU32(); + if (0 == index || index > (unsigned)fTFCount) { + if (index) { + SkDebugf("====== typeface index %d\n", index); + } + return NULL; + } else { + SkASSERT(fTFArray); + return fTFArray[index - 1]; + } +} + +SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) { + // + // TODO: confirm that ft matches the factory we decide to use + // + + SkFlattenable::Factory factory = NULL; + + if (fFactoryCount > 0) { + int32_t index = fReader.readU32(); + if (0 == index) { + return NULL; // writer failed to give us the flattenable + } + index -= 1; // we stored the index-base-1 + SkASSERT(index < fFactoryCount); + factory = fFactoryArray[index]; + } else if (fFactoryTDArray) { + int32_t index = fReader.readU32(); + if (0 == index) { + return NULL; // writer failed to give us the flattenable + } + index -= 1; // we stored the index-base-1 + factory = (*fFactoryTDArray)[index]; + } else { + factory = (SkFlattenable::Factory)readFunctionPtr(); + if (NULL == factory) { + return NULL; // writer failed to give us the flattenable + } + } + + // if we get here, factory may still be null, but if that is the case, the + // failure was ours, not the writer. + SkFlattenable* obj = NULL; + uint32_t sizeRecorded = fReader.readU32(); + if (factory) { + uint32_t offset = fReader.offset(); + obj = (*factory)(*this); + // check that we read the amount we expected + uint32_t sizeRead = fReader.offset() - offset; + if (sizeRecorded != sizeRead) { + // we could try to fix up the offset... + sk_throw(); + } + } else { + // we must skip the remaining data + fReader.skip(sizeRecorded); + } + return obj; +} diff --git a/gfx/skia/trunk/src/core/SkOrderedReadBuffer.h b/gfx/skia/trunk/src/core/SkOrderedReadBuffer.h new file mode 100644 index 000000000000..3286f6b9df12 --- /dev/null +++ b/gfx/skia/trunk/src/core/SkOrderedReadBuffer.h @@ -0,0 +1,9 @@ +// Temporary shim to keep a couple dependencies working in Chromium. +#ifndef SkOrderedReadBuffer_DEFINED +#define SkOrderedReadBuffer_DEFINED + +#include "SkReadBuffer.h" + +typedef SkReadBuffer SkOrderedReadBuffer; + +#endif//SkOrderedReadBuffer_DEFINED diff --git a/gfx/skia/src/core/SkOrderedWriteBuffer.cpp b/gfx/skia/trunk/src/core/SkOrderedWriteBuffer.cpp similarity index 75% rename from gfx/skia/src/core/SkOrderedWriteBuffer.cpp rename to gfx/skia/trunk/src/core/SkOrderedWriteBuffer.cpp index e458bfe59759..25ca769168da 100644 --- a/gfx/skia/src/core/SkOrderedWriteBuffer.cpp +++ b/gfx/skia/trunk/src/core/SkOrderedWriteBuffer.cpp @@ -9,7 +9,6 @@ #include "SkOrderedWriteBuffer.h" #include "SkBitmap.h" #include "SkData.h" -#include "SkPixelRef.h" #include "SkPtrRecorder.h" #include "SkStream.h" #include "SkTypeface.h" @@ -144,21 +143,31 @@ bool SkOrderedWriteBuffer::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); + void SkOrderedWriteBuffer::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()); + this->writeInt(bitmap.height()); + // Record information about the bitmap in one of three ways, in order of priority: // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the - // bitmap entirely or serialize it later as desired. - // 2. Write an encoded version of the bitmap. Afterwards the width and height are written, so - // a reader without a decoder can draw a dummy bitmap of the right size. - // A. If the bitmap has an encoded representation, write it to the stream. - // B. If there is a function for encoding bitmaps, use it. - // 3. Call SkBitmap::flatten. - // For an encoded bitmap, write the size first. Otherwise store a 0 so the reader knows not to - // decode. - if (fBitmapHeap != NULL) { + // bitmap entirely or serialize it later as desired. A boolean value of true will be written + // to the stream to signify that a heap was used. + // 2. If there is a function for encoding bitmaps, use it to write an encoded version of the + // bitmap. After writing a boolean value of false, signifying that a heap was not used, write + // the size of the encoded data. A non-zero size signifies that encoded data was written. + // 3. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was + // not used, write a zero to signify that the data was not encoded. + bool useBitmapHeap = fBitmapHeap != NULL; + // Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an + // SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way. + this->writeBool(useBitmapHeap); + if (useBitmapHeap) { SkASSERT(NULL == fBitmapEncoder); - // Bitmap was not encoded. Record a zero, implying that the reader need not decode. - this->writeUInt(0); int32_t slot = fBitmapHeap->insert(bitmap); fWriter.write32(slot); // crbug.com/155875 @@ -170,48 +179,30 @@ void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) { fWriter.write32(bitmap.getGenerationID()); return; } - bool encoded = false; - // Before attempting to encode the SkBitmap, check to see if there is already an encoded - // version. - SkPixelRef* ref = bitmap.pixelRef(); - if (ref != NULL) { - SkAutoDataUnref data(ref->refEncodedData()); + if (fBitmapEncoder != NULL) { + SkASSERT(NULL == fBitmapHeap); + size_t offset = 0; + 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 must match the case where fBitmapEncoder is used so the - // reader need not know the difference. - this->writeUInt(data->size()); + // by the actual data. + this->writeUInt(SkToU32(data->size())); fWriter.writePad(data->data(), data->size()); - encoded = true; - } - } - if (fBitmapEncoder != NULL && !encoded) { - SkASSERT(NULL == fBitmapHeap); - SkDynamicMemoryWStream stream; - if (fBitmapEncoder(&stream, bitmap)) { - uint32_t offset = fWriter.bytesWritten(); - // Write the length to indicate that the bitmap was encoded successfully, followed - // by the actual data. This must match the case where the original data is used so the - // reader need not know the difference. - size_t length = stream.getOffset(); - this->writeUInt(length); - if (stream.read(fWriter.reservePad(length), 0, length)) { - encoded = true; - } else { - // Writing the stream failed, so go back to original state to store another way. - fWriter.rewindToOffset(offset); + // 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); + return; } } - if (encoded) { - // Write the width and height in case the reader does not have a decoder. - this->writeInt(bitmap.width()); - this->writeInt(bitmap.height()); - } else { - // Bitmap was not encoded. Record a zero, implying that the reader need not decode. - this->writeUInt(0); - bitmap.flatten(*this); - } + // Bitmap was not encoded. Record a zero, implying that the reader need not decode. + this->writeUInt(0); + bitmap.flatten(*this); } void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) { @@ -262,7 +253,7 @@ void SkOrderedWriteBuffer::setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncode } } -void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { +void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { /* * If we have a factoryset, then the first 32bits tell us... * 0: failure to write the flattenable @@ -279,7 +270,10 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { factory = flattenable->getFactory(); } if (NULL == factory) { - if (fFactorySet != NULL || fNamedFactorySet != NULL) { + 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 { this->writeFunctionPtr(NULL); @@ -299,7 +293,9 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { * name. SkGPipe uses this technique so it can write the name to its * stream before writing the flattenable. */ - if (fFactorySet) { + if (this->isValidating()) { + this->writeString(flattenable->getTypeName()); + } else if (fFactorySet) { this->write32(fFactorySet->add(factory)); } else if (fNamedFactorySet) { int32_t index = fNamedFactorySet->find(factory); @@ -314,10 +310,10 @@ void SkOrderedWriteBuffer::writeFlattenable(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.size(); + uint32_t offset = fWriter.bytesWritten(); // now flatten the object flattenObject(flattenable, *this); - uint32_t objSize = fWriter.size() - offset; + uint32_t objSize = fWriter.bytesWritten() - offset; // record the obj's size *fWriter.peek32(offset - sizeof(uint32_t)) = objSize; } diff --git a/gfx/skia/src/core/SkOrderedWriteBuffer.h b/gfx/skia/trunk/src/core/SkOrderedWriteBuffer.h similarity index 80% rename from gfx/skia/src/core/SkOrderedWriteBuffer.h rename to gfx/skia/trunk/src/core/SkOrderedWriteBuffer.h index 17040b84b1c6..f3b414e104a4 100644 --- a/gfx/skia/src/core/SkOrderedWriteBuffer.h +++ b/gfx/skia/trunk/src/core/SkOrderedWriteBuffer.h @@ -26,18 +26,25 @@ class SkRefCntSet; class SkOrderedWriteBuffer : public SkFlattenableWriteBuffer { public: SkOrderedWriteBuffer(size_t minSize); - SkOrderedWriteBuffer(size_t minSize, void* initialStorage, - size_t storageSize); + 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); } - uint32_t size() { return fWriter.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; @@ -52,7 +59,7 @@ public: virtual void writeEncodedString(const void* value, size_t byteLength, SkPaint::TextEncoding encoding) SK_OVERRIDE; - virtual void writeFlattenable(SkFlattenable* flattenable) 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; @@ -84,14 +91,15 @@ public: void setBitmapHeap(SkBitmapHeap*); /** - * Provide a function to encode an SkBitmap to an SkStream. writeBitmap will attempt to use + * 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); + void setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncoder); private: SkFactorySet* fFactorySet; diff --git a/gfx/skia/src/core/SkPackBits.cpp b/gfx/skia/trunk/src/core/SkPackBits.cpp similarity index 100% rename from gfx/skia/src/core/SkPackBits.cpp rename to gfx/skia/trunk/src/core/SkPackBits.cpp diff --git a/gfx/skia/src/core/SkPaint.cpp b/gfx/skia/trunk/src/core/SkPaint.cpp similarity index 86% rename from gfx/skia/src/core/SkPaint.cpp rename to gfx/skia/trunk/src/core/SkPaint.cpp index aa1b8e4803b9..c3f217cefc60 100644 --- a/gfx/skia/src/core/SkPaint.cpp +++ b/gfx/skia/trunk/src/core/SkPaint.cpp @@ -18,9 +18,10 @@ #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" #include "SkRasterizer.h" #include "SkScalar.h" @@ -30,6 +31,7 @@ #include "SkStroke.h" #include "SkTextFormatParams.h" #include "SkTextToPathIter.h" +#include "SkTLazy.h" #include "SkTypeface.h" #include "SkXfermode.h" @@ -69,9 +71,6 @@ SkPaint::SkPaint() { fTextSize = SkPaintDefaults_TextSize; fTextScaleX = SK_Scalar1; -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - fHintingScaleFactor = SK_Scalar1; -#endif fColor = SK_ColorBLACK; fMiterLimit = SkPaintDefaults_MiterLimit; fFlags = SkPaintDefaults_Flags; @@ -81,8 +80,8 @@ SkPaint::SkPaint() { fStyle = kFill_Style; fTextEncoding = kUTF8_TextEncoding; fHinting = SkPaintDefaults_Hinting; - fPrivFlags = 0; #ifdef SK_BUILD_FOR_ANDROID + new (&fPaintOptionsAndroid) SkPaintOptionsAndroid; fGenerationID = 0; #endif } @@ -100,6 +99,10 @@ SkPaint::SkPaint(const SkPaint& src) { SkSafeRef(fLooper); SkSafeRef(fImageFilter); SkSafeRef(fAnnotation); + +#ifdef SK_BUILD_FOR_ANDROID + new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid); +#endif } SkPaint::~SkPaint() { @@ -141,11 +144,15 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { SkSafeUnref(fAnnotation); #ifdef SK_BUILD_FOR_ANDROID + fPaintOptionsAndroid.~SkPaintOptionsAndroid(); + uint32_t oldGenerationID = fGenerationID; #endif memcpy(this, &src, sizeof(src)); #ifdef SK_BUILD_FOR_ANDROID fGenerationID = oldGenerationID + 1; + + new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid); #endif return *this; @@ -180,16 +187,44 @@ uint32_t SkPaint::getGenerationID() const { void SkPaint::setGenerationID(uint32_t generationID) { fGenerationID = generationID; } -#endif -#ifdef SK_BUILD_FOR_ANDROID unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const { SkAutoGlyphCache autoCache(*this, NULL, NULL); SkGlyphCache* cache = autoCache.getCache(); return cache->getBaseGlyphCount(text); } + +void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) { + if (options != fPaintOptionsAndroid) { + fPaintOptionsAndroid = options; + GEN_ID_INC; + } +} #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); +} + void SkPaint::setHinting(Hinting hintingLevel) { GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting); fHinting = hintingLevel; @@ -248,10 +283,6 @@ void SkPaint::setDevKernText(bool doDevKern) { this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); } -void SkPaint::setFilterBitmap(bool doFilter) { - this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); -} - void SkPaint::setStyle(Style style) { if ((unsigned)style < kStyleCount) { GEN_ID_INC_EVAL((unsigned)style != fStyle); @@ -355,13 +386,6 @@ void SkPaint::setTextSkewX(SkScalar skewX) { fTextSkewX = skewX; } -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR -void SkPaint::setHintingScaleFactor(SkScalar hintingScaleFactor) { - GEN_ID_INC_EVAL(hintingScaleFactor != fHintingScaleFactor); - fHintingScaleFactor = hintingScaleFactor; -} -#endif - void SkPaint::setTextEncoding(TextEncoding encoding) { if ((unsigned)encoding <= kGlyphID_TextEncoding) { GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding); @@ -402,15 +426,42 @@ SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) { SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) { SkRefCnt_SafeAssign(fAnnotation, annotation); GEN_ID_INC; - - bool isNoDraw = annotation && annotation->isNoDraw(); - fPrivFlags = SkSetClearMask(fPrivFlags, isNoDraw, kNoDrawAnnotation_PrivFlag); - return annotation; } /////////////////////////////////////////////////////////////////////////////// +static SkScalar mag2(SkScalar x, SkScalar y) { + return x * x + y * y; +} + +static bool tooBig(const SkMatrix& m, SkScalar ma2max) { + return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max + || + mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max; +} + +bool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) { + SkASSERT(!ctm.hasPerspective()); + SkASSERT(!textM.hasPerspective()); + + SkMatrix matrix; + matrix.setConcat(ctm, textM); + return tooBig(matrix, MaxCacheSize2()); +} + +bool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const { + SkMatrix textM; + return TooBigToUseCache(ctm, *this->setTextMatrix(&textM)); +} + +bool SkPaint::tooBigToUseCache() const { + SkMatrix textM; + return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2()); +} + +/////////////////////////////////////////////////////////////////////////////// + #include "SkGlyphCache.h" #include "SkUtils.h" @@ -901,33 +952,51 @@ SkDrawCacheProc SkPaint::getDrawCacheProc() const { /////////////////////////////////////////////////////////////////////////////// -class SkAutoRestorePaintTextSizeAndFrame { +#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE ( \ +SkPaint::kDevKernText_Flag | \ +SkPaint::kLinearText_Flag | \ +SkPaint::kLCDRenderText_Flag | \ +SkPaint::kEmbeddedBitmapText_Flag | \ +SkPaint::kAutoHinting_Flag | \ +SkPaint::kGenA8FromLCD_Flag ) + +SkScalar SkPaint::setupForAsPaths() { + uint32_t flags = this->getFlags(); + // clear the flags we don't care about + flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE; + // set the flags we do care about + flags |= SkPaint::kSubpixelText_Flag; + + this->setFlags(flags); + this->setHinting(SkPaint::kNo_Hinting); + + SkScalar textSize = fTextSize; + this->setTextSize(kCanonicalTextSizeForPaths); + return textSize / kCanonicalTextSizeForPaths; +} + +class SkCanonicalizePaint { public: - SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) - : fPaint((SkPaint*)paint) { - fTextSize = paint->getTextSize(); - fStyle = paint->getStyle(); - fPaint->setStyle(SkPaint::kFill_Style); -#ifdef SK_BUILD_FOR_ANDROID - fGenerationID = fPaint->getGenerationID(); -#endif + SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) { + if (paint.isLinearText() || paint.tooBigToUseCache()) { + SkPaint* p = fLazy.set(paint); + fScale = p->setupForAsPaths(); + fPaint = p; + } } - ~SkAutoRestorePaintTextSizeAndFrame() { - fPaint->setStyle(fStyle); - fPaint->setTextSize(fTextSize); -#ifdef SK_BUILD_FOR_ANDROID - fPaint->setGenerationID(fGenerationID); -#endif - } + const SkPaint& getPaint() const { return *fPaint; } + + /** + * Returns 0 if the paint was unmodified, or the scale factor need to + * the original textSize + */ + SkScalar getScale() const { return fScale; } private: - SkPaint* fPaint; - SkScalar fTextSize; - SkPaint::Style fStyle; -#ifdef SK_BUILD_FOR_ANDROID - uint32_t fGenerationID; -#endif + const SkPaint* fPaint; + SkScalar fScale; + SkTLazy fLazy; }; static void set_bounds(const SkGlyph& g, SkRect* bounds) { @@ -941,16 +1010,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(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); @@ -1055,14 +1117,9 @@ SkScalar SkPaint::measureText(const void* textData, size_t length, const char* text = (const char*)textData; SkASSERT(text != NULL || length == 0); - SkScalar scale = 0; - SkAutoRestorePaintTextSizeAndFrame restore(this); - - if (this->isLinearText()) { - scale = fTextSize / kCanonicalTextSizeForPaths; - // this gets restored by restore - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); - } + SkCanonicalizePaint canon(*this); + const SkPaint& paint = canon.getPaint(); + SkScalar scale = canon.getScale(); SkMatrix zoomMatrix, *zoomPtr = NULL; if (zoom) { @@ -1070,7 +1127,7 @@ SkScalar SkPaint::measureText(const void* textData, size_t length, zoomPtr = &zoomMatrix; } - SkAutoGlyphCache autoCache(*this, NULL, zoomPtr); + SkAutoGlyphCache autoCache(paint, NULL, zoomPtr); SkGlyphCache* cache = autoCache.getCache(); SkScalar width = 0; @@ -1078,7 +1135,7 @@ SkScalar SkPaint::measureText(const void* textData, size_t length, if (length > 0) { int tempCount; - width = this->measure_text(cache, text, length, &tempCount, bounds); + width = paint.measure_text(cache, text, length, &tempCount, bounds); if (scale) { width = SkScalarMul(width, scale); if (bounds) { @@ -1139,23 +1196,22 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, SkASSERT(textD != NULL); const char* text = (const char*)textD; - SkScalar scale = 0; - SkAutoRestorePaintTextSizeAndFrame restore(this); + SkCanonicalizePaint canon(*this); + const SkPaint& paint = canon.getPaint(); + SkScalar scale = canon.getScale(); - if (this->isLinearText()) { - scale = fTextSize / kCanonicalTextSizeForPaths; - maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize); - // this gets restored by restore - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); + // adjust max in case we changed the textSize in paint + if (scale) { + maxWidth /= scale; } - SkAutoGlyphCache autoCache(*this, NULL, NULL); + SkAutoGlyphCache autoCache(paint, NULL, NULL); SkGlyphCache* cache = autoCache.getCache(); - SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false); + SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false); const char* stop; SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop); - const int xyIndex = this->isVerticalText() ? 1 : 0; + const int xyIndex = paint.isVerticalText() ? 1 : 0; // use 64bits for our accumulator, to avoid overflowing 16.16 Sk48Dot16 max = SkScalarToFixed(maxWidth); Sk48Dot16 width = 0; @@ -1203,7 +1259,7 @@ size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth, /////////////////////////////////////////////////////////////////////////////// static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) { - *(SkPaint::FontMetrics*)context = cache->getFontMetricsY(); + *(SkPaint::FontMetrics*)context = cache->getFontMetrics(); return false; // don't detach the cache } @@ -1213,14 +1269,9 @@ static void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc, } SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { - SkScalar scale = 0; - SkAutoRestorePaintTextSizeAndFrame restore(this); - - if (this->isLinearText()) { - scale = fTextSize / kCanonicalTextSizeForPaths; - // this gets restored by restore - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); - } + SkCanonicalizePaint canon(*this); + const SkPaint& paint = canon.getPaint(); + SkScalar scale = canon.getScale(); SkMatrix zoomMatrix, *zoomPtr = NULL; if (zoom) { @@ -1228,17 +1279,12 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { zoomPtr = &zoomMatrix; } -#if 0 - SkAutoGlyphCache autoCache(*this, zoomPtr); - SkGlyphCache* cache = autoCache.getCache(); - const FontMetrics& my = cache->getFontMetricsY(); -#endif FontMetrics storage; if (NULL == metrics) { metrics = &storage; } - this->descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true); + paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true); if (scale) { metrics->fTop = SkScalarMul(metrics->fTop, scale); @@ -1246,6 +1292,10 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const { metrics->fDescent = SkScalarMul(metrics->fDescent, scale); metrics->fBottom = SkScalarMul(metrics->fBottom, scale); metrics->fLeading = SkScalarMul(metrics->fLeading, scale); + metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale); + metrics->fXMin = SkScalarMul(metrics->fXMin, scale); + metrics->fXMax = SkScalarMul(metrics->fXMax, scale); + metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale); } return metrics->fDescent - metrics->fAscent + metrics->fLeading; } @@ -1271,25 +1321,20 @@ int SkPaint::getTextWidths(const void* textData, size_t byteLength, return this->countText(textData, byteLength); } - SkAutoRestorePaintTextSizeAndFrame restore(this); - SkScalar scale = 0; + SkCanonicalizePaint canon(*this); + const SkPaint& paint = canon.getPaint(); + SkScalar scale = canon.getScale(); - if (this->isLinearText()) { - scale = fTextSize / kCanonicalTextSizeForPaths; - // this gets restored by restore - ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths)); - } - - SkAutoGlyphCache autoCache(*this, NULL, NULL); + SkAutoGlyphCache autoCache(paint, NULL, NULL); SkGlyphCache* cache = autoCache.getCache(); SkMeasureCacheProc glyphCacheProc; - glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection, + glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection, NULL != bounds); const char* text = (const char*)textData; const char* stop = text + byteLength; int count = 0; - const int xyIndex = this->isVerticalText() ? 1 : 0; + const int xyIndex = paint.isVerticalText() ? 1 : 0; if (this->isDevKernText()) { // we adjust the widths returned here through auto-kerning @@ -1429,8 +1474,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() @@ -1504,13 +1549,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, @@ -1528,9 +1568,6 @@ void SkScalerContext::MakeRec(const SkPaint& paint, rec->fTextSize = paint.getTextSize(); rec->fPreScaleX = paint.getTextScaleX(); rec->fPreSkewX = paint.getTextSkewX(); -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - rec->fHintingScaleFactor = paint.getHintingScaleFactor(); -#endif if (deviceMatrix) { rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX()); @@ -1610,7 +1647,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; @@ -1647,7 +1684,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint, * With higher values lcd fringing is worse and the smoothing effect of * partial coverage is diminished. */ - rec->setContrast(SkFloatToScalar(0.5f)); + rec->setContrast(0.5f); #endif rec->fReservedAlign = 0; @@ -1778,20 +1815,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. @@ -1802,11 +1837,18 @@ 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 + SkWriteBuffer androidBuffer; + fPaintOptionsAndroid.flatten(androidBuffer); + descSize += androidBuffer.bytesWritten(); + entryCount += 1; +#endif + /////////////////////////////////////////////////////////////////////////// // Now that we're done tweaking the rec, call the PostMakeRec cleanup SkScalerContext::PostMakeRec(*this, &rec); @@ -1819,6 +1861,10 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, desc->init(); desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); +#ifdef SK_BUILD_FOR_ANDROID + add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer); +#endif + if (pe) { add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); } @@ -1853,6 +1899,11 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); +#ifdef SK_BUILD_FOR_ANDROID + add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer); + add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer); +#endif + if (pe) { add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer); add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer); @@ -1934,16 +1985,13 @@ static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) { } enum FlatFlags { - kHasTypeface_FlatFlag = 0x01, - kHasEffects_FlatFlag = 0x02, + kHasTypeface_FlatFlag = 0x01, + kHasEffects_FlatFlag = 0x02, + kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04, }; // The size of a flat paint's POD fields -// Include an SkScalar for hinting scale factor whether it is -// supported or not so that an SKP is valid whether it was -// created with support or not. - -static const uint32_t kPODPaintSize = 6 * sizeof(SkScalar) + +static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) + 1 * sizeof(SkColor) + 1 * sizeof(uint16_t) + 6 * sizeof(uint8_t); @@ -1951,7 +1999,7 @@ static const uint32_t kPODPaintSize = 6 * 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; @@ -1967,56 +2015,30 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { asint(this->getImageFilter())) { flatFlags |= kHasEffects_FlatFlag; } - - - 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()); -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - ptr = write_scalar(ptr, this->getHintingScaleFactor()); -#else - // Dummy value. - ptr = write_scalar(ptr, SK_Scalar1); -#endif - 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); -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - buffer.writeScalar(fHintingScaleFactor); -#else - // Dummy value. - buffer.writeScalar(SK_Scalar1); -#endif - 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); +#ifdef SK_BUILD_FOR_ANDROID + if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) { + flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag; } +#endif + + 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(); + // 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()); // now we're done with ptr and the (pre)reserved space. If we need to write // additional fields, use the buffer directly @@ -2032,74 +2054,53 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const { buffer.writeFlattenable(this->getRasterizer()); buffer.writeFlattenable(this->getLooper()); buffer.writeFlattenable(this->getImageFilter()); - buffer.writeFlattenable(this->getAnnotation()); + + if (fAnnotation) { + buffer.writeBool(true); + fAnnotation->writeToBuffer(buffer); + } else { + buffer.writeBool(false); + } } +#ifdef SK_BUILD_FOR_ANDROID + if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) { + this->getPaintOptionsAndroid().flatten(buffer); + } +#endif } -void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { - fPrivFlags = 0; - +void SkPaint::unflatten(SkReadBuffer& 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(podData); + SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize); + const void* podData = buffer.skip(kPODPaintSize); + const uint32_t* pod = reinterpret_cast(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)); -#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR - this->setHintingScaleFactor(read_scalar(pod)); -#else - // Skip the hinting scalar factor, which is not supported. - read_scalar(pod); -#endif - this->setStrokeWidth(read_scalar(pod)); - this->setStrokeMiter(read_scalar(pod)); - this->setColor(*pod++); + // 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); + // 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-1)); + // 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-1)); - this->setTextAlign(static_cast((tmp >> 8) & 0xF)); + this->setTextAlign(static_cast((tmp >> 8) & 0xF)); - flatFlags = tmp & 0xFF; + flatFlags = tmp & 0xFF; - tmp = *pod++; - this->setStrokeCap(static_cast((tmp >> 24) & 0xFF)); - this->setStrokeJoin(static_cast((tmp >> 16) & 0xFF)); - this->setStyle(static_cast