Back out changesets from bug 910754 due to build bustage

This commit is contained in:
George Wright 2014-02-18 17:54:04 -05:00
parent 7c4ca1245a
commit 309648f662
1647 changed files with 49968 additions and 106889 deletions

View File

@ -7,8 +7,7 @@
#include "SourceSurfaceSkia.h"
#include "ScaledFontBase.h"
#include "ScaledFontCairo.h"
#include "skia/SkGpuDevice.h"
#include "skia/SkBitmapDevice.h"
#include "skia/SkDevice.h"
#include "FilterNodeSoftware.h"
#ifdef USE_SKIA_GPU
@ -748,9 +747,9 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
bool
DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
{
SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(GfxFormatToSkiaConfig(aFormat),
aSize.width, aSize.height,
aFormat == SurfaceFormat::B8G8R8X8));
SkAutoTUnref<SkDevice> device(new SkDevice(GfxFormatToSkiaConfig(aFormat),
aSize.width, aSize.height,
aFormat == SurfaceFormat::B8G8R8X8));
SkBitmap bitmap = device->accessBitmap(true);
if (!bitmap.allocPixels()) {
@ -795,7 +794,7 @@ DrawTargetSkia::InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLCont
targetDescriptor.fRenderTargetHandle = 0; // GLContext always exposes the right framebuffer as id 0
SkAutoTUnref<GrRenderTarget> target(mGrContext->wrapBackendRenderTarget(targetDescriptor));
SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), target.get()));
SkAutoTUnref<SkDevice> device(new SkGpuDevice(mGrContext.get(), target.get()));
SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
mCanvas = canvas.get();
@ -813,17 +812,18 @@ DrawTargetSkia::SetCacheLimits(int aCount, int aSizeInBytes)
void
DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
{
SkAlphaType alphaType = kPremul_SkAlphaType;
bool isOpaque = false;
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);
alphaType = kOpaque_SkAlphaType;
isOpaque = true;
}
SkBitmap bitmap;
bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride, alphaType);
bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride);
bitmap.setPixels(aData);
SkAutoTUnref<SkCanvas> canvas(new SkCanvas(new SkBitmapDevice(bitmap)));
bitmap.setIsOpaque(isOpaque);
SkAutoTUnref<SkCanvas> canvas(new SkCanvas(new SkDevice(bitmap)));
mSize = aSize;
mCanvas = canvas.get();

View File

@ -18,18 +18,19 @@ bool Scale(uint8_t* srcData, int32_t srcWidth, int32_t srcHeight, int32_t srcStr
SurfaceFormat format)
{
#ifdef USE_SKIA
SkAlphaType alphaType;
bool opaque;
if (format == SurfaceFormat::B8G8R8A8) {
alphaType = kPremul_SkAlphaType;
opaque = false;
} else {
alphaType = kOpaque_SkAlphaType;
opaque = true;
}
SkBitmap::Config config = GfxFormatToSkiaConfig(format);
SkBitmap imgSrc;
imgSrc.setConfig(config, srcWidth, srcHeight, srcStride, alphaType);
imgSrc.setConfig(config, srcWidth, srcHeight, srcStride);
imgSrc.setPixels(srcData);
imgSrc.setIsOpaque(opaque);
// Rescaler is compatible with 32 bpp only. Convert to RGB32 if needed.
if (config != SkBitmap::kARGB_8888_Config) {

View File

@ -78,7 +78,7 @@ SourceSurfaceSkia::InitFromData(unsigned char* aData,
ConvertBGRXToBGRA(reinterpret_cast<unsigned char*>(mBitmap.getPixels()), aSize, mBitmap.rowBytes());
mBitmap.unlockPixels();
mBitmap.notifyPixelsChanged();
mBitmap.setAlphaType(kOpaque_SkAlphaType);
mBitmap.setIsOpaque(true);
}
mSize = aSize;

View File

@ -470,7 +470,7 @@ SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source,
src_row += h * row_words;
dst_row += result.rowBytes() / 4;
}
result.setAlphaType(img.alphaType());
result.setIsOpaque(img.isOpaque());
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.setAlphaType(source.alphaType());
result.setIsOpaque(source.isOpaque());
return result;
}

View File

@ -499,19 +499,6 @@ 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 } },
};

View File

@ -862,12 +862,6 @@ 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);
@ -960,12 +954,6 @@ 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);
@ -1010,12 +998,6 @@ 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);
@ -1361,24 +1343,6 @@ 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);
@ -1506,24 +1470,6 @@ 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;
@ -1730,12 +1676,6 @@ 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);

View File

@ -125,12 +125,6 @@ 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();
@ -256,11 +250,6 @@ 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);
@ -721,57 +710,6 @@ 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"
@ -799,7 +737,6 @@ 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;
@ -826,7 +763,6 @@ 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;
@ -913,18 +849,6 @@ 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;

View File

@ -313,31 +313,6 @@ 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);

View File

@ -19,13 +19,10 @@ 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
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
SkBlitRect_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkUtils_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
endif
endif

View File

@ -2,14 +2,4 @@ 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 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.
The subversion revision used was r8495.

View File

@ -1,92 +0,0 @@
# 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()

View File

@ -1,295 +0,0 @@
#!/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()

View File

@ -1,13 +0,0 @@
#!/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

View File

@ -37,6 +37,22 @@
///////////////////////////////////////////////////////////////////////////////
/* 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
@ -63,7 +79,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 0
//#define SK_ENABLE_INST_COUNT 1
/* If, in debugging mode, Skia needs to stop (presumably to invoke a debugger)
it will call SK_CRASH(). If this is not defined it, it is defined in
@ -88,6 +104,12 @@
//#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
@ -100,12 +122,10 @@
*/
//#define SK_DEFAULT_FONT_CACHE_LIMIT (1024 * 1024)
/*
* To specify the default size of the image cache, undefine this and set it to
* the desired value (in bytes). SkGraphics.h as a runtime API to set this
* value as well. If this is undefined, a built-in value will be used.
*/
//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
/* If defined, use CoreText instead of ATSUI on OS X.
*/
//#define SK_USE_MAC_CORE_TEXT
/* If zlib is available and you want to support the flate compression
algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the
@ -124,6 +144,17 @@
*/
//#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
@ -170,35 +201,14 @@
*/
//#define SK_SUPPORT_GPU 1
/* The PDF generation code uses Path Ops to generate inverse fills and complex
* clipping paths, but at this time, Path Ops is not release ready yet. So,
* the code is hidden behind this #define guard. If you are feeling adventurous
* and want the latest and greatest PDF generation code, uncomment the #define.
* When Path Ops is release ready, the define guards and this user config
* define should be removed entirely.
/* Don't dither 32bit gradients, to match what the canvas test suite expects.
*/
//#define SK_PDF_USE_PATHOPS
#define SK_DISABLE_DITHER_32BIT_GRADIENT
/* 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.
/* Don't include stdint.h on windows as it conflicts with our build system.
*/
//#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
#ifdef SK_BUILD_FOR_WIN32
#define SK_IGNORE_STDINT_DOT_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

View File

@ -0,0 +1,23 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef sk_stdint_DEFINED
#define sk_stdint_DEFINED
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
#endif

View File

@ -15,6 +15,7 @@
#include "SkString.h"
#include "SkTDArray.h"
#include "SkTemplates.h"
#include "SkTScopedPtr.h"
/** \class SkAdvancedTypefaceMetrics
@ -89,7 +90,7 @@ public:
uint16_t fStartId;
uint16_t fEndId;
SkTDArray<Data> fAdvance;
SkAutoTDelete<AdvanceMetric<Data> > fNext;
SkTScopedPtr<AdvanceMetric<Data> > fNext;
};
struct VerticalMetric {
@ -101,12 +102,12 @@ public:
typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
// This is indexed by glyph id.
SkAutoTDelete<WidthRange> fGlyphWidths;
SkTScopedPtr<WidthRange> fGlyphWidths;
// Only used for Vertical CID fonts.
SkAutoTDelete<VerticalAdvanceRange> fVerticalMetrics;
SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
// The names of each glyph, only populated for postscript fonts.
SkAutoTDelete<SkAutoTArray<SkString> > fGlyphNames;
SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
// The mapping from glyph to Unicode, only populated if
// kToUnicode_PerGlyphInfo is passed to GetAdvancedTypefaceMetrics.
@ -124,7 +125,7 @@ void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
template <typename Data>
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
SkAutoTDelete<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
int startId);
template <typename Data>

View File

@ -8,12 +8,10 @@
#ifndef SkAnnotation_DEFINED
#define SkAnnotation_DEFINED
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkFlattenable.h"
class SkData;
class SkReadBuffer;
class SkWriteBuffer;
class SkDataSet;
class SkStream;
class SkWStream;
struct SkPoint;
@ -22,24 +20,40 @@ 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 SkRefCnt {
class SkAnnotation : public SkFlattenable {
public:
SkAnnotation(const char key[], SkData* value);
enum Flags {
// If set, the associated drawing primitive should not be drawn
kNoDraw_Flag = 1 << 0,
};
SkAnnotation(SkDataSet*, uint32_t flags);
virtual ~SkAnnotation();
/**
* Return the data for the specified key, or NULL.
*/
SkData* find(const char key[]) const;
uint32_t getFlags() const { return fFlags; }
SkDataSet* getDataSet() const { return fDataSet; }
SkAnnotation(SkReadBuffer&);
void writeToBuffer(SkWriteBuffer&) const;
bool isNoDraw() const { return SkToBool(fFlags & kNoDraw_Flag); }
/**
* Helper for search the annotation's dataset.
*/
SkData* find(const char name[]) const;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAnnotation)
protected:
SkAnnotation(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:
SkString fKey;
SkData* fData;
SkDataSet* fDataSet;
uint32_t fFlags;
typedef SkRefCnt INHERITED;
void writeToStream(SkWStream*) const;
void readFromStream(SkStream*);
typedef SkFlattenable INHERITED;
};
/**

View File

@ -1,3 +1,4 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -5,12 +6,13 @@
* 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"
@ -18,11 +20,11 @@ struct SkIRect;
struct SkRect;
class SkPaint;
class SkPixelRef;
class SkPixelRefFactory;
class SkRegion;
class SkString;
class GrTexture;
// This is an opaque class, not interpreted by skia
class SkGpuTexture;
/** \class SkBitmap
@ -36,21 +38,29 @@ class GrTexture;
*/
class SK_API SkBitmap {
public:
class SK_API Allocator;
class Allocator;
enum Config {
kNo_Config, //!< bitmap has not been configured
/**
* 1-bit per pixel, (0 is transparent, 1 is opaque)
* Valid as a destination (target of a canvas), but not valid as a src.
* i.e. you can draw into a 1-bit bitmap, but you cannot draw from one.
*/
kA1_Config,
kA8_Config, //!< 8-bits per pixel, with only alpha specified (0 is transparent, 0xFF is opaque)
kIndex8_Config, //!< 8-bits per pixel, using SkColorTable to specify the colors
kRGB_565_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
kARGB_4444_Config, //!< 16-bits per pixel, (see SkColorPriv.h for packing)
kARGB_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing)
};
/**
* 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,
// 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
kConfigCount
};
/**
@ -79,72 +89,49 @@ public:
// This method is not exported to java.
void swap(SkBitmap& other);
///////////////////////////////////////////////////////////////////////////
const SkImageInfo& info() const { return fInfo; }
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 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 >> 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(); }
*/
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()).
* Hey! Before you use this, see if you really want to know drawsNothing() instead.
*/
dimensions of the bitmap are > 0 (see empty()).
*/
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()")
/** Return the config for the bitmap.
*/
Config config() const { return (Config)fConfig; }
/** DEPRECATED, use config()
*/
Config getConfig() const { return this->config(); }
/** Return the number of bytes between subsequent rows of the bitmap. */
/** 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; }
/**
* 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 shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for
2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0
for configs that are not at least 1-byte per pixel (e.g. kA1_Config
or kNo_Config)
*/
int shiftPerPixel() const { return fBytesPerPixel >> 1; }
/** Return the number of bytes per pixel based on the config. If the config
does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned.
*/
int bytesPerPixel() const { return fBytesPerPixel; }
/** Return the rowbytes expressed as a number of pixels (like width and
height). Note, for 1-byte per pixel configs like kA8_Config, this will
return the same as rowBytes(). Is undefined for configs that are less
than 1-byte per pixel (e.g. kA1_Config)
*/
int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); }
/** Return the address of the pixels for this SkBitmap.
*/
@ -154,29 +141,27 @@ public:
Note this truncates the result to 32bits. Call getSize64() to detect
if the real size exceeds 32bits.
*/
size_t getSize() const { return fInfo.fHeight * fRowBytes; }
size_t getSize() const { return fHeight * fRowBytes; }
/** Return the number of bytes from the pointer returned by getPixels()
to the end of the allocated space in the buffer. Required in
cases where extractSubset has been called.
*/
size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
size_t getSafeSize() const ;
/**
* Return the full size of the bitmap, in bytes.
*/
int64_t computeSize64() const {
return sk_64_mul(fInfo.fHeight, 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 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);
}
/** Same as getSafeSize(), but does not truncate the answer to 32bits.
*/
Sk64 getSafeSize64() const ;
/** Returns true if this bitmap is marked as immutable, meaning that the
contents of its pixels will not change for the lifetime of the bitmap.
@ -193,9 +178,12 @@ public:
/** Returns true if the bitmap is opaque (has no translucent/transparent pixels).
*/
bool isOpaque() const {
return SkAlphaTypeIsOpaque(this->alphaType());
}
bool isOpaque() const;
/** Specify if this bitmap's pixels are all opaque or not. Is only meaningful for configs
that support per-pixel alpha (RGB32, A1, A8).
*/
void setIsOpaque(bool);
/** Returns true if the bitmap is volatile (i.e. should not be cached by devices.)
*/
@ -232,7 +220,7 @@ public:
return ComputeBytesPerPixel(c) >> 1;
}
static int64_t ComputeSize64(Config, int width, int height);
static Sk64 ComputeSize64(Config, int width, int height);
static size_t ComputeSize(Config, int width, int height);
/**
@ -241,11 +229,18 @@ public:
* it will return false.
*
* Since this can be an expensive operation, the bitmap stores a flag for
* this (isOpaque). Only call this if you need to compute this value from
* "unknown" pixels.
* this (isOpaque, setIsOpaque). Only call this if you need to compute this
* value from "unknown" pixels.
*/
static bool ComputeIsOpaque(const SkBitmap&);
/**
* Calls ComputeIsOpaque, and passes its result to setIsOpaque().
*/
void computeAndSetOpaquePredicate() {
this->setIsOpaque(ComputeIsOpaque(*this));
}
/**
* Return the bitmap's bounds [0, 0, width, height] as an SkRect
*/
@ -256,72 +251,7 @@ public:
ComputeRowBytes() is called to compute the optimal value. This resets
any pixel/colortable ownership, just like reset().
*/
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;
}
void setConfig(Config, int width, int height, size_t rowBytes = 0);
/** Use this to assign a new pixel address for an existing bitmap. This
will automatically release any pixelref previously installed. Only call
this if you are handling ownership/lifetime of the pixel memory.
@ -393,41 +323,18 @@ public:
*/
bool allocPixels(Allocator* allocator, SkColorTable* ctable);
/**
* Return the current pixelref object or NULL if there is none. This does
* not affect the refcount of the pixelref.
*/
/** Return the current pixelref object, if any
*/
SkPixelRef* pixelRef() const { return fPixelRef; }
/**
* 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);
}
/** Return the offset into the pixelref, if any. Will return 0 if there is
no pixelref installed.
*/
size_t pixelRefOffset() const { return fPixelRefOffset; }
/** Assign a pixelref and optional offset. Pixelrefs are reference counted,
so the existing one (if any) will be unref'd and the new one will be
ref'd.
*/
SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset = 0);
/** Call this to ensure that the bitmap points to the current pixel address
in the pixelref. Balance it with a call to unlockPixels(). These calls
@ -455,16 +362,16 @@ public:
*/
bool readyToDraw() const {
return this->getPixels() != NULL &&
(this->config() != kIndex8_Config || NULL != fColorTable);
((this->config() != kIndex8_Config &&
this->config() != kRLE_Index8_Config) ||
fColorTable != NULL);
}
/** Returns the pixelRef's texture, or NULL
*/
GrTexture* getTexture() const;
SkGpuTexture* getTexture() const;
/** 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
/** Return the bitmap's colortable (if any). Does not affect the colortable's
reference count.
*/
SkColorTable* getColorTable() const { return fColorTable; }
@ -482,38 +389,28 @@ public:
*/
void notifyPixelsChanged() const;
/**
* Fill the entire bitmap with the specified color.
* If the bitmap's config does not support alpha (e.g. 565) then the alpha
* of the color is ignored (treated as opaque). If the config only supports
* alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
*/
/** 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.
*/
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,
@ -578,6 +475,14 @@ 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,
@ -627,8 +532,15 @@ public:
*/
bool canCopyTo(Config newConfig) const;
SK_ATTR_DEPRECATED("use setFilterLevel on SkPaint")
bool hasMipMap() const;
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 {
@ -676,8 +588,8 @@ public:
buffers as they can optimize the recording process and avoid recording
duplicate bitmaps and pixelRefs.
*/
void flatten(SkWriteBuffer&) const;
void unflatten(SkReadBuffer&);
void flatten(SkFlattenableWriteBuffer&) const;
void unflatten(SkFlattenableReadBuffer&);
SkDEBUGCODE(void validate() const;)
@ -703,7 +615,7 @@ public:
*/
class HeapAllocator : public Allocator {
public:
virtual bool allocPixelRef(SkBitmap*, SkColorTable*) SK_OVERRIDE;
virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
};
class RLEPixels {
@ -734,13 +646,13 @@ private:
mutable MipMap* fMipMap;
mutable SkPixelRef* fPixelRef;
mutable size_t fPixelRefOffset;
mutable int fPixelLockCount;
// These are just caches from the locked pixelref
// either user-specified (in which case it is not treated as mutable)
// or a cache of the returned value from fPixelRef->lockPixels()
mutable void* fPixels;
mutable SkColorTable* fColorTable; // only meaningful for kIndex8
SkIPoint fPixelRefOrigin;
enum Flags {
kImageIsOpaque_Flag = 0x01,
kImageIsVolatile_Flag = 0x02,
@ -754,20 +666,19 @@ private:
#endif
};
SkImageInfo fInfo;
uint32_t fRowBytes;
uint32_t fWidth;
uint32_t fHeight;
uint8_t fConfig;
uint8_t fFlags;
void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const;
uint8_t fBytesPerPixel; // based on config
/* Internal computations for safe size.
*/
static int64_t ComputeSafeSize64(Config config,
uint32_t width,
uint32_t height,
size_t rowBytes);
static Sk64 ComputeSafeSize64(Config config,
uint32_t width,
uint32_t height,
size_t rowBytes);
static size_t ComputeSafeSize(Config config,
uint32_t width,
uint32_t height,
@ -779,16 +690,6 @@ 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 {
@ -809,8 +710,6 @@ 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
@ -835,7 +734,7 @@ public:
}
~SkAutoLockColors() {
if (fCTable) {
fCTable->unlockColors();
fCTable->unlockColors(false);
}
}
@ -849,7 +748,7 @@ public:
*/
const SkPMColor* lockColors(SkColorTable* ctable) {
if (fCTable) {
fCTable->unlockColors();
fCTable->unlockColors(false);
}
fCTable = ctable;
fColors = ctable ? ctable->lockColors() : NULL;
@ -864,37 +763,44 @@ 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(this->config() == kARGB_8888_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kARGB_8888_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
}
inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kRGB_565_Config || this->config() == kARGB_4444_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
}
inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kA8_Config || this->config() == kIndex8_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint8_t*)fPixels + y * fRowBytes + x;
}
inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kIndex8_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
SkASSERT(fColorTable);
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}
// returns the address of the byte that contains the x coordinate
inline uint8_t* SkBitmap::getAddr1(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(fConfig == kA1_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
}
#endif

View File

@ -92,6 +92,7 @@ public:
static Proc32 PlatformProcs32(unsigned flags);
static Proc PlatformProcs565(unsigned flags);
static Proc PlatformProcs4444(unsigned flags);
static ColorProc PlatformColorProc();
private:

View File

@ -1,3 +1,4 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -5,6 +6,7 @@
* found in the LICENSE file.
*/
#ifndef SkCanvas_DEFINED
#define SkCanvas_DEFINED
@ -16,18 +18,17 @@
#include "SkRefCnt.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkScalarCompare.h"
#include "SkXfermode.h"
class SkBounder;
class SkBaseDevice;
class SkDevice;
class SkDraw;
class SkDrawFilter;
class SkMetaData;
class SkPicture;
class SkRRect;
class SkSurface;
class SkSurface_Base;
class GrContext;
/** \class SkCanvas
@ -48,26 +49,15 @@ 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(SkBaseDevice* device);
explicit SkCanvas(SkDevice* device);
/** Construct a canvas with the specified bitmap to draw into.
/** Deprecated - Construct a canvas with the specified bitmap to draw into.
@param bitmap Specifies a bitmap for the canvas to draw into. Its
structure are copied to the canvas.
*/
@ -94,7 +84,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.
*/
SkBaseDevice* getDevice() const;
SkDevice* getDevice() const;
/**
* saveLayer() can create another device (which is later drawn onto
@ -109,19 +99,15 @@ public:
* is drawn to, but is optional here, as there is a small perf hit
* sometimes.
*/
SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
SkDevice* getTopDevice(bool updateMatrixClip = false) const;
/**
* Create a new surface matching the specified info, one that attempts to
* be maximally compatible when used with this canvas.
* Shortcut for getDevice()->createCompatibleDevice(...).
* If getDevice() == NULL, this method does nothing, and returns NULL.
*/
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();
SkDevice* createCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque);
///////////////////////////////////////////////////////////////////////////
@ -253,12 +239,6 @@ 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);
@ -401,13 +381,6 @@ 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
@ -462,13 +435,14 @@ public:
not intersect the current clip)
*/
bool quickRejectY(SkScalar top, SkScalar bottom) const {
SkASSERT(top <= bottom);
const SkRect& clipR = this->getLocalClipBounds();
SkASSERT(SkScalarToCompareType(top) <= SkScalarToCompareType(bottom));
const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
// In the case where the clip is empty and we are provided with a
// negative top and positive bottom parameter then this test will return
// false even though it will be clipped. We have chosen to exclude that
// check as it is rare and would result double the comparisons.
return top >= clipR.fBottom || bottom <= clipR.fTop;
return SkScalarToCompareType(top) >= clipR.fBottom
|| SkScalarToCompareType(bottom) <= clipR.fTop;
}
/** Return the bounds of the current clip (in local coordinates) in the
@ -678,11 +652,6 @@ 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
@ -691,16 +660,6 @@ 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
@ -711,24 +670,22 @@ public:
*/
virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst,
const SkPaint* paint = NULL,
DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
const SkPaint* paint);
void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
const SkPaint* paint = NULL) {
this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
const SkPaint* paint) {
this->drawBitmapRectToRect(bitmap, NULL, dst, paint);
}
void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
const SkRect& dst, const SkPaint* paint = NULL,
DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
const SkRect& dst, const SkPaint* paint = NULL) {
SkRect realSrcStorage;
SkRect* realSrcPtr = NULL;
if (isrc) {
realSrcStorage.set(*isrc);
realSrcPtr = &realSrcStorage;
}
this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint);
}
virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
@ -741,9 +698,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 stretched at all.
* - The sides are stretched in only one axis.
* - The center is stretched in both axes.
* - The 4 corners are not stretch at all.
* - The sides are stretch in only one axis.
* - The center is stretch 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
@ -829,6 +786,21 @@ 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.
@ -849,7 +821,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 (not uv space) for each vertex.
in texture 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
@ -873,24 +845,7 @@ 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) {
// 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
}
virtual void drawData(const void* data, size_t length);
//////////////////////////////////////////////////////////////////////////
@ -945,10 +900,11 @@ public:
*/
ClipType getClipType() const;
/** DEPRECATED -- need to move this guy to private/friend
* Return the current device clip (concatenation of all clip calls).
/** 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;
@ -996,7 +952,7 @@ public:
// These reflect the current device in the iterator
SkBaseDevice* device() const;
SkDevice* device() const;
const SkMatrix& matrix() const;
const SkRegion& clip() const;
const SkPaint& paint() const;
@ -1016,34 +972,27 @@ 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,
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);
SkIRect* intersection);
// 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 -- need to remove when subclass stop relying on it.
/** DEPRECATED -- use constructor(device)
Marked as 'protected' to avoid new clients using this before we can
completely remove it.
@ -1051,7 +1000,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 SkBaseDevice* setDevice(SkBaseDevice* device);
virtual SkDevice* setDevice(SkDevice* device);
private:
class MCRec;
@ -1074,7 +1023,6 @@ private:
fSurfaceBase = sb;
}
friend class SkSurface_Base;
friend class SkSurface_Gpu;
bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
void updateDeviceCMCache();
@ -1082,23 +1030,23 @@ private:
friend class SkDrawIter; // needs setupDrawForLayerDevice()
friend class AutoDrawLooper;
SkBaseDevice* createLayerDevice(SkBitmap::Config, int width, int height,
bool isOpaque);
SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
bool isOpaque);
SkBaseDevice* init(SkBaseDevice*);
SkDevice* init(SkDevice*);
// internal methods are not virtual, so they can safely be called by other
// canvas apis, without confusing subclasses (like SkPictureRecording)
void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m,
const SkPaint* paint);
void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
DrawBitmapRectFlags flags);
const SkRect& dst, const SkPaint* paint);
void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint);
void internalDrawPaint(const SkPaint& paint);
int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
SaveFlags, bool justForImageFilter);
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
void internalDrawDevice(SkDevice*, int x, int y, const SkPaint*);
// shared by save() and saveLayer()
int internalSave(SaveFlags flags);
@ -1112,20 +1060,18 @@ private:
/* These maintain a cache of the clip bounds in local coordinates,
(converted to 2s-compliment if floats are slow).
*/
mutable SkRect fCachedLocalClipBounds;
mutable bool fCachedLocalClipBoundsDirty;
mutable SkRectCompareType fLocalBoundsCompareType;
mutable bool fLocalBoundsCompareTypeDirty;
bool fAllowSoftClip;
bool fAllowSimplifyClip;
const SkRect& getLocalClipBounds() const {
if (fCachedLocalClipBoundsDirty) {
if (!this->getClipBounds(&fCachedLocalClipBounds)) {
fCachedLocalClipBounds.setEmpty();
}
fCachedLocalClipBoundsDirty = false;
const SkRectCompareType& getLocalClipBoundsCompareType() const {
if (fLocalBoundsCompareTypeDirty) {
this->computeLocalClipBoundsCompareType();
fLocalBoundsCompareTypeDirty = false;
}
return fCachedLocalClipBounds;
return fLocalBoundsCompareType;
}
void computeLocalClipBoundsCompareType() const;
class AutoValidateClip : ::SkNoncopyable {
public:
@ -1153,12 +1099,11 @@ private:
*/
class SkAutoCanvasRestore : SkNoncopyable {
public:
SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
if (fCanvas) {
fSaveCount = canvas->getSaveCount();
if (doSave) {
canvas->save();
}
SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
SkASSERT(canvas);
fSaveCount = canvas->getSaveCount();
if (doSave) {
canvas->save();
}
}
~SkAutoCanvasRestore() {
@ -1182,28 +1127,5 @@ 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

View File

@ -10,15 +10,6 @@
#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:
/*
@ -36,42 +27,6 @@ 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
*

View File

@ -42,7 +42,6 @@ public:
size_t unalloc(void* ptr);
size_t totalCapacity() const { return fTotalCapacity; }
size_t totalUsed() const { return fTotalUsed; }
int blockCount() const { return fBlockCount; }
/**
@ -59,7 +58,6 @@ 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);

View File

@ -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 { SkASSERT(kInvalidGenID != fGenID); return fGenID; }
int32_t getGenID() const { return fGenID; }
/**
* Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
@ -315,13 +315,26 @@ 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; //!< Invalid id that is never returned by
//!< SkClipStack. Useful when caching clips
//!< based on GenID.
static const int32_t kInvalidGenID = 0;
static const int32_t kEmptyGenID = 1; // no pixels writeable
static const int32_t kWideOpenGenID = 2; // all pixels writeable
@ -427,10 +440,22 @@ 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<ClipCallbackData> fCallbackData;
/**
* Restore the stack back to the specified save count.
* Invoke all the purge callbacks passing in element's generation ID.
*/
void restoreTo(int saveCount);
void purgeClip(Element* element);
/**
* Return the next unique generation ID.

View File

@ -73,9 +73,6 @@ 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

View File

@ -18,14 +18,6 @@ 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)
@ -128,14 +120,10 @@ 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(SkReadBuffer& rb) : INHERITED(rb) {}
SkColorFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {}
private:
typedef SkFlattenable INHERITED;

View File

@ -269,90 +269,36 @@ static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
}
/**
* 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].
* 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.
*/
static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
SkPMColor dst,
U8CPU srcWeight) {
SkASSERT(srcWeight <= 255);
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;
// scale = srcWeight + (srcWeight >> 7) is more accurate than
// scale = srcWeight + 1, but 7% slower
return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
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);
}
/**
@ -367,9 +313,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);
SkR32Assert(r);
SkG32Assert(g);
SkB32Assert(b);
SkA32Assert(r);
SkA32Assert(g);
SkA32Assert(b);
if (a != 255) {
r = SkMulDiv255Round(r, a);
@ -383,6 +329,7 @@ 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;
@ -886,29 +833,29 @@ static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
SkBlend32(srcB, dstB, maskB));
}
static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
SkColor src, int width, SkPMColor) {
int srcA = SkColorGetA(src);
int srcR = SkColorGetR(src);
int srcG = SkColorGetG(src);
int srcB = SkColorGetB(src);
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);
srcA = SkAlpha255To256(srcA);
for (int i = 0; i < width; i++) {
dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], src[i]);
}
}
static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
SkColor src, int width,
static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t src[],
SkColor color, int width,
SkPMColor opaqueDst) {
int srcR = SkColorGetR(src);
int srcG = SkColorGetG(src);
int srcB = SkColorGetB(src);
int srcR = SkColorGetR(color);
int srcG = SkColorGetG(color);
int srcB = SkColorGetB(color);
for (int i = 0; i < width; i++) {
dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], src[i],
opaqueDst);
}
}

View File

@ -52,8 +52,8 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorShader)
protected:
SkColorShader(SkReadBuffer&);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkColorShader(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:

View File

@ -0,0 +1,112 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkColorTable_DEFINED
#define SkColorTable_DEFINED
#include "SkColor.h"
#include "SkFlattenable.h"
/** \class SkColorTable
SkColorTable holds an array SkPMColors (premultiplied 32-bit colors) used by
8-bit bitmaps, where the bitmap bytes are interpreted as indices into the colortable.
*/
class SkColorTable : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkColorTable)
/** Makes a deep copy of colors.
*/
SkColorTable(const SkColorTable& src);
/** Preallocates the colortable to have 'count' colors, which
* are initially set to 0.
*/
explicit SkColorTable(int count);
SkColorTable(const SkPMColor colors[], int count);
virtual ~SkColorTable();
enum Flags {
kColorsAreOpaque_Flag = 0x01 //!< if set, all of the colors in the table are opaque (alpha==0xFF)
};
/** Returns the flag bits for the color table. These can be changed with setFlags().
*/
unsigned getFlags() const { return fFlags; }
/** Set the flags for the color table. See the Flags enum for possible values.
*/
void setFlags(unsigned flags);
bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; }
void setIsOpaque(bool isOpaque);
/** Returns the number of colors in the table.
*/
int count() const { return fCount; }
/** Returns the specified color from the table. In the debug build, this asserts that
the index is in range (0 <= index < count).
*/
SkPMColor operator[](int index) const {
SkASSERT(fColors != NULL && (unsigned)index < fCount);
return fColors[index];
}
/** Specify the number of colors in the color table. This does not initialize the colors
to any value, just allocates memory for them. To initialize the values, either call
setColors(array, count), or follow setCount(count) with a call to
lockColors()/{set the values}/unlockColors(true).
*/
// void setColors(int count) { this->setColors(NULL, count); }
// void setColors(const SkPMColor[], int count);
/** Return the array of colors for reading and/or writing. This must be
balanced by a call to unlockColors(changed?), telling the colortable if
the colors were changed during the lock.
*/
SkPMColor* lockColors() {
SkDEBUGCODE(sk_atomic_inc(&fColorLockCount);)
return fColors;
}
/** Balancing call to lockColors(). If the colors have been changed, pass true.
*/
void unlockColors(bool changed);
/** Similar to lockColors(), lock16BitCache() returns the array of
RGB16 colors that mirror the 32bit colors. However, this function
will return null if kColorsAreOpaque_Flag is not set.
Also, unlike lockColors(), the returned array here cannot be modified.
*/
const uint16_t* lock16BitCache();
/** Balancing call to lock16BitCache().
*/
void unlock16BitCache() {
SkASSERT(f16BitCacheLockCount > 0);
SkDEBUGCODE(f16BitCacheLockCount -= 1);
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorTable)
protected:
explicit SkColorTable(SkFlattenableReadBuffer&);
void flatten(SkFlattenableWriteBuffer&) const;
private:
SkPMColor* fColors;
uint16_t* f16BitCache;
uint16_t fCount;
uint8_t fFlags;
SkDEBUGCODE(int fColorLockCount;)
SkDEBUGCODE(int f16BitCacheLockCount;)
void inval16BitCache();
typedef SkFlattenable INHERITED;
};
#endif

View File

@ -43,8 +43,8 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader)
protected:
SkComposeShader(SkReadBuffer& );
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkComposeShader(SkFlattenableReadBuffer& );
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:

View File

@ -11,16 +11,14 @@
#ifndef SkData_DEFINED
#define SkData_DEFINED
#include "SkRefCnt.h"
struct SkFILE;
#include "SkFlattenable.h"
/**
* 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 SkRefCnt {
class SK_API SkData : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkData)
@ -91,28 +89,10 @@ public:
static SkData* NewFromMalloc(const void* data, size_t length);
/**
* Create a new dataref the file with the specified path.
* If the file cannot be opened, this returns NULL.
* Create a new dataref from a pointer allocated by mmap. The Data object
* will handle calling munmap().
*/
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);
static SkData* NewFromMMap(const void* data, size_t length);
/**
* Create a new dataref using a subset of the data in the specified
@ -126,6 +106,12 @@ 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;
@ -136,13 +122,41 @@ private:
SkData(const void* ptr, size_t size, ReleaseProc, void* context);
virtual ~SkData();
// Called the first time someone calls NewEmpty to initialize the singleton.
static void NewEmptyImpl(int/*unused*/);
// 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<SkData>::BlockRef<SkData>;
typedef SkRefCnt INHERITED;
typedef SkFlattenable INHERITED;
};
/** Typedef of SkAutoTUnref<SkData> for automatically unref-ing a SkData. */
typedef SkAutoTUnref<SkData> SkAutoDataUnref;
/**
* Specialized version of SkAutoTUnref<SkData> 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;
};
#endif

View File

@ -0,0 +1,88 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDataSet_DEFINED
#define SkDataSet_DEFINED
#include "SkData.h"
#include "SkFlattenable.h"
class SkStream;
class SkWStream;
class SkDataSet : public SkFlattenable {
public:
/**
* Returns a new empty dataset. Note: since SkDataSet is immutable, this
* "new" set may be the same one that was returned before, but each
* returned object must have its reference-count balanced regardless.
*
* SkDataSet* empty = SkDataSet::NewEmpty();
* ...
* empty->unref();
*/
static SkDataSet* NewEmpty();
struct Pair {
const char* fKey;
SkData* fValue;
};
SkDataSet(const char key[], SkData* value);
SkDataSet(const Pair[], int count);
virtual ~SkDataSet();
bool isEmpty() const { return 0 == fCount; }
int count() const { return fCount; }
SkData* find(const char name[]) const;
class Iter {
public:
Iter(const SkDataSet& ds) {
fPair = ds.fPairs;
fStop = ds.fPairs + ds.fCount;
}
const char* key() const {
SkASSERT(!this->done());
return fPair->fKey;
}
SkData* value() const {
SkASSERT(!this->done());
return fPair->fValue;
}
bool done() const { return fPair >= fStop; }
void next() {
SkASSERT(!this->done());
fPair += 1;
}
private:
const SkDataSet::Pair* fPair;
const SkDataSet::Pair* fStop;
};
explicit SkDataSet(SkStream*);
void writeToStream(SkWStream*) const;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataSet)
protected:
SkDataSet(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:
int32_t fCount;
uint32_t fKeySize;
Pair* fPairs;
typedef SkFlattenable INHERITED;
};
#endif

View File

@ -81,7 +81,7 @@ public:
void reset(const SkDeque& d, IterStart startLoc);
private:
SkDeque::Block* fCurBlock;
SkDeque::Block* fCurBlock;
char* fPos;
size_t fElemSize;
};

View File

@ -23,23 +23,60 @@ class SkMatrix;
class SkMetaData;
class SkRegion;
class GrRenderTarget;
// This is an opaque class, not interpreted by skia
class SkGpuRenderTarget;
class SK_API SkBaseDevice : public SkRefCnt {
class SK_API SkDevice : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkBaseDevice)
SK_DECLARE_INST_COUNT(SkDevice)
/**
* Construct a new device.
* 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.
*/
SkBaseDevice();
SkDevice(const SkBitmap& bitmap);
/**
* Construct a new device.
* 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.
*/
SkBaseDevice(const SkDeviceProperties& deviceProperties);
SkDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties);
virtual ~SkBaseDevice();
/**
* Create a new raster device and have the pixels be automatically
* allocated. The rowBytes of the device will be computed automatically
* based on the config and the width.
*
* @param config The desired config for the pixels. If the request cannot
* be met, the closest matching support config will be used.
* @param width width (in pixels) of the device
* @param height height (in pixels) of the device
* @param isOpaque Set to true if it is known that all of the pixels will
* be drawn to opaquely. Used as an accelerator when drawing
* these pixels to another device.
*/
SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque = false);
/**
* Create a new raster device and have the pixels be automatically
* allocated. The rowBytes of the device will be computed automatically
* based on the config and the width.
*
* @param config The desired config for the pixels. If the request cannot
* be met, the closest matching support config will be used.
* @param width width (in pixels) of the device
* @param height height (in pixels) of the device
* @param isOpaque Set to true if it is known that all of the pixels will
* be drawn to opaquely. Used as an accelerator when drawing
* these pixels to another device.
* @param deviceProperties Properties which affect compositing.
*/
SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
const SkDeviceProperties& deviceProperties);
virtual ~SkDevice();
/**
* Creates a device that is of the same type as this device (e.g. SW-raster,
@ -52,23 +89,25 @@ public:
* draw into this device such that all of the pixels will
* be opaque.
*/
SkBaseDevice* createCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque);
SkDevice* createCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque);
SkMetaData& getMetaData();
enum Capabilities {
kVector_Capability = 0x1, //!< mask indicating a vector representation
kGL_Capability = 0x1, //!< mask indicating GL support
kVector_Capability = 0x2, //!< mask indicating a vector representation
kAll_Capabilities = 0x3
};
virtual uint32_t getDeviceCapabilities() = 0;
virtual uint32_t getDeviceCapabilities() { return 0; }
/** Return the width of the device (in pixels).
*/
virtual int width() const = 0;
virtual int width() const { return fBitmap.width(); }
/** Return the height of the device (in pixels).
*/
virtual int height() const = 0;
virtual int height() const { return fBitmap.height(); }
/** Return the image properties of the device. */
virtual const SkDeviceProperties& getDeviceProperties() const {
@ -81,22 +120,16 @@ 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 {
SkASSERT(bounds);
const SkIPoint& origin = this->getOrigin();
bounds->setXYWH(origin.x(), origin.y(), this->width(), this->height());
}
void getGlobalBounds(SkIRect* bounds) const;
/** Returns true if the device's bitmap's config treats every pixel as
/** Returns true if the device's bitmap's config treats every pixels as
implicitly opaque.
*/
virtual bool isOpaque() const = 0;
bool isOpaque() const { return fBitmap.isOpaque(); }
/** Return the bitmap config of the device's pixels
*/
SK_ATTR_DEPRECATED("want to hide configness of the device -- don't use")
virtual SkBitmap::Config config() const = 0;
*/
SkBitmap::Config config() const { return fBitmap.getConfig(); }
/** Return the bitmap associated with this device. Call this each time you need
to access the bitmap, as it notifies the subclass to perform any flushing
@ -122,12 +155,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) = 0;
SkCanvas::Config8888 config8888 = SkCanvas::kNative_Premul_Config8888);
/**
* Return the device's associated gpu render target, or NULL.
*/
virtual GrRenderTarget* accessRenderTarget() = 0;
virtual SkGpuRenderTarget* accessRenderTarget() { return NULL; }
/**
@ -139,7 +172,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' SkBaseDevice & SkBitmap -taking ctors). It allows the
* and SkCanvas' SkDevice & SkBitmap -taking ctors). It allows the
* devices to prepare for drawing (e.g., locking their pixels, etc.)
*/
virtual void onAttachToCanvas(SkCanvas*) {
@ -181,9 +214,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 SkBaseDevice filters based on its depth and blitters.
* The baseclass SkDevice filters based on its depth and blitters.
*/
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) = 0;
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
/**
*
@ -202,14 +235,16 @@ 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) = 0;
virtual void clear(SkColor color);
SK_ATTR_DEPRECATED("use clear() instead")
/**
* Deprecated name for clear.
*/
void eraseColor(SkColor eraseColor) { this->clear(eraseColor); }
/** These are called inside the per-device-layer loop for each draw call.
@ -217,16 +252,13 @@ protected:
and are handling any looping from the paint, and any effects from the
DrawFilter.
*/
virtual void drawPaint(const SkDraw&, const SkPaint& paint) = 0;
virtual void drawPaint(const SkDraw&, const SkPaint& paint);
virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
const SkPoint[], const SkPaint& paint) = 0;
const SkPoint[], const SkPaint& paint);
virtual void drawRect(const SkDraw&, const SkRect& r,
const SkPaint& paint) = 0;
const SkPaint& paint);
virtual void drawOval(const SkDraw&, const SkRect& oval,
const SkPaint& paint) = 0;
virtual void drawRRect(const SkDraw&, const SkRRect& rr,
const SkPaint& paint) = 0;
const SkPaint& paint);
/**
* If pathIsMutable, then the implementation is allowed to cast path to a
* non-const pointer and modify it in place (as an optimization). Canvas
@ -241,11 +273,12 @@ protected:
virtual void drawPath(const SkDraw&, const SkPath& path,
const SkPaint& paint,
const SkMatrix* prePathMatrix = NULL,
bool pathIsMutable = false) = 0;
bool pathIsMutable = false);
virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
const SkMatrix& matrix, const SkPaint& paint) = 0;
const SkIRect* srcRectOrNull,
const SkMatrix& matrix, const SkPaint& paint);
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) = 0;
int x, int y, const SkPaint& paint);
/**
* The default impl. will create a bitmap-shader from the bitmap,
@ -253,31 +286,35 @@ protected:
*/
virtual void drawBitmapRect(const SkDraw&, const SkBitmap&,
const SkRect* srcOrNull, const SkRect& dst,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) = 0;
const SkPaint& paint);
/**
* Does not handle text decoration.
* Decorations (underline and stike-thru) will be handled by SkCanvas.
*/
virtual void drawText(const SkDraw&, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint) = 0;
SkScalar x, SkScalar y, const SkPaint& paint);
virtual void drawPosText(const SkDraw&, const void* text, size_t len,
const SkScalar pos[], SkScalar constY,
int scalarsPerPos, const SkPaint& paint) = 0;
int scalarsPerPos, const SkPaint& paint);
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) = 0;
const SkPaint& paint);
#ifdef SK_BUILD_FOR_ANDROID
virtual void drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
const SkPoint pos[], const SkPaint& paint,
const SkPath& path, const SkMatrix* matrix);
#endif
virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
const SkPoint verts[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) = 0;
const SkPaint& paint);
/** The SkDevice passed will be an SkDevice which was returned by a call to
onCreateCompatibleDevice on this device with kSaveLayer_Usage.
*/
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) = 0;
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&);
/**
* On success (returns true), copy the device pixels into the bitmap.
@ -313,10 +350,20 @@ protected:
///////////////////////////////////////////////////////////////////////////
/** Update as needed the pixel value in the bitmap, so that the caller can
access the pixels directly.
@return The device contents as a bitmap
access the pixels directly. Note: only the pixels field should be
altered. The config/width/height/rowbytes must remain unchanged.
@param bitmap The device's bitmap
@return Echo the bitmap parameter, or an alternate (shadow) bitmap
maintained by the subclass.
*/
virtual const SkBitmap& onAccessBitmap() = 0;
virtual const SkBitmap& onAccessBitmap(SkBitmap*);
SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
// just for subclasses, to assign a custom pixelref
SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) {
fBitmap.setPixelRef(pr, offset);
return pr;
}
/**
* Implements readPixels API. The caller will ensure that:
@ -327,13 +374,13 @@ protected:
*/
virtual bool onReadPixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888) = 0;
SkCanvas::Config8888 config8888);
/** Called when this device is installed into a Canvas. Balanced by a call
/** Called when this device is installed into a Canvas. Balanaced by a call
to unlockPixels() when the device is removed from a Canvas.
*/
virtual void lockPixels() = 0;
virtual void unlockPixels() = 0;
virtual void lockPixels();
virtual void unlockPixels();
/**
* Returns true if the device allows processing of this imagefilter. If
@ -341,7 +388,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(const SkImageFilter*) = 0;
virtual bool allowImageFilter(SkImageFilter*);
/**
* Override and return true for filters that the device can handle
@ -350,7 +397,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(const SkImageFilter*) = 0;
virtual bool canHandleImageFilter(SkImageFilter*);
/**
* Related (but not required) to canHandleImageFilter, this method returns
@ -359,25 +406,13 @@ protected:
* 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) = 0;
virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
SkBitmap* result, SkIPoint* offset);
// This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if
// either is identical to kNative_Premul_Config8888. Otherwise, -1.
static const SkCanvas::Config8888 kPMColorAlias;
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
@ -385,37 +420,42 @@ 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.
// TODO: move to SkBitmapDevice
virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) = 0;
void replaceBitmapBackendForRasterSurface(const SkBitmap&);
// just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); }
// just called by SkCanvas for saveLayer
SkBaseDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
int width, int height,
bool isOpaque);
SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
int width, int height,
bool isOpaque);
/**
* Subclasses should override this to implement createCompatibleDevice.
*/
virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque,
Usage usage) = 0;
virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque,
Usage usage);
/** Causes any deferred drawing to the device to be completed.
*/
virtual void flush() = 0;
virtual void flush() {}
SkBitmap fBitmap;
SkIPoint fOrigin;
SkMetaData* fMetaData;
/**
* Leaky properties are those which the device should be applying but it isn't.
* These properties will be applied by the draw, when and as it can.
* If the device does handle a property, that property should be set to the identity value
* for that property, effectively making it non-leaky.
*/
SkDeviceProperties fLeakyProperties;
#ifdef SK_DEBUG
bool fAttachedToCanvas;

View File

@ -46,10 +46,10 @@ struct SkDeviceProperties {
};
Orientation getOrientation() {
return static_cast<Orientation>(fGeometry & kOrientationMask);
return static_cast<Orientation>(fGeometry | kOrientationMask);
}
Layout getLayout() {
return static_cast<Layout>(fGeometry & kLayoutMask);
return static_cast<Layout>(fGeometry | kLayoutMask);
}
bool isOrientationKnown() {

View File

@ -10,21 +10,20 @@
#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 SkBaseDevice;
class SkMatrix;
class SkDevice;
class SkPath;
class SkRegion;
class SkRasterClip;
struct SkDrawProcs;
struct SkRect;
class SkRRect;
class SkDraw {
public:
@ -35,7 +34,6 @@ 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.
@ -45,15 +43,8 @@ public:
* affect the geometry/rasterization, then the pre matrix can just be
* pre-concated with the current matrix.
*/
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 drawPath(const SkPath& srcPath, const SkPaint&,
const SkMatrix* prePathMatrix, bool pathIsMutable) const;
void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const;
void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const;
void drawText(const char text[], size_t byteLength, SkScalar x,
@ -63,20 +54,19 @@ 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;
/**
* 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);
void drawPath(const SkPath& src, const SkPaint& paint) const {
this->drawPath(src, paint, NULL, false);
}
/** Helper function that creates a mask from a path and an optional maskfilter.
@ -107,20 +97,12 @@ 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
@ -139,7 +121,7 @@ public:
const SkRasterClip* fRC; // required
const SkClipStack* fClipStack; // optional
SkBaseDevice* fDevice; // optional
SkDevice* fDevice; // optional
SkBounder* fBounder; // optional
SkDrawProcs* fProcs; // optional

View File

@ -31,7 +31,6 @@ public:
kLine_Type,
kBitmap_Type,
kRect_Type,
kRRect_Type,
kOval_Type,
kPath_Type,
kText_Type,

View File

@ -64,11 +64,10 @@ public:
const SkRect& src, SkRect* dst);
SkDEVCODE(virtual void toString(SkString* str) const = 0;)
SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)
protected:
SkDrawLooper() {}
SkDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
typedef SkFlattenable INHERITED;

View File

@ -34,7 +34,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader)
protected:
SkEmptyShader(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkEmptyShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
typedef SkShader INHERITED;

View File

@ -65,7 +65,7 @@ template<uint32_t N> struct SkTEndianSwap32 {
(N >> 24);
};
/** Vector version of SkEndianSwap32(), which swaps the
/** Vector version of SkEndianSwap16(), which swaps the
bytes of each value in the array.
*/
static inline void SkEndianSwap32s(uint32_t array[], int count) {
@ -77,70 +77,26 @@ 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<uint64_t N> struct SkTEndianSwap64 {
static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) |
((N & 0x000000000000FF00ULL) << (8*5)) |
((N & 0x0000000000FF0000ULL) << (8*3)) |
((N & 0x00000000FF000000ULL) << (8*1)) |
((N & 0x000000FF00000000ULL) >> (8*1)) |
((N & 0x0000FF0000000000ULL) >> (8*3)) |
((N & 0x00FF000000000000ULL) >> (8*5)) |
((N) >> (8*7)));
};
/** Vector version of SkEndianSwap64(), which swaps the
bytes of each value in the array.
*/
static inline void SkEndianSwap64s(uint64_t array[], int count) {
SkASSERT(count == 0 || array != NULL);
while (--count >= 0) {
*array = SkEndianSwap64(*array);
array += 1;
}
}
#ifdef SK_CPU_LENDIAN
#define SkEndian_SwapBE16(n) SkEndianSwap16(n)
#define SkEndian_SwapBE32(n) SkEndianSwap32(n)
#define SkEndian_SwapBE64(n) SkEndianSwap64(n)
#define SkEndian_SwapLE16(n) (n)
#define SkEndian_SwapLE32(n) (n)
#define SkEndian_SwapLE64(n) (n)
#define SkTEndian_SwapBE16(n) SkTEndianSwap16<n>::value
#define SkTEndian_SwapBE32(n) SkTEndianSwap32<n>::value
#define SkTEndian_SwapBE64(n) SkTEndianSwap64<n>::value
#define SkTEndian_SwapLE16(n) (n)
#define SkTEndian_SwapLE32(n) (n)
#define SkTEndian_SwapLE64(n) (n)
#else // SK_CPU_BENDIAN
#define SkEndian_SwapBE16(n) (n)
#define SkEndian_SwapBE32(n) (n)
#define SkEndian_SwapBE64(n) (n)
#define SkEndian_SwapLE16(n) SkEndianSwap16(n)
#define SkEndian_SwapLE32(n) SkEndianSwap32(n)
#define SkEndian_SwapLE64(n) SkEndianSwap64(n)
#define SkTEndian_SwapBE16(n) (n)
#define SkTEndian_SwapBE32(n) (n)
#define SkTEndian_SwapBE64(n) (n)
#define SkTEndian_SwapLE16(n) SkTEndianSwap16<n>::value
#define SkTEndian_SwapLE32(n) SkTEndianSwap32<n>::value
#define SkTEndian_SwapLE64(n) SkTEndianSwap64<n>::value
#endif
// When a bytestream is embedded in a 32-bit word, how far we need to

View File

@ -1,3 +1,4 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -5,6 +6,7 @@
* found in the LICENSE file.
*/
#ifndef SkFixed_DEFINED
#define SkFixed_DEFINED
@ -53,6 +55,16 @@ 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
*/
@ -67,6 +79,31 @@ typedef int32_t SkFixed;
#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)
@ -75,24 +112,62 @@ typedef int32_t SkFixed;
#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
///////////////////////////////////////////////////////////////////////////////
// TODO: move fixed sin/cos into SkCosineMapper, as that is the only caller
// or rewrite SkCosineMapper to not use it at all
#define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30)
#define SkFractSqrt(n) SkSqrtBits(n, 30)
SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
#define SkFixedSin(radians) SkFixedSinCos(radians, NULL)
static inline SkFixed SkFixedCos(SkFixed radians) {
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)
@ -100,25 +175,34 @@ static inline SkFixed SkFixedCos(SkFixed radians) {
#ifdef SkLONGLONG
inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
{
return (SkFixed)((int64_t)a * b >> 16);
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);
}
#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)
#if defined(SK_CPU_ARM) && !defined(__thumb__)
/* This guy does not handle NaN or other obscurities, but is faster than
than (int)(x*65536)
than (int)(x*65536) when we only have software floats
*/
inline SkFixed SkFloatToFixed_arm(float x)
{
int32_t y, z;
register int32_t y, z;
asm("movs %1, %3, lsl #1 \n"
"mov %2, #0x8E \n"
"sub %1, %2, %1, lsr #24 \n"
"mov %2, %3, lsl #8 \n"
"orr %2, %2, #0x80000000 \n"
"mov %1, %2, lsr %1 \n"
"it cs \n"
"rsbcs %1, %1, #0 \n"
: "=r"(x), "=&r"(y), "=&r"(z)
: "r"(x)
@ -128,7 +212,7 @@ static inline SkFixed SkFixedCos(SkFixed radians) {
}
inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
{
int32_t t;
register int32_t t;
asm("smull %0, %2, %1, %3 \n"
"mov %0, %0, lsr #16 \n"
"orr %0, %0, %2, lsl #16 \n"
@ -138,16 +222,54 @@ static inline SkFixed SkFixedCos(SkFixed radians) {
);
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
///////////////////////////////////////////////////////////////////////////////
@ -159,6 +281,10 @@ typedef int64_t SkFixed48;
#define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32))
#define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f)))
#define SkScalarToFixed48(x) SkFloatToFixed48(x)
#ifdef SK_SCALAR_IS_FLOAT
#define SkScalarToFixed48(x) SkFloatToFixed48(x)
#else
#define SkScalarToFixed48(x) SkFixedToFixed48(x)
#endif
#endif

View File

@ -12,12 +12,11 @@
#include "SkRefCnt.h"
class SkReadBuffer;
class SkWriteBuffer;
class SkFlattenableReadBuffer;
class SkFlattenableWriteBuffer;
#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \
flattenable::GetFlattenableType());
SkFlattenable::Registrar(#flattenable, flattenable::CreateProc);
#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
@ -28,22 +27,14 @@ class SkWriteBuffer;
}
#define SK_DECLARE_UNFLATTENABLE_OBJECT() \
virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
virtual Factory getFactory() SK_OVERRIDE { return NULL; }; \
#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; } \
static SkFlattenable* CreateProc(SkReadBuffer& buffer) { \
virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } \
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& 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
@ -52,22 +43,9 @@ class SkWriteBuffer;
*/
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)(SkReadBuffer&);
typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
SkFlattenable() {}
@ -75,38 +53,32 @@ public:
to recreate your class given a buffer (previously written to by your
override of flatten().
*/
virtual Factory getFactory() const = 0;
/** Returns the name of the object's class
*/
const char* getTypeName() const { return FactoryToName(getFactory()); }
virtual Factory getFactory() = 0;
static Factory NameToFactory(const char name[]);
static const char* FactoryToName(Factory);
static bool NameToType(const char name[], Type* type);
static void Register(const char name[], Factory, Type);
static void Register(const char name[], Factory);
class Registrar {
public:
Registrar(const char name[], Factory factory, Type type) {
SkFlattenable::Register(name, factory, type);
Registrar(const char name[], Factory factory) {
SkFlattenable::Register(name, factory);
}
};
protected:
SkFlattenable(SkFlattenableReadBuffer&) {}
/** Override this to write data specific to your subclass into the buffer,
being sure to call your super-class' version first. This data will later
be passed to your Factory function, returned by getFactory().
*/
virtual void flatten(SkWriteBuffer&) const;
protected:
SkFlattenable(SkReadBuffer&) {}
virtual void flatten(SkFlattenableWriteBuffer&) const;
private:
static void InitializeFlattenablesIfNeeded();
static void InitializeFlattenables();
friend class SkGraphics;
friend class SkFlattenableWriteBuffer;
typedef SkRefCnt INHERITED;
};

View File

@ -0,0 +1,175 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFlattenableBuffers_DEFINED
#define SkFlattenableBuffers_DEFINED
#include "SkColor.h"
#include "SkPaint.h"
#include "SkPoint.h"
class SkBitmap;
class SkFlattenable;
struct SkIRect;
class SkMatrix;
class SkOrderedReadBuffer;
class SkOrderedWriteBuffer;
class SkPath;
class SkPixelRef;
struct SkRect;
class SkRefCnt;
class SkRegion;
class SkStream;
class SkString;
class SkTypeface;
class SkWStream;
class SkFlattenableReadBuffer {
public:
SkFlattenableReadBuffer();
virtual ~SkFlattenableReadBuffer();
bool isOrderedBinaryBuffer() { return NULL != getOrderedBinaryBuffer(); }
virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() { return NULL; }
enum Flags {
kCrossProcess_Flag = 1 << 0,
kScalarIsFloat_Flag = 1 << 1,
kPtrIs64Bit_Flag = 1 << 2,
};
void setFlags(uint32_t flags) { fFlags = flags; }
uint32_t getFlags() const { return fFlags; }
bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
// primitives
virtual bool readBool() = 0;
virtual SkColor readColor() = 0;
virtual SkFixed readFixed() = 0;
virtual int32_t readInt() = 0;
virtual SkScalar readScalar() = 0;
virtual uint32_t readUInt() = 0;
virtual int32_t read32() = 0;
// strings -- the caller is responsible for freeing the string contents
virtual 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 <typename T> T* readFlattenableT() {
return static_cast<T*>(this->readFlattenable());
}
private:
uint32_t fFlags;
};
///////////////////////////////////////////////////////////////////////////////
class SkFlattenableWriteBuffer {
public:
SkFlattenableWriteBuffer();
virtual ~SkFlattenableWriteBuffer();
virtual bool isOrderedBinaryBuffer() { return false; }
virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() { sk_throw(); return NULL; }
// primitives
virtual void writeByteArray(const void* data, size_t size) = 0;
virtual void writeBool(bool value) = 0;
virtual void writeFixed(SkFixed value) = 0;
virtual void writeScalar(SkScalar value) = 0;
virtual void writeScalarArray(const SkScalar* value, uint32_t count) = 0;
virtual void writeInt(int32_t value) = 0;
virtual void writeIntArray(const int32_t* value, uint32_t count) = 0;
virtual void writeUInt(uint32_t value) = 0;
virtual void write32(int32_t value) = 0; // printf in hex
virtual void writeString(const char* value) = 0;
virtual void writeEncodedString(const void* value, size_t byteLength,
SkPaint::TextEncoding encoding) = 0;
// common data structures
virtual void writeFlattenable(SkFlattenable* flattenable) = 0;
virtual void writeColor(const SkColor& color) = 0;
virtual void writeColorArray(const SkColor* color, uint32_t count) = 0;
virtual void writePoint(const SkPoint& point) = 0;
virtual void writePointArray(const SkPoint* points, uint32_t count) = 0;
virtual void writeMatrix(const SkMatrix& matrix) = 0;
virtual void writeIRect(const SkIRect& rect) = 0;
virtual void writeRect(const SkRect& rect) = 0;
virtual void writeRegion(const SkRegion& region) = 0;
virtual void writePath(const SkPath& path) = 0;
virtual size_t writeStream(SkStream* stream, size_t length) = 0;
// helper functions
virtual void writeFunctionPtr(void* ptr);
virtual void writePaint(const SkPaint& paint);
virtual void writeBitmap(const SkBitmap& bitmap) = 0;
virtual void writeTypeface(SkTypeface* typeface) = 0;
virtual bool writeToStream(SkWStream*) = 0;
enum Flags {
kCrossProcess_Flag = 0x01,
};
uint32_t getFlags() const { return fFlags; }
void setFlags(uint32_t flags) { fFlags = flags; }
bool isCrossProcess() const {
return SkToBool(fFlags & kCrossProcess_Flag);
}
bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
protected:
// A helper function so that each subclass does not have to be a friend of SkFlattenable
void flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer);
uint32_t fFlags;
};
#endif

View File

@ -127,7 +127,12 @@ static inline int32_t SkFloatToIntCeil(float x) {
// Scalar wrappers for float-bit routines
#define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x)
#define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x)
#ifdef SK_SCALAR_IS_FLOAT
#define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x)
#define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x)
#else
#define SkScalarAs2sCompliment(x) (x)
#define Sk2sComplimentAsScalar(x) (x)
#endif
#endif

View File

@ -77,8 +77,6 @@ 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)
@ -96,45 +94,4 @@ extern const uint32_t gIEEENegativeInfinity;
#define SK_FloatNaN (*SkTCast<const float*>(&gIEEENotANumber))
#define SK_FloatInfinity (*SkTCast<const float*>(&gIEEEInfinity))
#define SK_FloatNegativeInfinity (*SkTCast<const float*>(&gIEEENegativeInfinity))
#if defined(__SSE__)
#include <xmmintrin.h>
#elif defined(__ARM_NEON__)
#include <arm_neon.h>
#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<int*>(&x);
i = 0x5f3759df - (i>>1);
float estimate = *SkTCast<float*>(&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

View File

@ -72,12 +72,6 @@ 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
@ -212,96 +206,4 @@ 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<kPointCount, SkPoint> fStorage;
int fQuadCount; // #quads for current usage
};
#endif

View File

@ -53,25 +53,6 @@ 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
@ -79,10 +60,6 @@ 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:

View File

@ -0,0 +1,100 @@
/*
* 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

View File

@ -0,0 +1,171 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef 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

View File

@ -0,0 +1,39 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImageTypes_DEFINED
#define SkImageTypes_DEFINED
#include "SkTypes.h"
enum SkColorType {
kAlpha_8_SkColorType,
kRGB_565_SkColorType,
// kRGBA_8888_SkColorType,
// kBGRA_8888_SkColorType,
kPMColor_SkColorType,
kLastEnum_SkColorType = kPMColor_SkColorType
};
enum SkAlphaType {
// kIgnore_SkAlphaType,
kOpaque_SkAlphaType,
// kUnpremul_SkAlphaType,
kPremul_SkAlphaType,
kLastEnum_SkAlphaType = kPremul_SkAlphaType
};
struct SkImageInfo {
int fWidth;
int fHeight;
SkColorType fColorType;
SkAlphaType fAlphaType;
};
#endif

View File

@ -14,74 +14,62 @@
* 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
// 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"
#include "SkThread_platform.h"
extern bool gPrintInstCount;
// The non-root classes just register themselves with their parent
#define SK_DECLARE_INST_COUNT(className) \
SK_DECLARE_INST_COUNT_INTERNAL(className, \
INHERITED::AddInstChild(CheckInstanceCount);)
INHERITED::AddInstChild(CheckInstanceCount);,\
/**/)
#define SK_DECLARE_INST_COUNT_TEMPLATE(className) \
SK_DECLARE_INST_COUNT_INTERNAL(className, \
INHERITED::AddInstChild(CheckInstanceCount);, \
typename)
// The root classes registers a function to print out the memory stats when
// the app ends
#define SK_DECLARE_INST_COUNT_ROOT(className) \
SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/)
#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \
#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \
class SkInstanceCountHelper { \
public: \
typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \
SkInstanceCountHelper() { \
SK_DECLARE_STATIC_ONCE(once); \
SkOnce(&once, init, 0); \
sk_atomic_inc(GetInstanceCountPtr()); \
} \
\
static void init(int) { \
initStep \
if (!gInited) { \
initStep \
gChildren = new SkTArray<PFCheckInstCnt>; \
gInited = true; \
} \
sk_atomic_inc(&gInstanceCount); \
} \
\
SkInstanceCountHelper(const SkInstanceCountHelper&) { \
sk_atomic_inc(GetInstanceCountPtr()); \
sk_atomic_inc(&gInstanceCount); \
} \
\
~SkInstanceCountHelper() { \
sk_atomic_dec(GetInstanceCountPtr()); \
} \
\
static int32_t* GetInstanceCountPtr() { \
static int32_t gInstanceCount; \
return &gInstanceCount; \
} \
\
static SkTArray<int (*)(int, bool)>*& GetChildren() { \
static SkTArray<int (*)(int, bool)>* gChildren; \
return gChildren; \
} \
\
static SkBaseMutex& GetChildrenMutex() { \
SK_DECLARE_STATIC_MUTEX(childrenMutex); \
return childrenMutex; \
sk_atomic_dec(&gInstanceCount); \
} \
\
static int32_t gInstanceCount; \
static bool gInited; \
static SkTArray<PFCheckInstCnt>* gChildren; \
} fInstanceCountHelper; \
\
static int32_t GetInstanceCount() { \
return *SkInstanceCountHelper::GetInstanceCountPtr(); \
return SkInstanceCountHelper::gInstanceCount; \
} \
\
static void exitPrint() { \
@ -89,54 +77,57 @@ extern bool gPrintInstCount;
} \
\
static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \
if (gPrintInstCount && 0 != GetInstanceCount()) { \
if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
SkDebugf("%*c Leaked %s: %d\n", \
4*level, ' ', #className, \
GetInstanceCount()); \
SkInstanceCountHelper::gInstanceCount); \
} \
if (NULL == SkInstanceCountHelper::GetChildren()) { \
return GetInstanceCount(); \
if (NULL == SkInstanceCountHelper::gChildren) { \
return SkInstanceCountHelper::gInstanceCount; \
} \
SkTArray<int (*)(int, bool)>* children = \
SkInstanceCountHelper::GetChildren(); \
int childCount = children->count(); \
int count = GetInstanceCount(); \
int childCount = SkInstanceCountHelper::gChildren->count(); \
int count = SkInstanceCountHelper::gInstanceCount; \
for (int i = 0; i < childCount; ++i) { \
count -= (*(*children)[i])(level+1, cleanUp); \
count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \
} \
SkASSERT(count >= 0); \
if (gPrintInstCount && childCount > 0 && count > 0) { \
SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \
} \
if (cleanUp) { \
delete children; \
SkInstanceCountHelper::GetChildren() = NULL; \
delete SkInstanceCountHelper::gChildren; \
SkInstanceCountHelper::gChildren = NULL; \
} \
return GetInstanceCount(); \
return SkInstanceCountHelper::gInstanceCount; \
} \
\
static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \
if (CheckInstanceCount != childCheckInstCnt) { \
SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \
if (NULL == SkInstanceCountHelper::GetChildren()) { \
SkInstanceCountHelper::GetChildren() = \
new SkTArray<int (*)(int, bool)>; \
} \
SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \
static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \
childCheckInstCnt) { \
if (CheckInstanceCount != childCheckInstCnt && \
NULL != SkInstanceCountHelper::gChildren) { \
SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \
} \
}
#else
// 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
#define SK_DEFINE_INST_COUNT(className) \
int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \
bool className::SkInstanceCountHelper::gInited = false; \
SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>* \
className::SkInstanceCountHelper::gChildren = NULL;
// 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_TEMPLATE(templateInfo, className) \
templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\
templateInfo bool className::SkInstanceCountHelper::gInited = false; \
templateInfo \
SkTArray<typename className::SkInstanceCountHelper::PFCheckInstCnt>*\
className::SkInstanceCountHelper::gChildren = NULL;
#else
#define SK_DECLARE_INST_COUNT(className)
#define SK_DECLARE_INST_COUNT_TEMPLATE(className)
#define SK_DECLARE_INST_COUNT_ROOT(className)
#define SK_DEFINE_INST_COUNT(className)
#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
#endif
#endif // SkInstCnt_DEFINED

View File

@ -0,0 +1,51 @@
/*
* Copyright 2008 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkMallocPixelRef_DEFINED
#define SkMallocPixelRef_DEFINED
#include "SkPixelRef.h"
/** We explicitly use the same allocator for our pixels that SkMask does,
so that we can freely assign memory allocated by one class to the other.
*/
class SkMallocPixelRef : public SkPixelRef {
public:
/** Allocate the specified buffer for pixels. The memory is freed when the
last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw()
is called to allocate it.
*/
SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable, bool ownPixels = true);
virtual ~SkMallocPixelRef();
//! Return the allocation size for the pixels
size_t getSize() const { return fSize; }
void* getAddr() const { return fStorage; }
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMallocPixelRef)
protected:
// overrides from SkPixelRef
virtual void* onLockPixels(SkColorTable**);
virtual void onUnlockPixels();
SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:
void* fStorage;
size_t fSize;
SkColorTable* fCTable;
bool fOwnPixels;
typedef SkPixelRef INHERITED;
};
#endif

View File

@ -99,19 +99,6 @@ 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
@ -157,6 +144,5 @@ public:
private:
uint8_t* fImage;
};
#define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage)
#endif

View File

@ -14,16 +14,11 @@
#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
@ -63,61 +58,27 @@ public:
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
SkIPoint* margin) const;
#if SK_SUPPORT_GPU
/**
* Returns true if the filter can be expressed a single-pass GrEffect 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;
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 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).
* 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.
*/
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
virtual BlurType asABlur(BlurInfo*) const;
/**
* The fast bounds function is used to enable the paint to be culled early
@ -133,11 +94,10 @@ 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(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkMaskFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
enum FilterReturn {
kFalse_FilterReturn,
@ -170,12 +130,6 @@ 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;
@ -189,14 +143,6 @@ 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;
};

View File

@ -35,58 +35,17 @@ 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);
#ifndef SkCLZ
#if defined(_MSC_VER) && _MSC_VER >= 1400
#include <intrin.h>
#if defined(SK_CPU_ARM)
#define SkCLZ(x) __builtin_clz(x)
#endif
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
#ifndef SkCLZ
#define SkCLZ(x) SkCLZ_portable(x)
#endif
/**
@ -180,7 +139,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(U16CPU a, U16CPU b, int shift) {
static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) {
SkASSERT(a <= 32767);
SkASSERT(b <= 32767);
SkASSERT(shift > 0 && shift <= 8);
@ -189,36 +148,14 @@ static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) {
}
/**
* Return a*b/255, rounding any fractional bits.
* Only valid if a and b are unsigned and <= 32767.
* Return a*b/255, rounding any fractional bits. Only valid if both
* a and b are 0..255
*/
static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {
SkASSERT(a <= 32767);
SkASSERT(b <= 32767);
static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) {
SkASSERT((uint8_t)a == a);
SkASSERT((uint8_t)b == b);
unsigned prod = SkMulS16(a, b) + 128;
return (prod + (prod >> 8)) >> 8;
}
/**
* Stores numer/denom and numer%denom into div and mod respectively.
*/
template <typename In, typename Out>
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<Out>(d);
*mod = static_cast<Out>(numer-d*denom);
#else
// On x86 this will just be a single idiv.
*div = static_cast<Out>(numer/denom);
*mod = static_cast<Out>(numer%denom);
#endif // SK_CPU_ARM
}
#endif

View File

@ -14,10 +14,15 @@
class SkString;
// TODO: can we remove these 3 (need to check chrome/android)
typedef SkScalar SkPersp;
#define SkScalarToPersp(x) (x)
#define SkPerspToScalar(x) (x)
#ifdef SK_SCALAR_IS_FLOAT
typedef SkScalar SkPersp;
#define SkScalarToPersp(x) (x)
#define SkPerspToScalar(x) (x)
#else
typedef SkFract SkPersp;
#define SkScalarToPersp(x) SkFixedToFract(x)
#define SkPerspToScalar(x) SkFractToFixed(x)
#endif
/** \class SkMatrix
@ -85,12 +90,6 @@ 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,
@ -418,19 +417,6 @@ 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);
@ -478,18 +464,6 @@ 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.
@ -538,7 +512,13 @@ 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);
}
@ -548,28 +528,13 @@ public:
kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
};
// return the number of bytes written, whether or not buffer is null
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);
uint32_t writeToMemory(void* buffer) const;
// return the number of bytes read
uint32_t readFromMemory(const void* buffer);
SkDEVCODE(void dump() const;)
SkDEVCODE(void toString(SkString*) const;)
/**
* Calculates the 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.

View File

@ -48,35 +48,9 @@ char* sk_fgets(char* str, int size, SkFILE* f);
void sk_fflush(SkFILE*);
bool sk_fseek(SkFILE*, size_t);
bool sk_fmove(SkFILE*, long);
int sk_fseek(SkFILE*, size_t, int);
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);
@ -131,29 +105,4 @@ 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

View File

@ -13,24 +13,21 @@
#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 SkReadBuffer;
class SkWriteBuffer;
class SkFlattenableReadBuffer;
class SkFlattenableWriteBuffer;
struct SkGlyph;
struct SkRect;
class SkGlyphCache;
class SkImageFilter;
class SkMaskFilter;
class SkMatrix;
class SkPath;
class SkPathEffect;
struct SkPoint;
@ -43,23 +40,12 @@ 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);
@ -72,8 +58,8 @@ public:
return !(a == b);
}
void flatten(SkWriteBuffer&) const;
void unflatten(SkReadBuffer&);
void flatten(SkFlattenableWriteBuffer&) const;
void unflatten(SkFlattenableReadBuffer&);
/** Restores the paint to its initial settings.
*/
@ -106,6 +92,7 @@ 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
@ -118,10 +105,11 @@ 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 = 0xFFFF
kAllFlags = 0x3FFF
};
/** Return the paint's flags. Use the Flag enum to test flag values.
@ -284,42 +272,12 @@ public:
*/
void setDevKernText(bool devKernText);
enum FilterLevel {
kNone_FilterLevel,
kLow_FilterLevel,
kMedium_FilterLevel,
kHigh_FilterLevel
};
/**
* Return the filter level. This affects the quality (and performance) of
* drawing scaled images.
*/
FilterLevel getFilterLevel() const;
/**
* Set the filter level. This affects the quality (and performance) of
* drawing scaled images.
*/
void setFilterLevel(FilterLevel);
/**
* 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);
}
/**
* Returns true if getFilterLevel() returns anything other than None.
*/
SK_ATTR_DEPRECATED("use getFilterLevel")
bool isFilterBitmap() const {
return kNone_FilterLevel != this->getFilterLevel();
return SkToBool(this->getFlags() & kFilterBitmap_Flag);
}
void setFilterBitmap(bool filterBitmap);
/** Styles apply to rect, oval, path, and text.
Bitmaps are always drawn in "fill", and lines are always drawn in
"stroke".
@ -639,8 +597,9 @@ public:
* Returns true if there is an annotation installed on this paint, and
* the annotation specifics no-drawing.
*/
SK_ATTR_DEPRECATED("use getAnnotation and check for non-null")
bool isNoDrawAnnotation() const { return this->getAnnotation() != NULL; }
bool isNoDrawAnnotation() const {
return SkToBool(fPrivFlags & kNoDrawAnnotation_PrivFlag);
}
/**
* Return the paint's SkDrawLooper (if any). Does not affect the looper's
@ -665,9 +624,8 @@ public:
kLeft_Align,
kCenter_Align,
kRight_Align,
};
enum {
kAlignCount = 3
kAlignCount
};
/** Return the paint's Align value for drawing text.
@ -716,6 +674,20 @@ 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().
*/
@ -737,11 +709,9 @@ 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 fCapHeight; //!< The cap height (> 0), or 0 if cannot be determined.
SkScalar fXHeight; //!< the height of an 'x' in px, or 0 if no 'x' in face
};
/** Return the recommend spacing between lines (which will be
@ -890,11 +860,6 @@ 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
@ -943,7 +908,6 @@ public:
uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
if (!effects) {
return orig;
}
@ -962,22 +926,6 @@ 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:
@ -985,6 +933,9 @@ private:
SkScalar fTextSize;
SkScalar fTextScaleX;
SkScalar fTextSkewX;
#ifdef SK_SUPPORT_HINTING_SCALE_FACTOR
SkScalar fHintingScaleFactor;
#endif
SkPathEffect* fPathEffect;
SkShader* fShader;
@ -1007,8 +958,11 @@ private:
unsigned fStyle : 2;
unsigned fTextEncoding : 2; // 3 values
unsigned fHinting : 2;
//unsigned fFreeBits : 4;
unsigned fPrivFlags : 4; // these are not flattened/unflattened
enum PrivFlags {
kNoDrawAnnotation_PrivFlag = 1 << 0,
};
SkDrawCacheProc getDrawCacheProc() const;
SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir,
@ -1026,59 +980,16 @@ private:
static void Term();
enum {
/* This is the size we use when we ask for a glyph's path. We then
* post-transform it as we draw to match the request.
* This is done to try to re-use cache entries for the path.
*
* This value is somewhat arbitrary. In theory, it could be 1, since
* we store paths as floats. However, we get the path from the font
* scaler, and it may represent its paths as fixed-point (or 26.6),
* so we shouldn't ask for something too big (might overflow 16.16)
* or too small (underflow 26.6).
*
* This value could track kMaxSizeForGlyphCache, assuming the above
* constraints, but since we ask for unhinted paths, the two values
* need not match per-se.
*/
kCanonicalTextSizeForPaths = 64,
/*
* Above this size (taking into account CTM and textSize), we never use
* the cache for bits or metrics (we might overflow), so we just ask
* for a caononical size and post-transform that.
*/
kMaxSizeForGlyphCache = 256,
kCanonicalTextSizeForPaths = 64
};
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;

View File

@ -12,16 +12,28 @@
#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
@ -36,6 +48,7 @@ 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);
@ -72,6 +85,7 @@ public:
*/
void setFillType(FillType ft) {
fFillType = SkToU8(ft);
GEN_ID_INC;
}
/** Returns true if the filltype is one of the Inverse variants */
@ -83,7 +97,8 @@ public:
*/
void toggleInverseFillType() {
fFillType ^= 2;
}
GEN_ID_INC;
}
enum Convexity {
kUnknown_Convexity,
@ -123,6 +138,7 @@ 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.
*/
@ -131,12 +147,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);
}
@ -151,18 +167,18 @@ public:
* optimization for performance and so some paths that are in
* fact ovals can report false.
*/
bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
bool isOval(SkRect* rect) const;
/** Clear any lines and curves from the path, making it empty. This frees up
internal storage associated with those segments.
On Android, does not change fSourcePath.
This does NOT change the fill-type setting nor isConvex
*/
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.
On Android, does not change fSourcePath.
This does NOT change the fill-type setting nor isConvex
*/
void rewind();
@ -170,18 +186,17 @@ public:
@return true if the path is empty (contains no lines or curves)
*/
bool isEmpty() const {
SkDEBUGCODE(this->validate();)
return 0 == fPathRef->countVerbs();
}
bool isEmpty() const;
/**
* Returns true if all of the points in this path are finite, meaning there
* are no infinities and no NaNs.
*/
bool isFinite() const {
SkDEBUGCODE(this->validate();)
return fPathRef->isFinite();
if (fBoundsIsDirty) {
this->computeBounds();
}
return SkToBool(fIsFinite);
}
/** Test a line for zero length
@ -231,6 +246,16 @@ 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;
@ -271,7 +296,10 @@ public:
do not extend as far as their control points.
*/
const SkRect& getBounds() const {
return fPathRef->getBounds();
if (fBoundsIsDirty) {
this->computeBounds();
}
return fBounds;
}
/** Calling this will, if the internal cache of the bounds is out of date,
@ -395,14 +423,6 @@ 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).
@ -446,8 +466,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
@ -461,8 +481,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".
@ -555,25 +575,6 @@ 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
@ -585,26 +586,13 @@ 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
@ -663,8 +651,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
@ -702,41 +690,25 @@ 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,
AddPathMode mode = kAppend_AddPathMode);
void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
/** Add a copy of src to the path
*/
void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
void addPath(const SkPath& src) {
SkMatrix m;
m.reset();
this->addPath(src, m, mode);
this->addPath(src, m);
}
/** Add a copy of src to the path, transformed by matrix
@param src The path to add as a new contour
@param matrix Transform applied to src
@param mode Determines how path is added
*/
void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
void addPath(const SkPath& src, const SkMatrix& matrix);
/**
* Same as addPath(), but reverses the src input
@ -804,8 +776,7 @@ public:
enum SegmentMask {
kLine_SegmentMask = 1 << 0,
kQuad_SegmentMask = 1 << 1,
kConic_SegmentMask = 1 << 2,
kCubic_SegmentMask = 1 << 3,
kCubic_SegmentMask = 1 << 2
};
/**
@ -813,16 +784,15 @@ 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 fPathRef->getSegmentMasks(); }
uint32_t getSegmentMasks() const { return fSegmentMask; }
enum Verb {
kMove_Verb, //!< iter.next returns 1 point
kLine_Verb, //!< iter.next returns 2 points
kQuad_Verb, //!< iter.next returns 3 points
kConic_Verb, //!< iter.next returns 3 points + iter.conicWeight()
kCubic_Verb, //!< iter.next returns 4 points
kClose_Verb, //!< iter.next returns 1 point (contour's moveTo pt)
kDone_Verb, //!< iter.next returns 0 points
kDone_Verb //!< iter.next returns 0 points
};
/** Iterate through all of the segments (lines, quadratics, cubics) of
@ -856,12 +826,6 @@ 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
@ -881,7 +845,6 @@ public:
const SkPoint* fPts;
const uint8_t* fVerbs;
const uint8_t* fVerbStop;
const SkScalar* fConicWeights;
SkPoint fMoveTo;
SkPoint fLastPt;
SkBool8 fForceClose;
@ -913,13 +876,10 @@ 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;
};
@ -934,73 +894,84 @@ public:
void dump() const;
/**
* Write the path to the buffer, and return the number of bytes written.
* Write the region to the buffer, and return the number of bytes written.
* If buffer is NULL, it still returns the number of bytes.
*/
size_t writeToMemory(void* buffer) const;
uint32_t writeToMemory(void* buffer) const;
/**
* 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
* Initialized the region from the buffer, returning the number
* of bytes actually read.
*/
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;
uint32_t readFromMemory(const void* buffer);
#ifdef SK_BUILD_FOR_ANDROID
static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762)
uint32_t getGenerationID() const;
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
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
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
};
SkAutoTUnref<SkPathRef> fPathRef;
#if SK_DEBUG_PATH_REF
public:
/** Debugging wrapper for SkAutoTUnref<SkPathRef> 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<SkPathRef>::BlockRefType *operator->() const;
operator SkPathRef*();
private:
SkAutoTUnref<SkPathRef> fPathRef;
SkPath* fOwner;
};
private:
PathRefDebugRef fPathRef;
#else
SkAutoTUnref<SkPathRef> 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
/** Resets all fields other than fPathRef to their initial 'empty' values.
* Assumes the caller has already emptied fPathRef.
* On Android increments fGenerationID without reseting it.
*/
void resetFields();
/** Sets all fields other than fPathRef to the values in 'that'.
* Assumes the caller has already set fPathRef.
* Doesn't change fGenerationID or fSourcePath on Android.
*/
void copyFields(const SkPath& that);
// called, if dirty, by getBounds()
void computeBounds() const;
friend class Iter;
friend class SkPathStroker;
/* Append the first contour of path, ignoring path's initial point. If no
moveTo() call has been made for this contour, the first point is
automatically set to (0,0).
*/
void pathTo(const SkPath& path);
/* Append, in reverse order, the first contour of path, ignoring path's
last point. If no moveTo() call has been made for this contour, the
@ -1023,27 +994,10 @@ 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 reversePathTo
friend class PathTest_Private; // unit test reversePathTo
friend class SkBench_AddPathTest; // perf test pathTo/reversePathTo
};
#endif

View File

@ -106,10 +106,8 @@ public:
const SkStrokeRec&, const SkMatrix&,
const SkRect* cullR) const;
SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect)
protected:
SkPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
// illegal
@ -131,8 +129,8 @@ public:
virtual ~SkPairPathEffect();
protected:
SkPairPathEffect(SkReadBuffer&);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkPairPathEffect(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
// these are visible to our subclasses
SkPathEffect* fPE0, *fPE1;
@ -162,7 +160,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
protected:
SkComposePathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkComposePathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
// illegal
@ -193,7 +191,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
protected:
SkSumPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkSumPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
// illegal

View File

@ -1,3 +1,4 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -5,13 +6,14 @@
* found in the LICENSE file.
*/
#ifndef SkPathMeasure_DEFINED
#define SkPathMeasure_DEFINED
#include "SkPath.h"
#include "SkTDArray.h"
class SK_API SkPathMeasure : SkNoncopyable {
class SkPathMeasure : SkNoncopyable {
public:
SkPathMeasure();
/** Initialize the pathmeasure with the specified path. The path must remain valid

View File

@ -11,20 +11,15 @@
#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
@ -44,6 +39,13 @@ 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.
@ -60,23 +62,12 @@ 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.
*/
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&);
SkPicture(SkStream*, bool* success, InstallPixelRefProc proc);
virtual ~SkPicture();
@ -124,16 +115,7 @@ 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,
/*
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
kOptimizeForClippedPlayback_RecordingFlag = 0x02
};
/** Returns the canvas that records the drawing commands.
@ -159,9 +141,9 @@ public:
/** Replays the drawing commands on the specified canvas. This internally
calls endRecording() if that has not already been called.
@param canvas the canvas receiving the drawing commands.
@param surface the canvas receiving the drawing commands.
*/
void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL);
void draw(SkCanvas* surface);
/** Return the width of the picture's recording canvas. This
value reflects what was passed to setSize(), and does not necessarily
@ -178,36 +160,20 @@ public:
int height() const { return fHeight; }
/**
* 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().
* 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.
*/
typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm);
typedef bool (*EncodeBitmap)(SkWStream*, const SkBitmap&);
/**
* 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
@ -228,18 +194,7 @@ 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
// 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;
static const uint32_t PICTURE_VERSION = 10;
// fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
@ -248,22 +203,12 @@ 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 createHeader(void* header) const;
void initFromStream(SkStream*, bool* success, InstallPixelRefProc);
friend class SkFlatPicture;
friend class SkPicturePlayback;
@ -271,22 +216,25 @@ private:
typedef SkRefCnt INHERITED;
};
/**
* 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 {
class SkAutoPictureRecord : SkNoncopyable {
public:
SkDrawPictureCallback() {}
virtual ~SkDrawPictureCallback() {}
SkAutoPictureRecord(SkPicture* pict, int width, int height,
uint32_t recordingFlags = 0) {
fPicture = pict;
fCanvas = pict->beginRecording(width, height, recordingFlags);
}
~SkAutoPictureRecord() {
fPicture->endRecording();
}
virtual bool abortDrawing() = 0;
/** Return the canvas to draw into for recording into the picture.
*/
SkCanvas* getRecordingCanvas() const { return fCanvas; }
private:
SkPicture* fPicture;
SkCanvas* fCanvas;
};
#endif

View File

@ -1,3 +1,4 @@
/*
* Copyright 2008 The Android Open Source Project
*
@ -5,6 +6,7 @@
* found in the LICENSE file.
*/
#ifndef SkPixelRef_DEFINED
#define SkPixelRef_DEFINED
@ -12,10 +14,6 @@
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkFlattenable.h"
#include "SkImageInfo.h"
#include "SkTDArray.h"
//#define xed
#ifdef SK_DEBUG
/**
@ -36,7 +34,8 @@ class SkData;
struct SkIRect;
class SkMutex;
class GrTexture;
// this is an opaque class, not interpreted by skia
class SkGpuTexture;
/** \class SkPixelRef
@ -50,40 +49,16 @@ class SK_API SkPixelRef : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkPixelRef)
explicit SkPixelRef(const SkImageInfo&);
SkPixelRef(const SkImageInfo&, SkBaseMutex* mutex);
virtual ~SkPixelRef();
const SkImageInfo& info() const {
return fInfo;
}
explicit SkPixelRef(SkBaseMutex* mutex = NULL);
/** Return the pixel memory returned from lockPixels, or null if the
lockCount is 0.
*/
void* pixels() const { return fRec.fPixels; }
void* pixels() const { return fPixels; }
/** Return the current colorTable (if any) if pixels are locked, or null.
*/
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;
}
};
SkColorTable* colorTable() const { return fColorTable; }
/**
* Returns true if the lockcount > 0
@ -92,19 +67,10 @@ public:
SkDEBUGCODE(int getLockCount() const { return fLockCount; })
/**
* 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 access the pixel memory, which is returned. Balance with a call
to unlockPixels().
*/
void lockPixels();
/** Call to balanace a previous call to lockPixels(). Returns the pixels
(or null) after the unlock. NOTE: lock calls can be nested, but the
matching number of unlock calls must be made in order to free the
@ -126,20 +92,12 @@ 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.
*/
@ -184,40 +142,9 @@ 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 GrTexture* getTexture() { return NULL; }
virtual SkGpuTexture* getTexture() { return NULL; }
bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
@ -250,52 +177,20 @@ 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:
/**
* 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.
*/
/** Called when the lockCount goes from 0 to 1. The caller will have already
acquire a mutex for thread safety, so this method need not do that.
*/
virtual void* onLockPixels(SkColorTable**) = 0;
/** Called when the lock count goes from 1 to 0. The caller will have
already acquire a mutex for thread safety, so this method need not do
that.
*/
virtual void onUnlockPixels() = 0;
/** Default impl returns true */
virtual bool onLockPixelsAreWritable() const;
// 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).
@ -307,44 +202,32 @@ 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(SkReadBuffer&, SkBaseMutex*);
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
// only call from constructor. Flags this to always be locked, removing
// the need to grab the mutex and call onLockPixels/onUnlockPixels.
// Performance tweak to avoid those calls (esp. in multi-thread use case).
void setPreLocked(void*, size_t rowBytes, SkColorTable*);
void setPreLocked(void* pixels, SkColorTable* ctable);
private:
SkBaseMutex* fMutex; // must remain in scope for the life of this object
// 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;
void* fPixels;
SkColorTable* fColorTable; // we do not track ownership, subclass does
int fLockCount;
mutable uint32_t fGenerationID;
mutable bool fUniqueGenerationID;
SkTDArray<GenIDChangeListener*> fGenIDChangeListeners; // pointers are owned
// SkBitmap is only a friend so that when copying, it can modify the new SkPixelRef to have the
// same fGenerationID as the original.
friend class SkBitmap;
SkString fURI;
@ -353,28 +236,9 @@ 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

View File

@ -216,10 +216,13 @@ 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) {
// Simple enough (and performance critical sometimes) so we inline it.
return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
}
static bool CanNormalize(SkScalar dx, SkScalar dy)
#ifdef SK_SCALAR_IS_FLOAT
// Simple enough (and performance critical sometimes) so we inline it.
{ return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero); }
#else
;
#endif
bool canNormalize() const {
return CanNormalize(fX, fY);
@ -249,14 +252,6 @@ 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.
*/
@ -321,6 +316,7 @@ 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;
@ -331,6 +327,12 @@ 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
}
/**
@ -351,7 +353,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 explicit tolerance version,
WARNING: Unlike the deprecated version of equalsWithinTolerance(),
this method does not use componentwise comparison. Instead, it
uses a comparison designed to match judgments elsewhere regarding
degeneracy ("points A and B are so close that the vector between them
@ -361,7 +363,10 @@ struct SK_API SkPoint {
return !CanNormalize(fX - p.fX, fY - p.fY);
}
/** WARNING: There is no guarantee that the result will reflect judgments
/** DEPRECATED: Return true if this and the given point are componentwise
within tolerance "tol".
WARNING: There is no guarantee that the result will reflect judgments
elsewhere regarding degeneracy ("points A and B are so close that the
vector between them is essentially zero").
*/
@ -411,13 +416,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 a.fX * b.fX + a.fY * b.fY;
return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
}
/** Returns the cross product of a and b, treating them as 2D vectors
*/
static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
return a.fX * b.fY - a.fY * b.fX;
return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
}
SkScalar cross(const SkPoint& vec) const {
@ -435,7 +440,7 @@ struct SK_API SkPoint {
SkScalar distanceToSqd(const SkPoint& pt) const {
SkScalar dx = fX - pt.fX;
SkScalar dy = fY - pt.fY;
return dx * dx + dy * dy;
return SkScalarMul(dx, dx) + SkScalarMul(dy, dy);
}
/**

View File

@ -0,0 +1,363 @@
/*
* 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 <windows.h>
#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 <stdio.h>
#ifndef SK_DEBUGBREAK
#define SK_DEBUGBREAK(cond) do { if (cond) break; \
SkDebugf("%s:%d: failed assertion \"%s\"\n", \
__FILE__, __LINE__, #cond); SK_CRASH(); } while (false)
#endif
#endif
#endif
/*
* We check to see if the SHIFT value has already been defined.
* if not, we define it ourself to some default values. We default to OpenGL
* order (in memory: r,g,b,a)
*/
#ifndef SK_A32_SHIFT
#ifdef SK_CPU_BENDIAN
#define SK_R32_SHIFT 24
#define SK_G32_SHIFT 16
#define SK_B32_SHIFT 8
#define SK_A32_SHIFT 0
#else
#define SK_R32_SHIFT 0
#define SK_G32_SHIFT 8
#define SK_B32_SHIFT 16
#define SK_A32_SHIFT 24
#endif
#endif
/**
* SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
* relationship between the byte order and shift values depends on machine endianness. If the shift
* order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
* endian machine and the A channel on a big endian machine. Thus, given those shifts values,
* SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
* SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
*/
#ifdef SK_CPU_BENDIAN
#define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
(SK_ ## C3 ## 32_SHIFT == 0 && \
SK_ ## C2 ## 32_SHIFT == 8 && \
SK_ ## C1 ## 32_SHIFT == 16 && \
SK_ ## C0 ## 32_SHIFT == 24)
#else
#define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
(SK_ ## C0 ## 32_SHIFT == 0 && \
SK_ ## C1 ## 32_SHIFT == 8 && \
SK_ ## C2 ## 32_SHIFT == 16 && \
SK_ ## C3 ## 32_SHIFT == 24)
#endif
// stdlib macros
#if 0
#if !defined(strlen) && defined(SK_DEBUG)
extern size_t sk_strlen(const char*);
#define strlen(s) sk_strlen(s)
#endif
#ifndef sk_strcpy
#define sk_strcpy(dst, src) strcpy(dst, src)
#endif
#ifndef sk_strchr
#define sk_strchr(s, c) strchr(s, c)
#endif
#ifndef sk_strrchr
#define sk_strrchr(s, c) strrchr(s, c)
#endif
#ifndef sk_strcmp
#define sk_strcmp(s, t) strcmp(s, t)
#endif
#ifndef sk_strncmp
#define sk_strncmp(s, t, n) strncmp(s, t, n)
#endif
#ifndef sk_memcpy
#define sk_memcpy(dst, src, n) memcpy(dst, src, n)
#endif
#ifndef memmove
#define memmove(dst, src, n) memmove(dst, src, n)
#endif
#ifndef sk_memset
#define sk_memset(dst, val, n) memset(dst, val, n)
#endif
#ifndef sk_memcmp
#define sk_memcmp(s, t, n) memcmp(s, t, n)
#endif
#define sk_strequal(s, t) (!sk_strcmp(s, t))
#define sk_strnequal(s, t, n) (!sk_strncmp(s, t, n))
#endif
//////////////////////////////////////////////////////////////////////
#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC)
#ifndef SkLONGLONG
#ifdef SK_BUILD_FOR_WIN32
#define SkLONGLONG __int64
#else
#define SkLONGLONG long long
#endif
#endif
#endif
//////////////////////////////////////////////////////////////////////////////////////////////
#ifndef SK_BUILD_FOR_WINCE
#include <string.h>
#include <stdlib.h>
#else
#define _CMNINTRIN_DECLARE_ONLY
#include "cmnintrin.h"
#endif
#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32
//#define _CRTDBG_MAP_ALLOC
#ifdef free
#undef free
#endif
#include <crtdbg.h>
#undef free
#ifdef SK_DEBUGx
#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)
void * operator new(
size_t cb,
int nBlockUse,
const char * szFileName,
int nLine,
int foo
);
void * operator new[](
size_t cb,
int nBlockUse,
const char * szFileName,
int nLine,
int foo
);
void operator delete(
void *pUserData,
int, const char*, int, int
);
void operator delete(
void *pUserData
);
void operator delete[]( void * p );
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)
#else
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#endif
#define new DEBUG_CLIENTBLOCK
#else
#define DEBUG_CLIENTBLOCK
#endif // _DEBUG
#endif
#endif
//////////////////////////////////////////////////////////////////////
#ifndef SK_OVERRIDE
#if defined(_MSC_VER)
#define SK_OVERRIDE override
#elif defined(__clang__) && !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

View File

@ -14,13 +14,6 @@
#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)
@ -60,6 +53,13 @@
#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,6 +77,7 @@
#if !defined(SK_WARN_UNUSED_RESULT)
#define SK_WARN_UNUSED_RESULT
#endif
#include "sk_stdint.h"
#endif
//////////////////////////////////////////////////////////////////////
@ -91,6 +92,12 @@
//////////////////////////////////////////////////////////////////////
#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__)
@ -102,6 +109,17 @@
//////////////////////////////////////////////////////////////////////
#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
*
@ -127,12 +145,10 @@
// Are we in VisualStudio?
#ifndef SK_CPU_SSE_LEVEL
#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
#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
@ -144,12 +160,6 @@
#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
@ -186,6 +196,16 @@
//////////////////////////////////////////////////////////////////////
/**
* 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

View File

@ -12,7 +12,6 @@
#include "SkPoint.h"
class SkPath;
class SkMatrix;
// Path forward:
// core work
@ -26,7 +25,7 @@ class SkMatrix;
// 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 SkBaseDevice
// add entry points (clipRRect, drawRRect) - plumb down to SkDevice
// update SkPath.addRRect() to take an SkRRect - only use quads
// -- alternatively add addRRectToPath here
// add GM and bench
@ -199,6 +198,30 @@ 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,
@ -228,12 +251,6 @@ 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 {
@ -245,31 +262,14 @@ public:
* write kSizeInMemory bytes, and that value is guaranteed to always be
* a multiple of 4. Return kSizeInMemory.
*/
size_t writeToMemory(void* buffer) const;
uint32_t writeToMemory(void* buffer) const;
/**
* 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
* 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.
*/
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;
uint32_t readFromMemory(const void* buffer);
private:
SkRect fRect;
@ -280,7 +280,6 @@ private:
// uninitialized data
void computeType() const;
bool checkCornerContainment(SkScalar x, SkScalar y) const;
// to access fRadii directly
friend class SkPath;

View File

@ -30,10 +30,8 @@ public:
const SkIRect* clipBounds, SkMaskFilter* filter,
SkMask* mask, SkMask::CreateMode mode) const;
SK_DEFINE_FLATTENABLE_TYPE(SkRasterizer)
protected:
SkRasterizer(SkReadBuffer& buffer) : INHERITED(buffer) {}
SkRasterizer(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix,
const SkIRect* clipBounds,

View File

@ -106,20 +106,27 @@ public:
int32_t readS32() { return this->readInt(); }
uint32_t readU32() { return this->readInt(); }
bool readPath(SkPath* path) {
return readObjectFromMemory(path);
void readPath(SkPath* path) {
size_t size = path->readFromMemory(this->peek());
SkASSERT(SkAlign4(size) == size);
(void)this->skip(size);
}
bool readMatrix(SkMatrix* matrix) {
return readObjectFromMemory(matrix);
void readMatrix(SkMatrix* matrix) {
size_t size = matrix->readFromMemory(this->peek());
SkASSERT(SkAlign4(size) == size);
(void)this->skip(size);
}
bool readRRect(SkRRect* rrect) {
return readObjectFromMemory(rrect);
SkRRect* readRRect(SkRRect* rrect) {
rrect->readFromMemory(this->skip(SkRRect::kSizeInMemory));
return rrect;
}
bool readRegion(SkRegion* rgn) {
return readObjectFromMemory(rgn);
void readRegion(SkRegion* rgn) {
size_t size = rgn->readFromMemory(this->peek());
SkASSERT(SkAlign4(size) == size);
(void)this->skip(size);
}
/**
@ -136,15 +143,6 @@ public:
size_t readIntoString(SkString* copy);
private:
template <typename T> 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

View File

@ -26,12 +26,6 @@ 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);
@ -100,11 +94,6 @@ 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));
}
@ -371,12 +360,6 @@ 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);
@ -401,7 +384,7 @@ struct SK_API SkRect {
return r;
}
SK_ATTR_DEPRECATED("use Make()")
// DEPRECATED: call Make(r)
static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {
SkRect r;
r.set(SkIntToScalar(irect.fLeft),
@ -425,17 +408,13 @@ 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;
@ -448,6 +427,13 @@ 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; }
@ -469,9 +455,8 @@ struct SK_API SkRect {
return !SkScalarsEqual((SkScalar*)&a, (SkScalar*)&b, 4);
}
/** 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.
*/
/** return the 4 points that enclose the rectangle
*/
void toQuad(SkPoint quad[4]) const;
/** Set this rectangle to the empty rectangle (0,0,0,0)
@ -625,7 +610,6 @@ 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
@ -695,19 +679,32 @@ struct SK_API SkRect {
fBottom = SkMaxScalar(y, fBottom);
}
/** Bulk version of growToInclude */
void growToInclude(const SkPoint pts[], int count) {
this->growToInclude(pts, sizeof(SkPoint), count);
/**
* 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 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);
}
/**
* 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;
}
/**
@ -715,7 +712,6 @@ 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;
@ -723,7 +719,7 @@ struct SK_API SkRect {
/**
* Set the dst rectangle by rounding this rectangle's coordinates to their
* nearest integer values using SkScalarRoundToInt.
* nearest integer values using SkScalarRound.
*/
void round(SkIRect* dst) const {
SkASSERT(dst);
@ -765,15 +761,6 @@ 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()

View File

@ -10,14 +10,13 @@
#ifndef SkRefCnt_DEFINED
#define SkRefCnt_DEFINED
#include "SkDynamicAnnotations.h"
#include "SkThread.h"
#include "SkInstCnt.h"
#include "SkTemplates.h"
/** \class SkRefCntBase
/** \class SkRefCnt
SkRefCntBase is the base class for objects that may be shared by multiple
SkRefCnt is the base class for objects that may be shared by multiple
objects. When an existing owner wants to share a reference, it calls ref().
When an owner wants to release its reference, it calls unref(). When the
shared object's reference count goes to zero as the result of an unref()
@ -25,41 +24,27 @@
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 SkRefCntBase : public SkNoncopyable {
class SK_API SkRefCnt : SkNoncopyable {
public:
SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase)
SK_DECLARE_INST_COUNT_ROOT(SkRefCnt)
/** Default construct, initializing the reference count to 1.
*/
SkRefCntBase() : fRefCnt(1) {}
SkRefCnt() : fRefCnt(1) {}
/** Destruct, asserting that the reference count is 1.
*/
virtual ~SkRefCntBase() {
virtual ~SkRefCnt() {
#ifdef SK_DEBUG
SkASSERT(fRefCnt == 1);
fRefCnt = 0; // illegal value, to catch us if we reuse after delete
#endif
}
/** Return the reference count. Use only for debugging. */
/** Return the reference count.
*/
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 {
@ -75,18 +60,26 @@ public:
SkASSERT(fRefCnt > 0);
// Release barrier (SL/S), if not provided below.
if (sk_atomic_dec(&fRefCnt) == 1) {
// Acquire barrier (L/SL), if not provided above.
// Aquire barrier (L/SL), if not provided above.
// Prevents code in dispose from happening before the decrement.
sk_membar_acquire__after_atomic_dec();
sk_membar_aquire__after_atomic_dec();
internal_dispose();
}
}
#ifdef SK_DEBUG
void validate() const {
SkASSERT(fRefCnt > 0);
}
#endif
/**
* Alias for ref(), for compatibility with scoped_refptr.
*/
void AddRef() { this->ref(); }
/**
* Alias for unref(), for compatibility with scoped_refptr.
*/
void Release() { this->unref(); }
protected:
/**
@ -111,24 +104,15 @@ 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
@ -168,13 +152,6 @@ template <typename T> static inline void SkSafeUnref(T* obj) {
}
}
template<typename T> static inline void SkSafeSetNull(T*& obj) {
if (NULL != obj) {
obj->unref();
obj = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
/**
@ -212,13 +189,12 @@ public:
}
/**
* BlockRef<B> is a type which inherits from B, cannot be created,
* cannot be deleted, and makes ref and unref private.
* BlockRef<B> is a type which inherits from B, cannot be created,
* and makes ref and unref private.
*/
template<typename B> class BlockRef : public B {
private:
BlockRef();
~BlockRef();
void ref() const;
void unref() const;
};
@ -240,13 +216,11 @@ public:
private:
T* fObj;
};
// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :(
class SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
public:
SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
};
#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref)
class SkAutoRef : SkNoncopyable {
public:
@ -255,7 +229,6 @@ 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.

View File

@ -85,16 +85,6 @@ 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.
@ -361,16 +351,13 @@ 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.
*/
size_t writeToMemory(void* buffer) const;
uint32_t writeToMemory(void* buffer) const;
/**
* 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
* Initialized the region from the buffer, returning the number
* of bytes actually read.
*/
size_t readFromMemory(const void* buffer, size_t length);
uint32_t readFromMemory(const void* buffer);
/**
* Returns a reference to a global empty region. Just a convenience for

View File

@ -0,0 +1,379 @@
/*
* 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<int>(x)
/** Returns the absolute value of the specified SkScalar
*/
#define SkScalarAbs(x) sk_float_abs(x)
/** Return x with the sign of y
*/
#define SkScalarCopySign(x, y) sk_float_copysign(x, y)
/** Returns the value pinned between 0 and max inclusive
*/
inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
return x < 0 ? 0 : x > max ? max : x;
}
/** Returns the value pinned between min and max inclusive
*/
inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
return x < min ? min : x > max ? max : x;
}
/** Returns the specified SkScalar squared (x*x)
*/
inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
/** Returns the product of two SkScalars
*/
#define SkScalarMul(a, b) ((float)(a) * (b))
/** Returns the product of two SkScalars plus a third SkScalar
*/
#define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c))
/** Returns the product of a SkScalar and an int rounded to the nearest integer value
*/
#define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b))
/** Returns the product of a SkScalar and an int promoted to the next larger int
*/
#define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b))
/** Returns the product of a SkScalar and an int truncated to the next smaller int
*/
#define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b))
/** Returns the quotient of two SkScalars (a/b)
*/
#define SkScalarDiv(a, b) ((float)(a) / (b))
/** Returns the mod of two SkScalars (a mod b)
*/
#define SkScalarMod(x,y) sk_float_mod(x,y)
/** Returns the product of the first two arguments, divided by the third argument
*/
#define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c))
/** Returns the multiplicative inverse of the SkScalar (1/x)
*/
#define SkScalarInvert(x) (SK_Scalar1 / (x))
#define SkScalarFastInvert(x) (SK_Scalar1 / (x))
/** Returns the square root of the SkScalar
*/
#define SkScalarSqrt(x) sk_float_sqrt(x)
/** Returns b to the e
*/
#define SkScalarPow(b, e) sk_float_pow(b, e)
/** Returns the average of two SkScalars (a+b)/2
*/
#define SkScalarAve(a, b) (((a) + (b)) * 0.5f)
/** Returns the geometric mean of two SkScalars
*/
#define SkScalarMean(a, b) sk_float_sqrt((float)(a) * (b))
/** Returns one half of the specified SkScalar
*/
#define SkScalarHalf(a) ((a) * 0.5f)
#define SK_ScalarSqrt2 1.41421356f
#define SK_ScalarPI 3.14159265f
#define SK_ScalarTanPIOver8 0.414213562f
#define SK_ScalarRoot2Over2 0.707106781f
#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
float SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
#define SkScalarSin(radians) (float)sk_float_sin(radians)
#define SkScalarCos(radians) (float)sk_float_cos(radians)
#define SkScalarTan(radians) (float)sk_float_tan(radians)
#define SkScalarASin(val) (float)sk_float_asin(val)
#define SkScalarACos(val) (float)sk_float_acos(val)
#define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
#define SkScalarExp(x) (float)sk_float_exp(x)
#define SkScalarLog(x) (float)sk_float_log(x)
inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }
static inline bool SkScalarIsInt(SkScalar x) {
return x == (float)(int)x;
}
#else
typedef SkFixed SkScalar;
#define SK_Scalar1 SK_Fixed1
#define SK_ScalarHalf SK_FixedHalf
#define SK_ScalarInfinity SK_FixedMax
#define SK_ScalarNegativeInfinity SK_FixedMin
#define SK_ScalarMax SK_FixedMax
#define SK_ScalarMin SK_FixedMin
#define SK_ScalarNaN SK_FixedNaN
#define SkScalarIsNaN(x) ((x) == SK_FixedNaN)
#define SkScalarIsFinite(x) ((x) != SK_FixedNaN)
#define SkIntToScalar(n) SkIntToFixed(n)
#define SkFixedToScalar(x) (x)
#define SkScalarToFixed(x) (x)
#define SkScalarToFloat(n) SkFixedToFloat(n)
#define SkFloatToScalar(n) SkFloatToFixed(n)
#define SkScalarToDouble(n) SkFixedToDouble(n)
#define SkDoubleToScalar(n) SkDoubleToFixed(n)
#define SkScalarFraction(x) SkFixedFraction(x)
#define SkScalarFloorToScalar(x) SkFixedFloorToFixed(x)
#define SkScalarCeilToScalar(x) SkFixedCeilToFixed(x)
#define SkScalarRoundToScalar(x) SkFixedRoundToFixed(x)
#define SkScalarFloorToInt(x) SkFixedFloorToInt(x)
#define SkScalarCeilToInt(x) SkFixedCeilToInt(x)
#define SkScalarRoundToInt(x) SkFixedRoundToInt(x)
#define SkScalarTruncToInt(x) (((x) < 0) ? SkScalarCeilToInt(x) : SkScalarFloorToInt(x))
#define SkScalarAbs(x) SkFixedAbs(x)
#define SkScalarCopySign(x, y) SkCopySign32(x, y)
#define SkScalarClampMax(x, max) SkClampMax(x, max)
#define SkScalarPin(x, min, max) SkPin32(x, min, max)
#define SkScalarSquare(x) SkFixedSquare(x)
#define SkScalarMul(a, b) SkFixedMul(a, b)
#define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c)
#define SkScalarMulRound(a, b) SkFixedMulCommon(a, b, SK_FixedHalf)
#define SkScalarMulCeil(a, b) SkFixedMulCommon(a, b, SK_Fixed1 - 1)
#define SkScalarMulFloor(a, b) SkFixedMulCommon(a, b, 0)
#define SkScalarDiv(a, b) SkFixedDiv(a, b)
#define SkScalarMod(a, b) SkFixedMod(a, b)
#define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c)
#define SkScalarInvert(x) SkFixedInvert(x)
#define SkScalarFastInvert(x) SkFixedFastInvert(x)
#define SkScalarSqrt(x) SkFixedSqrt(x)
#define SkScalarAve(a, b) SkFixedAve(a, b)
#define SkScalarMean(a, b) SkFixedMean(a, b)
#define SkScalarHalf(a) ((a) >> 1)
#define SK_ScalarSqrt2 SK_FixedSqrt2
#define SK_ScalarPI SK_FixedPI
#define SK_ScalarTanPIOver8 SK_FixedTanPIOver8
#define SK_ScalarRoot2Over2 SK_FixedRoot2Over2
#define SkDegreesToRadians(degrees) SkFractMul(degrees, SK_FractPIOver180)
#define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr)
#define SkScalarSin(radians) SkFixedSin(radians)
#define SkScalarCos(radians) SkFixedCos(radians)
#define SkScalarTan(val) SkFixedTan(val)
#define SkScalarASin(val) SkFixedASin(val)
#define SkScalarACos(val) SkFixedACos(val)
#define SkScalarATan2(y, x) SkFixedATan2(y,x)
#define SkScalarExp(x) SkFixedExp(x)
#define SkScalarLog(x) SkFixedLog(x)
#define SkMaxScalar(a, b) SkMax32(a, b)
#define SkMinScalar(a, b) SkMin32(a, b)
static inline bool SkScalarIsInt(SkFixed x) {
return 0 == (x & 0xffff);
}
#endif
// DEPRECATED : use ToInt or ToScalar variant
#define SkScalarFloor(x) SkScalarFloorToInt(x)
#define SkScalarCeil(x) SkScalarCeilToInt(x)
#define SkScalarRound(x) SkScalarRoundToInt(x)
/**
* Returns -1 || 0 || 1 depending on the sign of value:
* -1 if x < 0
* 0 if x == 0
* 1 if x > 0
*/
static inline int SkScalarSignAsInt(SkScalar x) {
return x < 0 ? -1 : (x > 0);
}
// Scalar result version of above
static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
}
#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12))
static inline bool SkScalarNearlyZero(SkScalar x,
SkScalar tolerance = SK_ScalarNearlyZero) {
SkASSERT(tolerance >= 0);
return SkScalarAbs(x) <= tolerance;
}
static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
SkScalar tolerance = SK_ScalarNearlyZero) {
SkASSERT(tolerance >= 0);
return SkScalarAbs(x-y) <= tolerance;
}
/** Linearly interpolate between A and B, based on t.
If t is 0, return A
If t is 1, return B
else interpolate.
t must be [0..SK_Scalar1]
*/
static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
SkASSERT(t >= 0 && t <= SK_Scalar1);
return A + SkScalarMul(B - A, t);
}
static inline SkScalar SkScalarLog2(SkScalar x) {
static const SkScalar log2_conversion_factor = SkScalarDiv(1, SkScalarLog(2));
return SkScalarMul(SkScalarLog(x), log2_conversion_factor);
}
/** Interpolate along the function described by (keys[length], values[length])
for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length]
clamp to the min or max value. This function was inspired by a desire
to change the multiplier for thickness in fakeBold; therefore it assumes
the number of pairs (length) will be small, and a linear search is used.
Repeated keys are allowed for discontinuous functions (so long as keys is
monotonically increasing), and if key is the value of a repeated scalar in
keys, the first one will be used. However, that may change if a binary
search is used.
*/
SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
const SkScalar values[], int length);
/*
* Helper to compare an array of scalars.
*/
static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
#ifdef SK_SCALAR_IS_FLOAT
SkASSERT(n >= 0);
for (int i = 0; i < n; ++i) {
if (a[i] != b[i]) {
return false;
}
}
return true;
#else
return 0 == memcmp(a, b, n * sizeof(SkScalar));
#endif
}
#endif

View File

@ -1,3 +1,4 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -311,17 +312,14 @@ 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 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.
* If the shader subclass has a GrEffect implementation, this installs an effect on the stage.
* The GrContext may be used by the effect to create textures. The GPU device does not call
* setContext. Instead we pass the paint here in case the shader needs paint info.
*/
virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const;
@ -334,9 +332,6 @@ 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.
@ -347,8 +342,6 @@ public:
SkDEVCODE(virtual void toString(SkString* str) const;)
SK_DEFINE_FLATTENABLE_TYPE(SkShader)
protected:
enum MatrixClass {
kLinear_MatrixClass, // no perspective
@ -359,15 +352,17 @@ 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(SkReadBuffer& );
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkShader(SkFlattenableReadBuffer& );
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:
SkMatrix fLocalMatrix;
SkMatrix fTotalInverse;
uint8_t fPaintAlpha;
uint8_t fDeviceConfig;
uint8_t fTotalInverseClass;
SkDEBUGCODE(SkBool8 fInSetContext;)

View File

@ -90,19 +90,19 @@ struct SkSize : public SkTSize<SkScalar> {
SkISize toRound() const {
SkISize s;
s.set(SkScalarRoundToInt(fWidth), SkScalarRoundToInt(fHeight));
s.set(SkScalarRound(fWidth), SkScalarRound(fHeight));
return s;
}
SkISize toCeil() const {
SkISize s;
s.set(SkScalarCeilToInt(fWidth), SkScalarCeilToInt(fHeight));
s.set(SkScalarCeil(fWidth), SkScalarCeil(fHeight));
return s;
}
SkISize toFloor() const {
SkISize s;
s.set(SkScalarFloorToInt(fWidth), SkScalarFloorToInt(fHeight));
s.set(SkScalarFloor(fWidth), SkScalarFloor(fHeight));
return s;
}
};

View File

@ -0,0 +1,397 @@
/*
* 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

View File

@ -11,7 +11,6 @@
#define SkString_DEFINED
#include "SkScalar.h"
#include "SkTArray.h"
#include <stdarg.h>
@ -60,14 +59,9 @@ static inline char *SkStrDup(const char string[]) {
#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)
#define SkStrAppendS32_MaxSize 11
char* SkStrAppendS32(char buffer[], int32_t);
#define SkStrAppendS64_MaxSize (SkStrAppendU64_MaxSize + 1)
#define SkStrAppendS64_MaxSize 20
char* SkStrAppendS64(char buffer[], int64_t, int minDigits);
/**
@ -86,7 +80,11 @@ 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.
*/
#define SkStrAppendScalar SkStrAppendFloat
#ifdef SK_SCALAR_IS_FLOAT
#define SkStrAppendScalar SkStrAppendFloat
#else
#define SkStrAppendScalar SkStrAppendFixed
#endif
char* SkStrAppendFloat(char buffer[], float);
char* SkStrAppendFixed(char buffer[], SkFixed);
@ -166,8 +164,6 @@ 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);
@ -177,8 +173,6 @@ 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); }
@ -193,7 +187,7 @@ public:
void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
void appendVAList(const char format[], va_list);
void appendf(const char format[], va_list);
void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
void remove(size_t offset, size_t length);
@ -211,7 +205,7 @@ public:
private:
struct Rec {
public:
uint32_t fLength; // logically size_t, but we want it to stay 32bits
size_t fLength;
int32_t fRefCnt;
char fBeginningOfData;
@ -232,6 +226,24 @@ 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, ...);
@ -241,7 +253,4 @@ 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<SkString>* out);
#endif

View File

@ -81,14 +81,6 @@ 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;

View File

@ -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 SK_API SkSurface : public SkRefCnt {
class 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 SkImageInfo&, void* pixels, size_t rowBytes);
static SkSurface* NewRasterDirect(const SkImage::Info&, void* pixels, size_t rowBytes);
/**
* Return a new surface, with the memory for the pixels automatically
@ -44,19 +44,7 @@ public:
* If the requested surface cannot be created, or the request is not a
* supported configuration, NULL will be returned.
*/
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);
}
static SkSurface* NewRaster(const SkImage::Info&);
/**
* Return a new surface whose contents will be recorded into a picture.
@ -68,13 +56,13 @@ public:
/**
* Return a new surface using the specified render target.
*/
static SkSurface* NewRenderTargetDirect(GrRenderTarget*);
static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*);
/**
* Return a new surface whose contents will be drawn to an offscreen
* render target, allocated by the surface.
*/
static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount = 0);
static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&, int sampleCount = 0);
int width() const { return fWidth; }
int height() const { return fHeight; }
@ -91,26 +79,10 @@ public:
uint32_t generationID();
/**
* Modes that can be passed to notifyContentWillChange
*/
enum ContentChangeMode {
/**
* Use this mode if it is known that the upcoming content changes will
* clear or overwrite prior contents, thus making them discardable.
*/
kDiscard_ContentChangeMode,
/**
* Use this mode if prior surface contents need to be preserved or
* if in doubt.
*/
kRetain_ContentChangeMode,
};
/**
* Call this if the contents are about to change. This will (lazily) force a new
* Call this if the contents have changed. This will (lazily) force a new
* value to be returned from generationID() when it is called next.
*/
void notifyContentWillChange(ContentChangeMode mode);
void notifyContentChanged();
/**
* Return a canvas that will draw into this surface. This will always
@ -133,14 +105,14 @@ public:
* ... // draw using canvasB
* canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
*/
SkSurface* newSurface(const SkImageInfo&);
SkSurface* newSurface(const SkImage::Info&);
/**
* Returns an image of the current state of the surface pixels up to this
* point. Subsequent changes to the surface (by drawing into its canvas)
* will not be reflected in this image.
*/
SkImage* newImageSnapshot();
SkImage* newImageShapshot();
/**
* Thought the caller could get a snapshot image explicitly, and draw that,
@ -153,7 +125,6 @@ public:
protected:
SkSurface(int width, int height);
SkSurface(const SkImageInfo&);
// called by subclass if their contents have changed
void dirtyGenerationID() {

View File

@ -28,21 +28,19 @@ inline void copyAndDelete(SkTArray<T, true>* self, char* newMemArray) {
template<typename T>
inline void copy(SkTArray<T, false>* self, const T* array) {
for (int i = 0; i < self->fCount; ++i) {
SkNEW_PLACEMENT_ARGS(self->fItemArray + i, T, (array[i]));
new (self->fItemArray + i) T(array[i]);
}
}
template<typename T>
inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) {
for (int i = 0; i < self->fCount; ++i) {
SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i]));
new (newMemArray + sizeof(T) * i) T(self->fItemArray[i]);
self->fItemArray[i].~T();
}
}
}
template <typename T, bool MEM_COPY> void* operator new(size_t, SkTArray<T, MEM_COPY>*, int);
/** When MEM_COPY is true T will be bit copied when moved.
When MEM_COPY is false, T will be copy constructed / destructed.
In all cases T's constructor will be called on allocation,
@ -93,7 +91,7 @@ public:
fItemArray[i].~T();
}
fCount = 0;
this->checkRealloc((int)array.count());
checkRealloc((int)array.count());
fCount = array.count();
SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray));
return *this;
@ -113,23 +111,6 @@ 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.
*/
@ -161,18 +142,20 @@ public:
* elements.
*/
T& push_back() {
T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
SkNEW_PLACEMENT(newT, T);
return *newT;
checkRealloc(1);
new ((char*)fMemArray+sizeof(T)*fCount) T;
++fCount;
return fItemArray[fCount-1];
}
/**
* Version of above that uses a copy constructor to initialize the new item
*/
T& push_back(const T& t) {
T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
SkNEW_PLACEMENT_ARGS(newT, T, (t));
return *newT;
checkRealloc(1);
new ((char*)fMemArray+sizeof(T)*fCount) T(t);
++fCount;
return fItemArray[fCount-1];
}
/**
@ -182,11 +165,12 @@ public:
*/
T* push_back_n(int n) {
SkASSERT(n >= 0);
T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
checkRealloc(n);
for (int i = 0; i < n; ++i) {
SkNEW_PLACEMENT(newTs + i, T);
new (fItemArray + fCount + i) T;
}
return newTs;
fCount += n;
return fItemArray + fCount - n;
}
/**
@ -195,11 +179,12 @@ public:
*/
T* push_back_n(int n, const T& t) {
SkASSERT(n >= 0);
T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
checkRealloc(n);
for (int i = 0; i < n; ++i) {
SkNEW_PLACEMENT_ARGS(newTs[i], T, (t));
new (fItemArray + fCount + i) T(t);
}
return newTs;
fCount += n;
return fItemArray + fCount - n;
}
/**
@ -208,9 +193,9 @@ public:
*/
T* push_back_n(int n, const T t[]) {
SkASSERT(n >= 0);
this->checkRealloc(n);
checkRealloc(n);
for (int i = 0; i < n; ++i) {
SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t[i]));
new (fItemArray + fCount + i) T(t[i]);
}
fCount += n;
return fItemArray + fCount - n;
@ -223,7 +208,7 @@ public:
SkASSERT(fCount > 0);
--fCount;
fItemArray[fCount].~T();
this->checkRealloc(0);
checkRealloc(0);
}
/**
@ -234,9 +219,9 @@ public:
SkASSERT(fCount >= n);
fCount -= n;
for (int i = 0; i < n; ++i) {
fItemArray[fCount + i].~T();
fItemArray[i].~T();
}
this->checkRealloc(0);
checkRealloc(0);
}
/**
@ -247,9 +232,9 @@ public:
SkASSERT(newCount >= 0);
if (newCount > fCount) {
this->push_back_n(newCount - fCount);
push_back_n(newCount - fCount);
} else if (newCount < fCount) {
this->pop_back_n(fCount - newCount);
pop_back_n(fCount - newCount);
}
}
@ -382,15 +367,6 @@ 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);
@ -425,8 +401,6 @@ private:
}
}
friend void* operator new<T>(size_t, SkTArray*, int);
template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that, const X*);
template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true>* that, char*);
@ -443,29 +417,6 @@ private:
};
};
// Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directly
template <typename T, bool MEM_COPY>
void* operator new(size_t, SkTArray<T, MEM_COPY>* array, int atIndex) {
// Currently, we only support adding to the end of the array. When the array class itself
// supports random insertion then this should be updated.
// SkASSERT(atIndex >= 0 && atIndex <= array->count());
SkASSERT(atIndex == array->count());
return array->push_back_raw(1);
}
// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
// to match the op new silences warnings about missing op delete when a constructor throws an
// exception.
template <typename T, bool MEM_COPY>
void operator delete(void*, SkTArray<T, MEM_COPY>* array, int atIndex) {
SK_CRASH();
}
// Constructs a new object as the last element of an SkTArray.
#define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \
(new ((array_ptr), (array_ptr)->count()) type_name args)
/**
* Subclass of SkTArray that contains a preallocated memory block for the array.
*/
@ -486,10 +437,6 @@ public:
: INHERITED(array, &fStorage) {
}
explicit SkSTArray(int reserveCount)
: INHERITED(reserveCount) {
}
SkSTArray(const T* array, int count)
: INHERITED(array, count, &fStorage) {
}

View File

@ -21,7 +21,7 @@ public:
fData = NULL;
#endif
}
SkTDArray(const T src[], int count) {
SkTDArray(const T src[], size_t count) {
SkASSERT(src || count == 0);
fReserve = fCount = 0;
@ -69,9 +69,6 @@ public:
(a.fCount == 0 ||
!memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
}
friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {
return !(a == b);
}
void swap(SkTDArray<T>& other) {
SkTSwap(fArray, other.fArray);
@ -98,14 +95,7 @@ public:
/**
* Return the number of elements in the array
*/
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; }
int count() const { return (int)fCount; }
/**
* return the number of bytes in the array: count * sizeof(T)
@ -118,11 +108,11 @@ public:
const T* end() const { return fArray ? fArray + fCount : NULL; }
T& operator[](int index) {
SkASSERT(index < fCount);
SkASSERT((unsigned)index < fCount);
return fArray[index];
}
const T& operator[](int index) const {
SkASSERT(index < fCount);
SkASSERT((unsigned)index < fCount);
return fArray[index];
}
@ -151,43 +141,25 @@ public:
fCount = 0;
}
/**
* 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);
void setCount(size_t count) {
if (count > fReserve) {
this->resizeStorageToAtLeast(count);
this->growBy(count - fCount);
} else {
fCount = count;
}
fCount = 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 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) {
void setReserve(size_t reserve) {
if (reserve > fReserve) {
this->resizeStorageToAtLeast(reserve);
SkASSERT(reserve > fCount);
size_t count = fCount;
this->growBy(reserve - fCount);
fCount = count;
}
}
T* prepend() {
this->adjustCount(1);
this->growBy(1);
memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
return fArray;
}
@ -195,13 +167,13 @@ public:
T* append() {
return this->append(1, NULL);
}
T* append(int count, const T* src = NULL) {
int oldCount = fCount;
T* append(size_t count, const T* src = NULL) {
size_t oldCount = fCount;
if (count) {
SkASSERT(src == NULL || fArray == NULL ||
src + count <= fArray || fArray + oldCount <= src);
this->adjustCount(count);
this->growBy(count);
if (src) {
memcpy(fArray + oldCount, src, sizeof(T) * count);
}
@ -215,14 +187,14 @@ public:
return result;
}
T* insert(int index) {
T* insert(size_t index) {
return this->insert(index, 1, NULL);
}
T* insert(int index, int count, const T* src = NULL) {
T* insert(size_t index, size_t count, const T* src = NULL) {
SkASSERT(count);
SkASSERT(index <= fCount);
size_t oldCount = fCount;
this->adjustCount(count);
this->growBy(count);
T* dst = fArray + index;
memmove(dst + count, dst, sizeof(T) * (oldCount - index));
if (src) {
@ -231,15 +203,15 @@ public:
return dst;
}
void remove(int index, int count = 1) {
void remove(size_t index, size_t count = 1) {
SkASSERT(index + count <= fCount);
fCount = fCount - count;
memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
}
void removeShuffle(int index) {
void removeShuffle(size_t index) {
SkASSERT(index < fCount);
int newCount = fCount - 1;
size_t newCount = fCount - 1;
fCount = newCount;
if (index != newCount) {
memcpy(fArray + index, fArray + newCount, sizeof(T));
@ -264,7 +236,7 @@ public:
while (iter > stop) {
if (*--iter == elem) {
return SkToInt(iter - stop);
return iter - stop;
}
}
return -1;
@ -281,7 +253,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, int index, int max) const {
int copyRange(T* dst, size_t index, int max) const {
SkASSERT(max >= 0);
SkASSERT(!max || dst);
if (index >= fCount) {
@ -293,7 +265,7 @@ public:
}
void copy(T* dst) const {
this->copyRange(dst, 0, fCount);
this->copyRange(0, fCount, dst);
}
// routines to treat the array like a stack
@ -371,46 +343,22 @@ private:
ArrayT* fData;
#endif
T* fArray;
int fReserve;
int fCount;
size_t fReserve, fCount;
/**
* 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);
}
void growBy(size_t extra) {
SkASSERT(extra);
/**
* 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));
if (fCount + extra > fReserve) {
size_t size = fCount + extra + 4;
size += size >> 2;
fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
#ifdef SK_DEBUG
fData = (ArrayT*)fArray;
fData = (ArrayT*)fArray;
#endif
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);
fReserve = size;
}
fCount += extra;
}
};

View File

@ -227,7 +227,7 @@ public:
void validate() const {
SkASSERT(!fHead == !fTail);
Iter iter;
for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != item; item = iter.next()) {
for (T* item = iter.init(*this, Iter::kHead_IterStart); NULL != (item = iter.next()); ) {
SkASSERT(this->isInList(item));
if (NULL == item->fPrev) {
SkASSERT(fHead == item);

View File

@ -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 <typename T> class SkTRegistry : SkNoncopyable {
template <typename T, typename P> class SkTRegistry : SkNoncopyable {
public:
typedef T Factory;
typedef T (*Factory)(P);
explicit SkTRegistry(T fact) : fFact(fact) {
SkTRegistry(Factory fact) {
#ifdef SK_BUILD_FOR_ANDROID
// work-around for double-initialization bug
{
@ -33,14 +33,15 @@ public:
}
}
#endif
fFact = fact;
fChain = gHead;
gHead = this;
gHead = this;
}
static const SkTRegistry* Head() { return gHead; }
const SkTRegistry* next() const { return fChain; }
const Factory& factory() const { return fFact; }
Factory factory() const { return fFact; }
private:
Factory fFact;
@ -50,6 +51,6 @@ private:
};
// The caller still needs to declare an instance of this somewhere
template <typename T> SkTRegistry<T>* SkTRegistry<T>::gHead;
template <typename T, typename P> SkTRegistry<T, P>* SkTRegistry<T, P>::gHead;
#endif

View File

@ -0,0 +1,76 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkTScopedPtr_DEFINED
#define SkTScopedPtr_DEFINED
#include "SkTypes.h"
/** \class SkTScopedPtr
A SkTScopedPtr<T> is like a T*, except that the destructor of SkTScopedPtr<T>
automatically deletes the pointer it holds (if any). That is, SkTScopedPtr<T>
owns the T object that it points to. Like a T*, a SkTScopedPtr<T> may hold
either NULL or a pointer to a T object. Also like T*, SkTScopedPtr<T> is
thread-compatible, and once you dereference it, you get the threadsafety
guarantees of T.
The size of a SkTScopedPtr is small: sizeof(SkTScopedPtr<T>) == sizeof(T*)
*/
template <typename T> class SkTScopedPtr : SkNoncopyable {
public:
explicit SkTScopedPtr(T* o = NULL) : fObj(o) {}
~SkTScopedPtr() {
enum { kTypeMustBeComplete = sizeof(T) };
delete fObj;
}
/** Delete the current object, if any. Then take ownership of the
passed object.
*/
void reset(T* o = NULL) {
if (o != fObj) {
enum { kTypeMustBeComplete = sizeof(T) };
delete fObj;
fObj = o;
}
}
/** Without deleting the current object, return it and forget about it.
Similar to calling get() and reset(), but the object is not deleted.
*/
T* release() {
T* retVal = fObj;
fObj = NULL;
return retVal;
}
T& operator*() const {
SkASSERT(fObj != NULL);
return *fObj;
}
T* operator->() const {
SkASSERT(fObj != NULL);
return fObj;
}
T* get() const { return fObj; }
bool operator==(T* o) const { return fObj == o; }
bool operator!=(T* o) const { return fObj != o; }
private:
T* fObj;
// Forbid comparison of SkTScopedPtr types. If T2 != T, it doesn't make
// sense, and if T2 == T, it still doesn't make sense because the same
// object can't be owned by two different scoped_ptrs.
template <class T2> bool operator==(SkTScopedPtr<T2> const& o2) const;
template <class T2> bool operator!=(SkTScopedPtr<T2> const& o2) const;
};
#endif

View File

@ -0,0 +1,239 @@
/*
* 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 <typename T>
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 <typename T, int (COMPARE)(const T*, const T*)>
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 <typename T>
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 <typename T>
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 <typename T, int (COMPARE)(const T*, const T*)>
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<int (*)(const void*, const void*)>(compare)
#endif

Some files were not shown because too many files have changed in this diff Show More