This commit is contained in:
Wes Kocher 2014-02-18 22:01:23 -08:00
Родитель 24b85c3495 47debb45e8
Коммит 4b6c7f4bc0
1654 изменённых файлов: 107040 добавлений и 50067 удалений

Просмотреть файл

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Recent Android build system changes from bug 961339 and bug 946083 seem to be needs-clobbery.
Skia update from Bug 910754 needs a CLOBBER build

Просмотреть файл

@ -13,6 +13,7 @@
#include "MacIOSurface.h"
#include "FilterNodeSoftware.h"
#include "mozilla/Assertions.h"
#include "mozilla/FloatingPoint.h"
using namespace std;
@ -413,6 +414,8 @@ UpdateLinearParametersToIncludePoint(double *min_t, double *max_t,
double dx, double dy,
double x, double y)
{
MOZ_ASSERT(IsFinite(x) && IsFinite(y));
/**
* Compute a parameter t such that a line perpendicular to the (dx,dy)
* vector, passing through (start->x + dx*t, start->y + dy*t), also
@ -609,6 +612,10 @@ DrawRadialRepeatingGradient(CGContextRef cg, const RadialGradientPattern &aPatte
static void
DrawGradient(CGContextRef cg, const Pattern &aPattern, const CGRect &aExtents)
{
if (CGRectIsEmpty(aExtents)) {
return;
}
if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -470,7 +470,7 @@ SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source,
src_row += h * row_words;
dst_row += result.rowBytes() / 4;
}
result.setIsOpaque(img.isOpaque());
result.setAlphaType(img.alphaType());
return result;
#else
return SkBitmap();
@ -534,7 +534,7 @@ SkBitmap ImageOperations::ResizeBasic(const SkBitmap& source,
/* sse = */ false);
// Preserve the "opaque" flag for use as an optimization later.
result.setIsOpaque(source.isOpaque());
result.setAlphaType(source.alphaType());
return result;
}

Просмотреть файл

@ -499,6 +499,19 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
{ (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
{ (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
// These functions are only used by Skia/GL in desktop mode.
// Other parts of Gecko should avoid using these
{ (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
{ (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
{ (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
{ (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
{ (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
{ (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
{ (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
{ (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
{ (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
{ (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
{ nullptr, { nullptr } },
};

Просмотреть файл

@ -862,6 +862,12 @@ public:
AFTER_GL_CALL;
}
void fClientActiveTexture(GLenum texture) {
BEFORE_GL_CALL;
mSymbols.fClientActiveTexture(texture);
AFTER_GL_CALL;
}
void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha) {
BEFORE_GL_CALL;
mSymbols.fColorMask(red, green, blue, alpha);
@ -954,6 +960,12 @@ public:
AFTER_GL_CALL;
}
void fDisableClientState(GLenum capability) {
BEFORE_GL_CALL;
mSymbols.fDisableClientState(capability);
AFTER_GL_CALL;
}
void fDisableVertexAttribArray(GLuint index) {
BEFORE_GL_CALL;
mSymbols.fDisableVertexAttribArray(index);
@ -998,6 +1010,12 @@ public:
AFTER_GL_CALL;
}
void fEnableClientState(GLenum capability) {
BEFORE_GL_CALL;
mSymbols.fEnableClientState(capability);
AFTER_GL_CALL;
}
void fEnableVertexAttribArray(GLuint index) {
BEFORE_GL_CALL;
mSymbols.fEnableVertexAttribArray(index);
@ -1343,6 +1361,24 @@ public:
AFTER_GL_CALL;
}
void fLoadIdentity() {
BEFORE_GL_CALL;
mSymbols.fLoadIdentity();
AFTER_GL_CALL;
}
void fLoadMatrixf(const GLfloat *matrix) {
BEFORE_GL_CALL;
mSymbols.fLoadMatrixf(matrix);
AFTER_GL_CALL;
}
void fMatrixMode(GLenum mode) {
BEFORE_GL_CALL;
mSymbols.fMatrixMode(mode);
AFTER_GL_CALL;
}
void fPixelStorei(GLenum pname, GLint param) {
BEFORE_GL_CALL;
mSymbols.fPixelStorei(pname, param);
@ -1470,6 +1506,24 @@ public:
AFTER_GL_CALL;
}
void fTexGeni(GLenum coord, GLenum pname, GLint param) {
BEFORE_GL_CALL;
mSymbols.fTexGeni(coord, pname, param);
AFTER_GL_CALL;
}
void fTexGenf(GLenum coord, GLenum pname, GLfloat param) {
BEFORE_GL_CALL;
mSymbols.fTexGenf(coord, pname, param);
AFTER_GL_CALL;
}
void fTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) {
BEFORE_GL_CALL;
mSymbols.fTexGenfv(coord, pname, params);
AFTER_GL_CALL;
}
private:
void raw_fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
BEFORE_GL_CALL;
@ -1676,6 +1730,12 @@ public:
AFTER_GL_CALL;
}
void fVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
BEFORE_GL_CALL;
mSymbols.fVertexPointer(size, type, stride, pointer);
AFTER_GL_CALL;
}
void fCompileShader(GLuint shader) {
BEFORE_GL_CALL;
mSymbols.fCompileShader(shader);

Просмотреть файл

@ -125,6 +125,12 @@ GrGLvoid glCompileShader_mozilla(GrGLuint shader)
return sGLContext.get()->fCompileShader(shader);
}
GrGLvoid glCopyTexSubImage2D_mozilla(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset,
GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height)
{
return sGLContext.get()->fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
GrGLuint glCreateProgram_mozilla(void)
{
return sGLContext.get()->fCreateProgram();
@ -250,6 +256,11 @@ GrGLvoid glGenTextures_mozilla(GrGLsizei n, GrGLuint* textures)
return sGLContext.get()->fGenTextures(n, textures);
}
GrGLvoid glGenerateMipmap_mozilla(GrGLenum target)
{
return sGLContext.get()->fGenerateMipmap(target);
}
GrGLvoid glGetBufferParameteriv_mozilla(GrGLenum target, GrGLenum pname, GrGLint* params)
{
return sGLContext.get()->fGetBufferParameteriv(target, pname, params);
@ -710,6 +721,57 @@ GrGLvoid glGenVertexArrays_mozilla(GrGLsizei n, GrGLuint *arrays) {
return sGLContext.get()->fGenVertexArrays(n, arrays);
}
// Additional functions required for desktop GL < version 3.2
GrGLvoid glClientActiveTexture_mozilla(GrGLenum texture)
{
return sGLContext.get()->fClientActiveTexture(texture);
}
GrGLvoid glDisableClientState_mozilla(GrGLenum capability)
{
return sGLContext.get()->fDisableClientState(capability);
}
GrGLvoid glEnableClientState_mozilla(GrGLenum capability)
{
return sGLContext.get()->fEnableClientState(capability);
}
GrGLvoid glLoadMatrixf_mozilla(const GLfloat* matrix)
{
return sGLContext.get()->fLoadMatrixf(matrix);
}
GrGLvoid glLoadIdentity_mozilla()
{
return sGLContext.get()->fLoadIdentity();
}
GrGLvoid glMatrixMode_mozilla(GrGLenum mode)
{
return sGLContext.get()->fMatrixMode(mode);
}
GrGLvoid glTexGeni_mozilla(GrGLenum coord, GrGLenum pname, GrGLint param)
{
return sGLContext.get()->fTexGeni(coord, pname, param);
}
GrGLvoid glTexGenf_mozilla(GrGLenum coord, GrGLenum pname, GrGLfloat param)
{
return sGLContext.get()->fTexGenf(coord, pname, param);
}
GrGLvoid glTexGenfv_mozilla(GrGLenum coord, GrGLenum pname, const GrGLfloat* param)
{
return sGLContext.get()->fTexGenfv(coord, pname, param);
}
GrGLvoid glVertexPointer_mozilla(GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* pointer)
{
return sGLContext.get()->fVertexPointer(size, type, stride, pointer);
}
} // extern "C"
@ -737,6 +799,7 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fClearStencil = glClearStencil_mozilla;
i->fColorMask = glColorMask_mozilla;
i->fCompileShader = glCompileShader_mozilla;
i->fCopyTexSubImage2D = glCopyTexSubImage2D_mozilla;
i->fCreateProgram = glCreateProgram_mozilla;
i->fCreateShader = glCreateShader_mozilla;
i->fCullFace = glCullFace_mozilla;
@ -763,6 +826,7 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fGenRenderbuffers = glGenRenderbuffers_mozilla;
i->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv_mozilla;
i->fGenTextures = glGenTextures_mozilla;
i->fGenerateMipmap = glGenerateMipmap_mozilla;
i->fGetBufferParameteriv = glGetBufferParameteriv_mozilla;
i->fGetError = glGetError_mozilla;
i->fGetIntegerv = glGetIntegerv_mozilla;
@ -849,6 +913,18 @@ GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
// Desktop OpenGL > 2.0
i->fDrawBuffers = glDrawBuffers_mozilla;
// Desktop OpenGL < 3.2 (which we pretend to be)
i->fClientActiveTexture = glClientActiveTexture_mozilla;
i->fDisableClientState = glDisableClientState_mozilla;
i->fEnableClientState = glEnableClientState_mozilla;
i->fLoadIdentity = glLoadIdentity_mozilla;
i->fLoadMatrixf = glLoadMatrixf_mozilla;
i->fMatrixMode = glMatrixMode_mozilla;
i->fTexGenf = glTexGenf_mozilla;
i->fTexGenfv = glTexGenfv_mozilla;
i->fTexGeni = glTexGeni_mozilla;
i->fVertexPointer = glVertexPointer_mozilla;
// We support both desktop GL and GLES2
if (context->IsGLES2()) {
i->fBindingsExported = kES2_GrGLBinding;

Просмотреть файл

@ -313,6 +313,31 @@ struct GLContextSymbols
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
// These functions are only used by Skia/GL in desktop mode.
// Other parts of Gecko should avoid using these
typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTURE) (GLenum texture);
PFNGLCLIENTACTIVETEXTURE fClientActiveTexture;
typedef void (GLAPIENTRY * PFNDISABLECLIENTSTATE) (GLenum capability);
PFNDISABLECLIENTSTATE fDisableClientState;
typedef void (GLAPIENTRY * PFNENABLECLIENTSTATE) (GLenum capability);
PFNENABLECLIENTSTATE fEnableClientState;
typedef void (GLAPIENTRY * PFNLOADIDENTITY) (void);
PFNLOADIDENTITY fLoadIdentity;
typedef void (GLAPIENTRY * PFNLOADMATRIXD) (const GLdouble* matrix);
PFNLOADMATRIXD fLoadMatrixd;
typedef void (GLAPIENTRY * PFNLOADMATRIXF) (const GLfloat* matrix);
PFNLOADMATRIXF fLoadMatrixf;
typedef void (GLAPIENTRY * PFNMATRIXMODE) (GLenum mode);
PFNMATRIXMODE fMatrixMode;
typedef void (GLAPIENTRY * PFNTEXGENI) (GLenum coord, GLenum pname, GLint param);
PFNTEXGENI fTexGeni;
typedef void (GLAPIENTRY * PFNTEXGENF) (GLenum coord, GLenum pname, GLfloat param);
PFNTEXGENF fTexGenf;
typedef void (GLAPIENTRY * PFNTEXGENFV) (GLenum coord, GLenum pname, const GLfloat* param);
PFNTEXGENFV fTexGenfv;
typedef void (GLAPIENTRY * PFNVERTEXPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
PFNVERTEXPOINTER fVertexPointer;
typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFER) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
PFNGLBLITFRAMEBUFFER fBlitFramebuffer;
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLE) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height);

Просмотреть файл

@ -813,9 +813,13 @@ ContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter)
}
if (prev) {
prev->SetNextSibling(next);
} else {
mFirstChild = next;
}
if (next) {
next->SetPrevSibling(prev);
} else {
mLastChild = prev;
}
if (!aAfter) {
aChild->SetPrevSibling(nullptr);

Просмотреть файл

@ -19,10 +19,13 @@ include $(topsrcdir)/config/rules.mk
ifneq (,$(INTEL_ARCHITECTURE))
ifdef GNU_CC
SkBitmapFilter_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkBitmapProcState_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkBitmapProcState_opts_SSSE3.$(OBJ_SUFFIX): CXXFLAGS+=-mssse3
SkBlitRow_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkBlitRect_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkBlitRow_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkBlurImage_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkMorphology_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
SkUtils_opts_SSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
endif
endif

Просмотреть файл

@ -2,4 +2,14 @@ The source from this directory was copied from the skia subversion trunk
using the update.sh script. The changes made were those applied by update.sh,
the addition/update of Makefile.in files for the Mozilla build system.
The subversion revision used was r8495.
The subversion revision used was r13424.
To update to a new version of Skia:
- Copy the entire trunk/ directory from a Skia clone to mozilla-central/gfx/skia
- cd gfx/skia && ./gyp_mozbuild
Once that's done, use git status to view the files that have changed. Keep an eye on GrUserConfig.h
and SkUserConfig.h as those probably don't want to be overwritten by upstream versions.
This process will be made more automatic in the future.

92
gfx/skia/dump_mozbuild.py Normal file
Просмотреть файл

@ -0,0 +1,92 @@
# Copyright (c) 2012 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import collections
import os
import gyp
import gyp.common
import gyp.msvs_emulation
import json
import sys
generator_supports_multiple_toolsets = True
generator_wants_static_library_dependencies_adjusted = False
generator_default_variables = {
}
for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
'LIB_DIR', 'SHARED_LIB_DIR']:
# Some gyp steps fail if these are empty(!).
generator_default_variables[dirname] = 'dir'
for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
'CONFIGURATION_NAME']:
generator_default_variables[unused] = ''
def CalculateVariables(default_variables, params):
generator_flags = params.get('generator_flags', {})
for key, val in generator_flags.items():
default_variables.setdefault(key, val)
default_variables.setdefault('OS', gyp.common.GetFlavor(params))
flavor = gyp.common.GetFlavor(params)
if flavor =='win':
# Copy additional generator configuration data from VS, which is shared
# by the Windows Ninja generator.
import gyp.generator.msvs as msvs_generator
generator_additional_non_configuration_keys = getattr(msvs_generator,
'generator_additional_non_configuration_keys', [])
generator_additional_path_sections = getattr(msvs_generator,
'generator_additional_path_sections', [])
gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
def CalculateGeneratorInputInfo(params):
"""Calculate the generator specific info that gets fed to input (called by
gyp)."""
generator_flags = params.get('generator_flags', {})
if generator_flags.get('adjust_static_libraries', False):
global generator_wants_static_library_dependencies_adjusted
generator_wants_static_library_dependencies_adjusted = True
def GetOS(params):
for d in params['defines']:
pass
def GenerateOutput(target_list, target_dicts, data, params):
# Map of target -> list of targets it depends on.
edges = {}
# Queue of targets to visit.
targets_to_visit = target_list[:]
sources = [];
while len(targets_to_visit) > 0:
target = targets_to_visit.pop()
if target in edges:
continue
edges[target] = []
target_sources = target_dicts[target].get('sources')
if target_sources:
for source in target_sources:
if source.endswith('.cpp'):
sources.append(source)
for dep in target_dicts[target].get('dependencies', []):
edges[target].append(dep)
targets_to_visit.append(dep)
skia_os = data['gyp/core.gyp']['variables']['skia_os%']
f = open('sources.json', 'w')
json.dump(sources, f)
f.close()

295
gfx/skia/generate_mozbuild.py Executable file
Просмотреть файл

@ -0,0 +1,295 @@
#!/usr/bin/env python
import os
import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
footer = """
# left out of UNIFIED_SOURCES for now; that's not C++ anyway, nothing else to unify it with
if not CONFIG['INTEL_ARCHITECTURE'] and CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:
SOURCES += [
'trunk/src/opts/memset.arm.S',
]
MSVC_ENABLE_PGO = True
FINAL_LIBRARY = 'gkmedias'
LOCAL_INCLUDES += [
'trunk/include/config',
'trunk/include/core',
'trunk/include/effects',
'trunk/include/gpu',
'trunk/include/images',
'trunk/include/lazy',
'trunk/include/pathops',
'trunk/include/pipe',
'trunk/include/ports',
'trunk/include/utils',
'trunk/include/utils/mac',
'trunk/include/utils/win',
'trunk/include/views',
'trunk/src/core',
'trunk/src/gpu',
'trunk/src/gpu/effects',
'trunk/src/gpu/gl',
'trunk/src/image',
'trunk/src/lazy',
'trunk/src/opts',
'trunk/src/sfnt',
'trunk/src/utils',
'trunk/src/utils/android',
'trunk/src/utils/mac',
'trunk/src/utils/win',
]
DEFINES['SK_A32_SHIFT'] = 24
DEFINES['SK_R32_SHIFT'] = 16
DEFINES['SK_G32_SHIFT'] = 8
DEFINES['SK_B32_SHIFT'] = 0
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'cocoa'):
DEFINES['SK_USE_POSIX_THREADS'] = 1
if CONFIG['INTEL_ARCHITECTURE'] and CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3']:
DEFINES['SK_BUILD_SSSE3'] = 1
if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android') or \
(CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa') or \
CONFIG['MOZ_WIDGET_GTK']:
DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DEFINES['SKIA_DLL'] = 1
DEFINES['SKIA_IMPLEMENTATION'] = 1
DEFINES['GR_IMPLEMENTATION'] = 1
"""
import json
platforms = ['linux', 'mac', 'android', 'win']
custom_includes = {
'trunk/src/ports/SkAtomics_android.h': True,
'trunk/src/ports/SkAtomics_sync.h': True,
'trunk/src/ports/SkAtomics_win.h': True,
'trunk/src/ports/SkMutex_pthread.h': True,
'trunk/src/ports/SkMutex_win.h': True
}
def generate_includes():
includes = {}
for root, dirs, files in os.walk('trunk/include'):
for name in files:
if name.endswith('.h'):
includes[os.path.join(root, name)] = True
return dict(includes.items() + custom_includes.items())
def generate_opt_sources():
opt_sources = {'opts': {''}}
for root, dirs, files in os.walk('trunk/src/opts'):
for name in files:
if name.endswith('.cpp'):
opt_sources['opts'].add(os.path.join(root, name))
return opt_sources
def generate_platform_sources():
sources = {}
for plat in platforms:
if os.system("cd trunk && GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=%s gyp/skia_lib.gyp" % plat) != 0:
print 'Failed to generate sources for ' + plat
continue
f = open('trunk/sources.json');
sources[plat] = set(json.load(f));
f.close()
return dict(sources.items() + generate_opt_sources().items())
def generate_separated_sources(platform_sources):
blacklist = [
'ChromeUtils',
'SkImageDecoder_',
'_gif',
'SkFontConfigParser_android',
'SkJpeg',
'SkXML',
'SkCity',
'GrGLCreateNativeInterface',
'fontconfig',
'_neon',
'SkImage_Codec',
'SkBitmapChecksummer',
'SkNativeGLContext',
'SkFontConfig',
'SkFontHost_win_dw',
'SkForceLinking',
'SkMovie',
'SkImageDecoder',
'SkImageEncoder',
'SkBitmapHasher',
'SkWGL',
'SkImages',
'SkDiscardableMemory_ashmem'
]
def isblacklisted(value):
for item in blacklist:
if value.find(item) >= 0:
return True
return False
separated = {
'common': {
#'trunk/src/effects/gradients/SkGradientTileProc.cpp',
'trunk/src/gpu/gl/GrGLCreateNativeInterface_none.cpp',
'trunk/src/ports/SkDiscardableMemory_none.cpp',
'trunk/src/ports/SkImageDecoder_empty.cpp',
# 'trunk/src/images/SkImages.cpp',
# 'trunk/src/images/SkImageRef.cpp',
# 'trunk/src/images/SkImageRef_GlobalPool.cpp',
# 'trunk/src/images/SkImageRefPool.cpp',
# 'trunk/src/images/SkImageDecoder.cpp',
# 'trunk/src/images/SkImageDecoder_Factory.cpp',
},
'android': {
# 'trunk/src/ports/SkDebug_android.cpp',
'trunk/src/ports/SkFontHost_cairo.cpp',
# 'trunk/src/ports/SkFontHost_FreeType.cpp',
# 'trunk/src/ports/SkFontHost_FreeType_common.cpp',
# 'trunk/src/ports/SkThread_pthread.cpp',
# 'trunk/src/ports/SkPurgeableMemoryBlock_android.cpp',
# 'trunk/src/ports/SkTime_Unix.cpp',
# 'trunk/src/utils/SkThreadUtils_pthread.cpp',
# 'trunk/src/utils/SkThreadUtils_pthread_other.cpp',
# 'trunk/src/images/SkImageRef_ashmem.cpp',
# 'trunk/src/utils/android/ashmem.cpp',
},
'linux': {
'trunk/src/ports/SkFontHost_cairo.cpp',
},
'intel': {
'trunk/src/opts/SkXfermode_opts_none.cpp',
},
'arm': {
'trunk/src/opts/SkUtils_opts_arm.cpp',
},
'none': {
'trunk/src/opts/SkUtils_opts_none.cpp',
}
}
for plat in platform_sources.keys():
if not separated.has_key(plat):
separated[plat] = set()
for value in platform_sources[plat]:
if isblacklisted(value):
continue
if value.find('_SSE') > 0 or value.find('_SSSE') > 0: #lol
separated['intel'].add(value)
continue
if value.find('_arm') > 0 or value.find('_neon') > 0:
separated['arm'].add(value)
continue
if value.find('_none') > 0:
separated['none'].add(value)
continue
found = True
for other in platforms:
if other == plat or not platform_sources.has_key(other):
continue
if not value in platform_sources[other]:
found = False
break;
if found:
separated['common'].add(value)
else:
separated[plat].add(value)
return separated
def uniq(seq):
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
def write_list(f, name, values, indent):
def write_indent(indent):
for _ in range(indent):
f.write(' ')
val_list = uniq(sorted(map(lambda val: val.replace('../', 'trunk/'), values), key=lambda x: x.lower()))
if len(val_list) == 0:
return
write_indent(indent)
f.write(name + ' += [\n')
for val in val_list:
write_indent(indent + 4)
f.write('\'' + val + '\',\n')
write_indent(4)
f.write(']\n')
def write_mozbuild(includes, sources):
filename = 'moz.build'
f = open(filename, 'w')
write_list(f, 'EXPORTS.skia', includes, 0)
write_list(f, 'SOURCES', sources['common'], 0)
f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):\n")
write_list(f, 'SOURCES', sources['android'], 4)
f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':\n")
write_list(f, 'SOURCES', sources['mac'], 4)
f.write("if CONFIG['MOZ_WIDGET_GTK']:\n")
write_list(f, 'SOURCES', sources['linux'], 4)
f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n")
write_list(f, 'SOURCES', sources['win'], 4)
f.write("\n\n")
f.write("if CONFIG['INTEL_ARCHITECTURE']:\n")
write_list(f, 'SOURCES', sources['intel'], 4)
f.write("elif CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_CC']:\n")
write_list(f, 'SOURCES', sources['arm'], 4)
f.write("else:\n")
write_list(f, 'SOURCES', sources['none'], 4)
f.write(footer)
f.close()
print 'Wrote ' + filename
def main():
includes = generate_includes()
platform_sources = generate_platform_sources()
separated_sources = generate_separated_sources(platform_sources)
write_mozbuild(includes, separated_sources)
if __name__ == '__main__':
main()

13
gfx/skia/gyp_mozbuild Executable file
Просмотреть файл

@ -0,0 +1,13 @@
#!/bin/bash
# Install our generator
cp dump_mozbuild.py trunk/third_party/externals/gyp/pylib/gyp/generator
# pushd trunk
# for OS in win linux mac; do
# GYP_GENERATORS=dump_mozbuild ./gyp_skia -D OS=$OS -D arm_neon=0 gyp/effects.gyp
# done
# popd
./generate_mozbuild.py

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1,175 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFlattenableBuffers_DEFINED
#define SkFlattenableBuffers_DEFINED
#include "SkColor.h"
#include "SkPaint.h"
#include "SkPoint.h"
class SkBitmap;
class SkFlattenable;
struct SkIRect;
class SkMatrix;
class SkOrderedReadBuffer;
class SkOrderedWriteBuffer;
class SkPath;
class SkPixelRef;
struct SkRect;
class SkRefCnt;
class SkRegion;
class SkStream;
class SkString;
class SkTypeface;
class SkWStream;
class SkFlattenableReadBuffer {
public:
SkFlattenableReadBuffer();
virtual ~SkFlattenableReadBuffer();
bool isOrderedBinaryBuffer() { return NULL != getOrderedBinaryBuffer(); }
virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() { return NULL; }
enum Flags {
kCrossProcess_Flag = 1 << 0,
kScalarIsFloat_Flag = 1 << 1,
kPtrIs64Bit_Flag = 1 << 2,
};
void setFlags(uint32_t flags) { fFlags = flags; }
uint32_t getFlags() const { return fFlags; }
bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
// primitives
virtual bool readBool() = 0;
virtual SkColor readColor() = 0;
virtual SkFixed readFixed() = 0;
virtual int32_t readInt() = 0;
virtual SkScalar readScalar() = 0;
virtual uint32_t readUInt() = 0;
virtual int32_t read32() = 0;
// strings -- the caller is responsible for freeing the string contents
virtual char* readString() = 0;
virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) = 0;
// common data structures
virtual SkFlattenable* readFlattenable() = 0;
virtual void readPoint(SkPoint* point) = 0;
virtual void readMatrix(SkMatrix* matrix) = 0;
virtual void readIRect(SkIRect* rect) = 0;
virtual void readRect(SkRect* rect) = 0;
virtual void readRegion(SkRegion* region) = 0;
virtual void readPath(SkPath* path) = 0;
// binary data and arrays
virtual uint32_t readByteArray(void* value) = 0;
virtual uint32_t readColorArray(SkColor* colors) = 0;
virtual uint32_t readIntArray(int32_t* values) = 0;
virtual uint32_t readPointArray(SkPoint* points) = 0;
virtual uint32_t readScalarArray(SkScalar* values) = 0;
/** This helper peeks into the buffer and reports back the length of the next array in
* the buffer but does not change the state of the buffer.
*/
virtual uint32_t getArrayCount() = 0;
// helper functions
virtual void* readFunctionPtr();
virtual void readPaint(SkPaint* paint);
virtual void readBitmap(SkBitmap* bitmap) = 0;
virtual SkTypeface* readTypeface() = 0;
// helper function for classes with const SkPoint members
SkPoint readPoint() {
SkPoint point;
this->readPoint(&point);
return point;
}
template <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

Просмотреть файл

@ -1,100 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImage_DEFINED
#define SkImage_DEFINED
#include "SkRefCnt.h"
#include "SkScalar.h"
class SkData;
class SkCanvas;
class SkPaint;
class SkShader;
class GrContext;
class GrTexture;
// need for TileMode
#include "SkShader.h"
////// EXPERIMENTAL
/**
* SkImage is an abstraction for drawing a rectagle of pixels, though the
* particular type of image could be actually storing its data on the GPU, or
* as drawing commands (picture or PDF or otherwise), ready to be played back
* into another canvas.
*
* The content of SkImage is always immutable, though the actual storage may
* change, if for example that image can be re-created via encoded data or
* other means.
*/
class SkImage : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkImage)
enum ColorType {
kAlpha_8_ColorType,
kRGB_565_ColorType,
kRGBA_8888_ColorType,
kBGRA_8888_ColorType,
kPMColor_ColorType,
kLastEnum_ColorType = kPMColor_ColorType
};
enum AlphaType {
kIgnore_AlphaType,
kOpaque_AlphaType,
kPremul_AlphaType,
kUnpremul_AlphaType,
kLastEnum_AlphaType = kUnpremul_AlphaType
};
struct Info {
int fWidth;
int fHeight;
ColorType fColorType;
AlphaType fAlphaType;
};
static SkImage* NewRasterCopy(const Info&, const void* pixels, size_t rowBytes);
static SkImage* NewRasterData(const Info&, SkData* pixels, size_t rowBytes);
static SkImage* NewEncodedData(SkData*);
static SkImage* NewTexture(GrTexture*);
int width() const { return fWidth; }
int height() const { return fHeight; }
uint32_t uniqueID() const { return fUniqueID; }
SkShader* newShaderClamp() const;
SkShader* newShader(SkShader::TileMode, SkShader::TileMode) const;
void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
protected:
SkImage(int width, int height) :
fWidth(width),
fHeight(height),
fUniqueID(NextUniqueID()) {
SkASSERT(width >= 0);
SkASSERT(height >= 0);
}
private:
const int fWidth;
const int fHeight;
const uint32_t fUniqueID;
static uint32_t NextUniqueID();
typedef SkRefCnt INHERITED;
};
#endif

Просмотреть файл

@ -1,171 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImageFilter_DEFINED
#define SkImageFilter_DEFINED
#include "SkFlattenable.h"
class SkBitmap;
class SkColorFilter;
class SkDevice;
class SkMatrix;
struct SkIPoint;
struct SkIRect;
class SkShader;
class GrEffectRef;
class GrTexture;
/**
* Experimental.
*
* Base class for image filters. If one is installed in the paint, then
* all drawing occurs as usual, but it is as if the drawing happened into an
* offscreen (before the xfermode is applied). This offscreen bitmap will
* then be handed to the imagefilter, who in turn creates a new bitmap which
* is what will finally be drawn to the device (using the original xfermode).
*
* THIS SIGNATURE IS TEMPORARY
*
* There are several weaknesses in this function signature:
* 1. Does not expose the destination/target device, so filters that can draw
* directly to it are unable to take advantage of that optimization.
* 2. Does not expose a way to create a "compabitible" image (i.e. gpu -> gpu)
* 3. As with #1, the filter is unable to "read" the dest (which would be slow)
*
* Therefore, we should not create any real dependencies on this API yet -- it
* is being checked in as a check-point so we can explore these and other
* considerations.
*/
class SK_API SkImageFilter : public SkFlattenable {
public:
SK_DECLARE_INST_COUNT(SkImageFilter)
class Proxy {
public:
virtual ~Proxy() {};
virtual SkDevice* createDevice(int width, int height) = 0;
// returns true if the proxy can handle this filter natively
virtual bool canHandleImageFilter(SkImageFilter*) = 0;
// returns true if the proxy handled the filter itself. if this returns
// false then the filter's code will be called.
virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset) = 0;
};
/**
* Request a new (result) image to be created from the src image.
* If the src has no pixels (isNull()) then the request just wants to
* receive the config and width/height of the result.
*
* The matrix is the current matrix on the canvas.
*
* Offset is the amount to translate the resulting image relative to the
* src when it is drawn.
*
* If the result image cannot be created, return false, in which case both
* the result and offset parameters will be ignored by the caller.
*/
bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset);
/**
* Given the src bounds of an image, this returns the bounds of the result
* image after the filter has been applied.
*/
bool filterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst);
/**
* Returns true if the filter can be expressed a single-pass
* GrEffect, used to process this filter on the GPU, or false if
* not.
*
* If effect is non-NULL, a new GrEffect instance is stored
* in it. The caller assumes ownership of the stage, and it is up to the
* caller to unref it.
*
* The effect can assume its vertexCoords space maps 1-to-1 with texels
* in the texture.
*/
virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
/**
* Returns true if the filter can be processed on the GPU. This is most
* often used for multi-pass effects, where intermediate results must be
* rendered to textures. For single-pass effects, use asNewEffect().
* The default implementation returns false.
*/
virtual bool canFilterImageGPU() const;
/**
* Process this image filter on the GPU. src is the source image for
* processing, as a texture-backed bitmap. result is the destination
* bitmap, which should contain a texture-backed pixelref on success.
* The default implementation returns returns false and ignores the
* result parameter.
*/
virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result);
/**
* Returns whether this image filter is a color filter and puts the color filter into the
* "filterPtr" parameter if it can. Does nothing otherwise.
* If this returns false, then the filterPtr is unchanged.
* If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
* (i.e. it may not be set to NULL).
*/
virtual bool asColorFilter(SkColorFilter** filterPtr) const;
/**
* Returns the number of inputs this filter will accept (some inputs can
* be NULL).
*/
int countInputs() const { return fInputCount; }
/**
* Returns the input filter at a given index, or NULL if no input is
* connected. The indices used are filter-specific.
*/
SkImageFilter* getInput(int i) const {
SkASSERT(i < fInputCount);
return fInputs[i];
}
protected:
SkImageFilter(int inputCount, SkImageFilter** inputs);
// Convenience constructor for 1-input filters.
explicit SkImageFilter(SkImageFilter* input);
// Convenience constructor for 2-input filters.
SkImageFilter(SkImageFilter* input1, SkImageFilter* input2);
virtual ~SkImageFilter();
explicit SkImageFilter(SkFlattenableReadBuffer& rb);
virtual void flatten(SkFlattenableWriteBuffer& wb) const SK_OVERRIDE;
// Default impl returns false
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset);
// Default impl copies src into dst and returns true
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
// Return the result of processing the given input, or the source bitmap
// if we have no connected input at that index.
SkBitmap getInputResult(int index, Proxy*, const SkBitmap& src, const SkMatrix&,
SkIPoint*);
private:
typedef SkFlattenable INHERITED;
int fInputCount;
SkImageFilter** fInputs;
};
#endif

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1,363 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPostConfig_DEFINED
#define SkPostConfig_DEFINED
#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE)
#define SK_BUILD_FOR_WIN
#endif
#if defined(SK_DEBUG) && defined(SK_RELEASE)
#error "cannot define both SK_DEBUG and SK_RELEASE"
#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
#error "must define either SK_DEBUG or SK_RELEASE"
#endif
#if defined SK_SUPPORT_UNITTEST && !defined(SK_DEBUG)
#error "can't have unittests without debug"
#endif
#if defined(SK_SCALAR_IS_FIXED) && defined(SK_SCALAR_IS_FLOAT)
#error "cannot define both SK_SCALAR_IS_FIXED and SK_SCALAR_IS_FLOAT"
#elif !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT)
#define SK_SCALAR_IS_FLOAT
#endif
#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT)
#error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT"
#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT)
// default is double, as that is faster given our impl uses doubles
// for intermediate calculations.
#define SK_MSCALAR_IS_DOUBLE
#endif
#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
#error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
#error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
#endif
// ensure the port has defined all of these, or none of them
#ifdef SK_A32_SHIFT
#if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)
#error "all or none of the 32bit SHIFT amounts must be defined"
#endif
#else
#if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)
#error "all or none of the 32bit SHIFT amounts must be defined"
#endif
#endif
#if !defined(SK_HAS_COMPILER_FEATURE)
#if defined(__has_feature)
#define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)
#else
#define SK_HAS_COMPILER_FEATURE(x) 0
#endif
#endif
#if !defined(SK_SUPPORT_GPU)
#define SK_SUPPORT_GPU 1
#endif
/**
* The clang static analyzer likes to know that when the program is not
* expected to continue (crash, assertion failure, etc). It will notice that
* some combination of parameters lead to a function call that does not return.
* It can then make appropriate assumptions about the parameters in code
* executed only if the non-returning function was *not* called.
*/
#if !defined(SkNO_RETURN_HINT)
#if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)
static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));
static inline void SkNO_RETURN_HINT() {}
#else
#define SkNO_RETURN_HINT() do {} while (false)
#endif
#endif
#if defined(SK_ZLIB_INCLUDE) && defined(SK_SYSTEM_ZLIB)
#error "cannot define both SK_ZLIB_INCLUDE and SK_SYSTEM_ZLIB"
#elif defined(SK_ZLIB_INCLUDE) || defined(SK_SYSTEM_ZLIB)
#define SK_HAS_ZLIB
#endif
///////////////////////////////////////////////////////////////////////////////
#ifndef SkNEW
#define SkNEW(type_name) (new type_name)
#define SkNEW_ARGS(type_name, args) (new type_name args)
#define SkNEW_ARRAY(type_name, count) (new type_name[(count)])
#define SkNEW_PLACEMENT(buf, type_name) (new (buf) type_name)
#define SkNEW_PLACEMENT_ARGS(buf, type_name, args) \
(new (buf) type_name args)
#define SkDELETE(obj) (delete (obj))
#define SkDELETE_ARRAY(array) (delete[] (array))
#endif
#ifndef SK_CRASH
#if 1 // set to 0 for infinite loop, which can help connecting gdb
#define SK_CRASH() do { SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0; } while (false)
#else
#define SK_CRASH() do { SkNO_RETURN_HINT(); } while (true)
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// SK_ENABLE_INST_COUNT defaults to 1 in DEBUG and 0 in RELEASE
#ifndef SK_ENABLE_INST_COUNT
#ifdef SK_DEBUG
#define SK_ENABLE_INST_COUNT 1
#else
#define SK_ENABLE_INST_COUNT 0
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
#if defined(SK_SOFTWARE_FLOAT) && defined(SK_SCALAR_IS_FLOAT)
// if this is defined, we convert floats to 2scompliment ints for compares
#ifndef SK_SCALAR_SLOW_COMPARES
#define SK_SCALAR_SLOW_COMPARES
#endif
#ifndef SK_USE_FLOATBITS
#define SK_USE_FLOATBITS
#endif
#endif
#ifdef SK_BUILD_FOR_WIN
// we want lean_and_mean when we include windows.h
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
#endif
#include <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

Просмотреть файл

@ -1,379 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkScalar_DEFINED
#define SkScalar_DEFINED
#include "SkFixed.h"
#include "SkFloatingPoint.h"
/** \file SkScalar.h
Types and macros for the data type SkScalar. This is the fractional numeric type
that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented
either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written
to allow the calling code to manipulate SkScalar values without knowing which representation
is in effect.
*/
#ifdef SK_SCALAR_IS_FLOAT
/** SkScalar is our type for fractional values and coordinates. Depending on
compile configurations, it is either represented as an IEEE float, or
as a 16.16 fixed point integer.
*/
typedef float SkScalar;
/** SK_Scalar1 is defined to be 1.0 represented as an SkScalar
*/
#define SK_Scalar1 (1.0f)
/** SK_Scalar1 is defined to be 1/2 represented as an SkScalar
*/
#define SK_ScalarHalf (0.5f)
/** SK_ScalarInfinity is defined to be infinity as an SkScalar
*/
#define SK_ScalarInfinity SK_FloatInfinity
/** SK_ScalarNegativeInfinity is defined to be negative infinity as an SkScalar
*/
#define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity
/** SK_ScalarMax is defined to be the largest value representable as an SkScalar
*/
#define SK_ScalarMax (3.402823466e+38f)
/** SK_ScalarMin is defined to be the smallest value representable as an SkScalar
*/
#define SK_ScalarMin (-SK_ScalarMax)
/** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar
*/
#define SK_ScalarNaN SK_FloatNaN
/** SkScalarIsNaN(n) returns true if argument is not a number
*/
static inline bool SkScalarIsNaN(float x) { return x != x; }
/** Returns true if x is not NaN and not infinite */
static inline bool SkScalarIsFinite(float x) {
// We rely on the following behavior of infinities and nans
// 0 * finite --> 0
// 0 * infinity --> NaN
// 0 * NaN --> NaN
float prod = x * 0;
// At this point, prod will either be NaN or 0
// Therefore we can return (prod == prod) or (0 == prod).
return prod == prod;
}
#ifdef SK_DEBUG
/** SkIntToScalar(n) returns its integer argument as an SkScalar
*
* If we're compiling in DEBUG mode, and can thus afford some extra runtime
* cycles, check to make sure that the parameter passed in has not already
* been converted to SkScalar. (A double conversion like this is harmless
* for SK_SCALAR_IS_FLOAT, but for SK_SCALAR_IS_FIXED this causes trouble.)
*
* Note that we need all of these method signatures to properly handle the
* various types that we pass into SkIntToScalar() to date:
* int, size_t, U8CPU, etc., even though what we really mean is "anything
* but a float".
*/
static inline float SkIntToScalar(signed int param) {
return (float)param;
}
static inline float SkIntToScalar(unsigned int param) {
return (float)param;
}
static inline float SkIntToScalar(signed long param) {
return (float)param;
}
static inline float SkIntToScalar(unsigned long param) {
return (float)param;
}
static inline float SkIntToScalar(float /* param */) {
/* If the parameter passed into SkIntToScalar is a float,
* one of two things has happened:
* 1. the parameter was an SkScalar (which is typedef'd to float)
* 2. the parameter was a float instead of an int
*
* Either way, it's not good.
*/
SkDEBUGFAIL("looks like you passed an SkScalar into SkIntToScalar");
return (float)0;
}
#else // not SK_DEBUG
/** SkIntToScalar(n) returns its integer argument as an SkScalar
*/
#define SkIntToScalar(n) ((float)(n))
#endif // not SK_DEBUG
/** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar
*/
#define SkFixedToScalar(x) SkFixedToFloat(x)
/** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed
*/
#define SkScalarToFixed(x) SkFloatToFixed(x)
#define SkScalarToFloat(n) (n)
#define SkFloatToScalar(n) (n)
#define SkScalarToDouble(n) (double)(n)
#define SkDoubleToScalar(n) (float)(n)
/** SkScalarFraction(x) returns the signed fractional part of the argument
*/
#define SkScalarFraction(x) sk_float_mod(x, 1.0f)
#define SkScalarFloorToScalar(x) sk_float_floor(x)
#define SkScalarCeilToScalar(x) sk_float_ceil(x)
#define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f)
#define SkScalarFloorToInt(x) sk_float_floor2int(x)
#define SkScalarCeilToInt(x) sk_float_ceil2int(x)
#define SkScalarRoundToInt(x) sk_float_round2int(x)
#define SkScalarTruncToInt(x) static_cast<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

Просмотреть файл

@ -1,397 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkStream_DEFINED
#define SkStream_DEFINED
#include "SkRefCnt.h"
#include "SkScalar.h"
class SkData;
class SK_API SkStream : public SkRefCnt {
public:
/**
* Attempts to open the specified file, and return a stream to it (using
* mmap if available). On success, the caller must call unref() on the
* returned object. On failure, returns NULL.
*/
static SkStream* NewFromFile(const char path[]);
SK_DECLARE_INST_COUNT(SkStream)
/** Called to rewind to the beginning of the stream. If this cannot be
done, return false.
*/
virtual bool rewind() = 0;
/** If this stream represents a file, this method returns the file's name.
If it does not, it returns NULL (the default behavior).
*/
virtual const char* getFileName();
/** Called to read or skip size number of bytes.
If buffer is NULL and size > 0, skip that many bytes, returning how many were skipped.
If buffer is NULL and size == 0, return the total length of the stream.
If buffer != NULL, copy the requested number of bytes into buffer, returning how many were copied.
@param buffer If buffer is NULL, ignore and just skip size bytes, otherwise copy size bytes into buffer
@param size The number of bytes to skip or copy
@return bytes read on success
*/
virtual size_t read(void* buffer, size_t size) = 0;
/** Return the total length of the stream.
*/
size_t getLength() { return this->read(NULL, 0); }
/** Skip the specified number of bytes, returning the actual number
of bytes that could be skipped.
*/
size_t skip(size_t bytes);
/** If the stream is backed by RAM, this method returns the starting
address for the data. If not (i.e. it is backed by a file or other
structure), this method returns NULL.
The default implementation returns NULL.
*/
virtual const void* getMemoryBase();
int8_t readS8();
int16_t readS16();
int32_t readS32();
uint8_t readU8() { return (uint8_t)this->readS8(); }
uint16_t readU16() { return (uint16_t)this->readS16(); }
uint32_t readU32() { return (uint32_t)this->readS32(); }
bool readBool() { return this->readU8() != 0; }
SkScalar readScalar();
size_t readPackedUInt();
/**
* Reconstitute an SkData object that was written to the stream
* using SkWStream::writeData().
*/
SkData* readData();
private:
typedef SkRefCnt INHERITED;
};
class SK_API SkWStream : SkNoncopyable {
public:
SK_DECLARE_INST_COUNT_ROOT(SkWStream)
virtual ~SkWStream();
/** Called to write bytes to a SkWStream. Returns true on success
@param buffer the address of at least size bytes to be written to the stream
@param size The number of bytes in buffer to write to the stream
@return true on success
*/
virtual bool write(const void* buffer, size_t size) = 0;
virtual void newline();
virtual void flush();
// helpers
bool write8(U8CPU);
bool write16(U16CPU);
bool write32(uint32_t);
bool writeText(const char text[]);
bool writeDecAsText(int32_t);
bool writeBigDecAsText(int64_t, int minDigits = 0);
bool writeHexAsText(uint32_t, int minDigits = 0);
bool writeScalarAsText(SkScalar);
bool writeBool(bool v) { return this->write8(v); }
bool writeScalar(SkScalar);
bool writePackedUInt(size_t);
bool writeStream(SkStream* input, size_t length);
/**
* Append an SkData object to the stream, such that it can be read
* out of the stream using SkStream::readData().
*
* Note that the encoding method used to write the SkData object
* to the stream may change over time. This method DOES NOT
* just write the raw content of the SkData object to the stream.
*/
bool writeData(const SkData*);
};
////////////////////////////////////////////////////////////////////////////////////////
#include "SkString.h"
struct SkFILE;
/** A stream that reads from a FILE*, which is opened in the constructor and
closed in the destructor
*/
class SK_API SkFILEStream : public SkStream {
public:
SK_DECLARE_INST_COUNT(SkFILEStream)
/** Initialize the stream by calling fopen on the specified path. Will be
closed in the destructor.
*/
explicit SkFILEStream(const char path[] = NULL);
virtual ~SkFILEStream();
/** Returns true if the current path could be opened.
*/
bool isValid() const { return fFILE != NULL; }
/** Close the current file, and open a new file with the specified
path. If path is NULL, just close the current file.
*/
void setPath(const char path[]);
virtual bool rewind() SK_OVERRIDE;
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
virtual const char* getFileName() SK_OVERRIDE;
private:
SkFILE* fFILE;
SkString fName;
typedef SkStream INHERITED;
};
/** A stream that reads from a file descriptor
*/
class SK_API SkFDStream : public SkStream {
public:
SK_DECLARE_INST_COUNT(SkFDStream)
/** Initialize the stream with a dup() of the specified file descriptor.
If closeWhenDone is true, then the descriptor will be closed in the
destructor.
*/
SkFDStream(int fileDesc, bool closeWhenDone);
virtual ~SkFDStream();
/** Returns true if the current path could be opened.
*/
bool isValid() const { return fFD >= 0; }
virtual bool rewind() SK_OVERRIDE;
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
virtual const char* getFileName() SK_OVERRIDE { return NULL; }
private:
int fFD;
bool fCloseWhenDone;
typedef SkStream INHERITED;
};
class SK_API SkMemoryStream : public SkStream {
public:
SK_DECLARE_INST_COUNT(SkMemoryStream)
SkMemoryStream();
/** We allocate (and free) the memory. Write to it via getMemoryBase()
*/
SkMemoryStream(size_t length);
/** if copyData is true, the stream makes a private copy of the data
*/
SkMemoryStream(const void* data, size_t length, bool copyData = false);
/**
* Use the specified data as the memory for this stream. The stream will
* call ref() on the data (assuming it is not null).
*/
SkMemoryStream(SkData*);
virtual ~SkMemoryStream();
/** Resets the stream to the specified data and length,
just like the constructor.
if copyData is true, the stream makes a private copy of the data
*/
virtual void setMemory(const void* data, size_t length,
bool copyData = false);
/** Replace any memory buffer with the specified buffer. The caller
must have allocated data with sk_malloc or sk_realloc, since it
will be freed with sk_free.
*/
void setMemoryOwned(const void* data, size_t length);
/**
* Return the stream's data in a SkData. The caller must call unref() when
* it is finished using the data.
*/
SkData* copyToData() const;
/**
* Use the specified data as the memory for this stream. The stream will
* call ref() on the data (assuming it is not null). The function returns
* the data parameter as a convenience.
*/
SkData* setData(SkData*);
void skipToAlign4();
virtual bool rewind() SK_OVERRIDE;
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
virtual const void* getMemoryBase() SK_OVERRIDE;
const void* getAtPos();
size_t seek(size_t offset);
size_t peek() const { return fOffset; }
private:
SkData* fData;
size_t fOffset;
typedef SkStream INHERITED;
};
/** \class SkBufferStream
This is a wrapper class that adds buffering to another stream.
The caller can provide the buffer, or ask SkBufferStream to allocated/free
it automatically.
*/
class SK_API SkBufferStream : public SkStream {
public:
SK_DECLARE_INST_COUNT(SkBufferStream)
/** Provide the stream to be buffered (proxy), and the size of the buffer that
should be used. This will be allocated and freed automatically. If bufferSize is 0,
a default buffer size will be used.
The proxy stream is referenced, and will be unreferenced in when the
bufferstream is destroyed.
*/
SkBufferStream(SkStream* proxy, size_t bufferSize = 0);
/** Provide the stream to be buffered (proxy), and a buffer and size to be used.
This buffer is owned by the caller, and must be at least bufferSize bytes big.
Passing NULL for buffer will cause the buffer to be allocated/freed automatically.
If buffer is not NULL, it is an error for bufferSize to be 0.
The proxy stream is referenced, and will be unreferenced in when the
bufferstream is destroyed.
*/
SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize);
virtual ~SkBufferStream();
virtual bool rewind() SK_OVERRIDE;
virtual const char* getFileName() SK_OVERRIDE;
virtual size_t read(void* buffer, size_t size) SK_OVERRIDE;
virtual const void* getMemoryBase() SK_OVERRIDE;
private:
enum {
kDefaultBufferSize = 128
};
// illegal
SkBufferStream(const SkBufferStream&);
SkBufferStream& operator=(const SkBufferStream&);
SkStream* fProxy;
char* fBuffer;
size_t fOrigBufferSize, fBufferSize, fBufferOffset;
bool fWeOwnTheBuffer;
void init(void*, size_t);
typedef SkStream INHERITED;
};
/////////////////////////////////////////////////////////////////////////////////////////////
class SK_API SkFILEWStream : public SkWStream {
public:
SK_DECLARE_INST_COUNT(SkFILEWStream)
SkFILEWStream(const char path[]);
virtual ~SkFILEWStream();
/** Returns true if the current path could be opened.
*/
bool isValid() const { return fFILE != NULL; }
virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
virtual void flush() SK_OVERRIDE;
private:
SkFILE* fFILE;
typedef SkWStream INHERITED;
};
class SkMemoryWStream : public SkWStream {
public:
SK_DECLARE_INST_COUNT(SkMemoryWStream)
SkMemoryWStream(void* buffer, size_t size);
virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
size_t bytesWritten() const { return fBytesWritten; }
private:
char* fBuffer;
size_t fMaxLength;
size_t fBytesWritten;
typedef SkWStream INHERITED;
};
class SK_API SkDynamicMemoryWStream : public SkWStream {
public:
SK_DECLARE_INST_COUNT(SkDynamicMemoryWStream)
SkDynamicMemoryWStream();
virtual ~SkDynamicMemoryWStream();
virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
// random access write
// modifies stream and returns true if offset + size is less than or equal to getOffset()
bool write(const void* buffer, size_t offset, size_t size);
bool read(void* buffer, size_t offset, size_t size);
size_t getOffset() const { return fBytesWritten; }
size_t bytesWritten() const { return fBytesWritten; }
// copy what has been written to the stream into dst
void copyTo(void* dst) const;
/**
* Return a copy of the data written so far. This call is responsible for
* calling unref() when they are finished with the data.
*/
SkData* copyToData() const;
// reset the stream to its original state
void reset();
void padToAlign4();
private:
struct Block;
Block* fHead;
Block* fTail;
size_t fBytesWritten;
mutable SkData* fCopy; // is invalidated if we write after it is created
void invalidateCopy();
typedef SkWStream INHERITED;
};
class SK_API SkDebugWStream : public SkWStream {
public:
SK_DECLARE_INST_COUNT(SkDebugWStream)
// overrides
virtual bool write(const void* buffer, size_t size) SK_OVERRIDE;
virtual void newline() SK_OVERRIDE;
private:
typedef SkWStream INHERITED;
};
// for now
typedef SkFILEStream SkURLStream;
#endif

Просмотреть файл

@ -1,76 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkTScopedPtr_DEFINED
#define SkTScopedPtr_DEFINED
#include "SkTypes.h"
/** \class SkTScopedPtr
A SkTScopedPtr<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

Просмотреть файл

@ -1,239 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkTSearch_DEFINED
#define SkTSearch_DEFINED
#include "SkTypes.h"
/**
* All of the SkTSearch variants want to return the index (0...N-1) of the
* found element, or the bit-not of where to insert the element.
*
* At a simple level, if the return value is negative, it was not found.
*
* For clients that want to insert the new element if it was not found, use
* the following logic:
*
* int index = SkTSearch(...);
* if (index >= 0) {
* // found at index
* } else {
* index = ~index; // now we are positive
* // insert at index
* }
*/
template <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

Просмотреть файл

@ -1,68 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkThread_DEFINED
#define SkThread_DEFINED
#include "SkTypes.h"
#include "SkThread_platform.h"
/****** SkThread_platform needs to define the following...
int32_t sk_atomic_inc(int32_t*);
int32_t sk_atomic_add(int32_t*, int32_t);
int32_t sk_atomic_dec(int32_t*);
int32_t sk_atomic_conditional_inc(int32_t*);
class SkMutex {
public:
SkMutex();
~SkMutex();
void acquire();
void release();
};
****************/
class SkAutoMutexAcquire : SkNoncopyable {
public:
explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) {
SkASSERT(fMutex != NULL);
mutex.acquire();
}
SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) {
if (mutex) {
mutex->acquire();
}
}
/** If the mutex has not been release, release it now.
*/
~SkAutoMutexAcquire() {
if (fMutex) {
fMutex->release();
}
}
/** If the mutex has not been release, release it now.
*/
void release() {
if (fMutex) {
fMutex->release();
fMutex = NULL;
}
}
private:
SkBaseMutex* fMutex;
};
#endif

Просмотреть файл

@ -1,294 +0,0 @@
/*
* Copyright 2008 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkWriter32_DEFINED
#define SkWriter32_DEFINED
#include "SkTypes.h"
#include "SkScalar.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkRRect.h"
#include "SkMatrix.h"
#include "SkRegion.h"
class SkStream;
class SkWStream;
class SkWriter32 : SkNoncopyable {
struct BlockHeader;
public:
/**
* The caller can specify an initial block of storage, which the caller manages.
* SkWriter32 will not attempt to free this in its destructor. It is up to the
* implementation to decide if, and how much, of the storage to utilize, and it
* is possible that it may be ignored entirely.
*/
SkWriter32(size_t minSize, void* initialStorage, size_t storageSize);
SkWriter32(size_t minSize)
: fHead(NULL)
, fTail(NULL)
, fMinSize(minSize)
, fSize(0)
, fWrittenBeforeLastBlock(0)
{}
~SkWriter32();
// return the current offset (will always be a multiple of 4)
uint32_t bytesWritten() const { return fSize; }
// DEPRECATED: use byetsWritten instead
uint32_t size() const { return this->bytesWritten(); }
void reset();
// size MUST be multiple of 4
uint32_t* reserve(size_t size) {
SkASSERT(SkAlign4(size) == size);
Block* block = fTail;
if (NULL == block || block->available() < size) {
block = this->doReserve(size);
}
fSize += size;
return block->alloc(size);
}
void reset(void* storage, size_t size);
bool writeBool(bool value) {
this->writeInt(value);
return value;
}
void writeInt(int32_t value) {
*(int32_t*)this->reserve(sizeof(value)) = value;
}
void write8(int32_t value) {
*(int32_t*)this->reserve(sizeof(value)) = value & 0xFF;
}
void write16(int32_t value) {
*(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF;
}
void write32(int32_t value) {
*(int32_t*)this->reserve(sizeof(value)) = value;
}
void writePtr(void* ptr) {
// Since we "know" that we're always 4-byte aligned, we can tell the
// compiler that here, by assigning to an int32 ptr.
int32_t* addr = (int32_t*)this->reserve(sizeof(void*));
if (4 == sizeof(void*)) {
*(void**)addr = ptr;
} else {
memcpy(addr, &ptr, sizeof(void*));
}
}
void writeScalar(SkScalar value) {
*(SkScalar*)this->reserve(sizeof(value)) = value;
}
void writePoint(const SkPoint& pt) {
*(SkPoint*)this->reserve(sizeof(pt)) = pt;
}
void writeRect(const SkRect& rect) {
*(SkRect*)this->reserve(sizeof(rect)) = rect;
}
void writeRRect(const SkRRect& rrect) {
rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory));
}
void writePath(const SkPath& path) {
size_t size = path.writeToMemory(NULL);
SkASSERT(SkAlign4(size) == size);
path.writeToMemory(this->reserve(size));
}
void writeMatrix(const SkMatrix& matrix) {
size_t size = matrix.writeToMemory(NULL);
SkASSERT(SkAlign4(size) == size);
matrix.writeToMemory(this->reserve(size));
}
void writeRegion(const SkRegion& rgn) {
size_t size = rgn.writeToMemory(NULL);
SkASSERT(SkAlign4(size) == size);
rgn.writeToMemory(this->reserve(size));
}
// write count bytes (must be a multiple of 4)
void writeMul4(const void* values, size_t size) {
this->write(values, size);
}
/**
* Write size bytes from values. size must be a multiple of 4, though
* values need not be 4-byte aligned.
*/
void write(const void* values, size_t size) {
SkASSERT(SkAlign4(size) == size);
// if we could query how much is avail in the current block, we might
// copy that much, and then alloc the rest. That would reduce the waste
// in the current block
memcpy(this->reserve(size), values, size);
}
/**
* Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be
* filled in with zeroes.
*/
uint32_t* reservePad(size_t size);
/**
* Write size bytes from src, and pad to 4 byte alignment with zeroes.
*/
void writePad(const void* src, size_t size);
/**
* Writes a string to the writer, which can be retrieved with
* SkReader32::readString().
* The length can be specified, or if -1 is passed, it will be computed by
* calling strlen(). The length must be < 0xFFFF
*/
void writeString(const char* str, size_t len = (size_t)-1);
/**
* Computes the size (aligned to multiple of 4) need to write the string
* in a call to writeString(). If the length is not specified, it will be
* computed by calling strlen().
*/
static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
// return the address of the 4byte int at the specified offset (which must
// be a multiple of 4. This does not allocate any new space, so the returned
// address is only valid for 1 int.
uint32_t* peek32(size_t offset);
/**
* Move the cursor back to offset bytes from the beginning.
* This has the same restrictions as peek32: offset must be <= size() and
* offset must be a multiple of 4.
*/
void rewindToOffset(size_t offset);
// copy into a single buffer (allocated by caller). Must be at least size()
void flatten(void* dst) const;
// read from the stream, and write up to length bytes. Return the actual
// number of bytes written.
size_t readFromStream(SkStream*, size_t length);
bool writeToStream(SkWStream*);
private:
struct Block {
Block* fNext;
char* fBasePtr;
size_t fSizeOfBlock; // total space allocated (after this)
size_t fAllocatedSoFar; // space used so far
size_t available() const { return fSizeOfBlock - fAllocatedSoFar; }
char* base() { return fBasePtr; }
const char* base() const { return fBasePtr; }
uint32_t* alloc(size_t size) {
SkASSERT(SkAlign4(size) == size);
SkASSERT(this->available() >= size);
void* ptr = this->base() + fAllocatedSoFar;
fAllocatedSoFar += size;
SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
return (uint32_t*)ptr;
}
uint32_t* peek32(size_t offset) {
SkASSERT(offset <= fAllocatedSoFar + 4);
void* ptr = this->base() + offset;
return (uint32_t*)ptr;
}
void rewind() {
fNext = NULL;
fAllocatedSoFar = 0;
// keep fSizeOfBlock as is
}
static Block* Create(size_t size) {
SkASSERT(SkIsAlign4(size));
Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
block->fNext = NULL;
block->fBasePtr = (char*)(block + 1);
block->fSizeOfBlock = size;
block->fAllocatedSoFar = 0;
return block;
}
Block* initFromStorage(void* storage, size_t size) {
SkASSERT(SkIsAlign4((intptr_t)storage));
SkASSERT(SkIsAlign4(size));
Block* block = this;
block->fNext = NULL;
block->fBasePtr = (char*)storage;
block->fSizeOfBlock = size;
block->fAllocatedSoFar = 0;
return block;
}
};
enum {
MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t)
};
Block fExternalBlock;
Block* fHead;
Block* fTail;
size_t fMinSize;
uint32_t fSize;
// sum of bytes written in all blocks *before* fTail
uint32_t fWrittenBeforeLastBlock;
bool isHeadExternallyAllocated() const {
return fHead == &fExternalBlock;
}
Block* newBlock(size_t bytes);
// only call from reserve()
Block* doReserve(size_t bytes);
SkDEBUGCODE(void validate() const;)
};
/**
* Helper class to allocated SIZE bytes as part of the writer, and to provide
* that storage to the constructor as its initial storage buffer.
*
* This wrapper ensures proper alignment rules are met for the storage.
*/
template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
public:
SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {}
private:
union {
void* fPtrAlignment;
double fDoubleAlignment;
char fStorage[SIZE];
} fData;
};
#endif

Просмотреть файл

@ -1,50 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBlendImageFilter_DEFINED
#define SkBlendImageFilter_DEFINED
#include "SkImageFilter.h"
#include "SkBitmap.h"
class SK_API SkBlendImageFilter : public SkImageFilter {
public:
enum Mode {
kNormal_Mode,
kMultiply_Mode,
kScreen_Mode,
kDarken_Mode,
kLighten_Mode,
};
SkBlendImageFilter(Mode mode, SkImageFilter* background, SkImageFilter* foreground = NULL);
~SkBlendImageFilter();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlendImageFilter)
virtual bool onFilterImage(Proxy* proxy,
const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* dst,
SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
#endif
protected:
explicit SkBlendImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
private:
Mode fMode;
typedef SkImageFilter INHERITED;
SkImageFilter* getBackgroundInput() { return getInput(0); }
SkImageFilter* getForegroundInput() { return getInput(1); }
};
#endif

Просмотреть файл

@ -1,73 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkMorphologyImageFilter_DEFINED
#define SkMorphologyImageFilter_DEFINED
#include "SkImageFilter.h"
#include "SkSize.h"
class SK_API SkMorphologyImageFilter : public SkImageFilter {
public:
SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input);
protected:
SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
#endif
SkISize radius() const { return fRadius; }
private:
SkISize fRadius;
typedef SkImageFilter INHERITED;
};
class SK_API SkDilateImageFilter : public SkMorphologyImageFilter {
public:
SkDilateImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL)
: INHERITED(radiusX, radiusY, input) {}
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter)
protected:
SkDilateImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
typedef SkMorphologyImageFilter INHERITED;
};
class SK_API SkErodeImageFilter : public SkMorphologyImageFilter {
public:
SkErodeImageFilter(int radiusX, int radiusY, SkImageFilter* input = NULL)
: INHERITED(radiusX, radiusY, input) {}
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter)
protected:
SkErodeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
private:
typedef SkMorphologyImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -1,43 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkRectShaderImageFilter_DEFINED
#define SkRectShaderImageFilter_DEFINED
#include "SkImageFilter.h"
#include "SkRect.h"
class SkShader;
class SK_API SkRectShaderImageFilter : public SkImageFilter {
public:
/**
* The SkShader object will have its refcnt increased as it becomes a member of the
* SkRectShaderImageFilter object returned by this function. It cannot be NULL.
* The region parameter is used to specify on which region the shader is applied.
*/
static SkRectShaderImageFilter* Create(SkShader* s, const SkRect& rect);
virtual ~SkRectShaderImageFilter();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter)
protected:
SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
private:
SkRectShaderImageFilter(SkShader* s, const SkRect& rect);
SkShader* fShader;
SkRect fRect;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -1,47 +0,0 @@
#ifndef _SkTestImageFilters_h
#define _SkTestImageFilters_h
#include "SkImageFilter.h"
#include "SkPoint.h"
class SK_API SkComposeImageFilter : public SkImageFilter {
public:
SkComposeImageFilter(SkImageFilter* outer, SkImageFilter* inner) : INHERITED(outer, inner) {}
virtual ~SkComposeImageFilter();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeImageFilter)
protected:
SkComposeImageFilter(SkFlattenableReadBuffer& buffer);
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
private:
typedef SkImageFilter INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
// Fun mode that scales down (only) and then scales back up to look pixelated
class SK_API SkDownSampleImageFilter : public SkImageFilter {
public:
SkDownSampleImageFilter(SkScalar scale) : INHERITED(0), fScale(scale) {}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDownSampleImageFilter)
protected:
SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
private:
SkScalar fScale;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -1,65 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrAARectRenderer_DEFINED
#define GrAARectRenderer_DEFINED
#include "GrRect.h"
#include "GrRefCnt.h"
class GrGpu;
class GrDrawTarget;
class GrIndexBuffer;
/*
* This class wraps helper functions that draw AA rects (filled & stroked)
*/
class GrAARectRenderer : public GrRefCnt {
public:
SK_DECLARE_INST_COUNT(GrAARectRenderer)
GrAARectRenderer()
: fAAFillRectIndexBuffer(NULL)
, fAAStrokeRectIndexBuffer(NULL) {
}
void reset();
~GrAARectRenderer() {
this->reset();
}
// TODO: potentialy fuse the fill & stroke methods and differentiate
// btween them by passing in strokeWidth (<0 means fill).
// TODO: Remove the useVertexCoverage boolean. Just use it all the time
// since we now have a coverage vertex attribute
void fillAARect(GrGpu* gpu,
GrDrawTarget* target,
const GrRect& devRect,
bool useVertexCoverage);
void strokeAARect(GrGpu* gpu,
GrDrawTarget* target,
const GrRect& devRect,
const GrVec& devStrokeSize,
bool useVertexCoverage);
private:
GrIndexBuffer* fAAFillRectIndexBuffer;
GrIndexBuffer* fAAStrokeRectIndexBuffer;
GrIndexBuffer* aaFillRectIndexBuffer(GrGpu* gpu);
static int aaStrokeRectIndexCount();
GrIndexBuffer* aaStrokeRectIndexBuffer(GrGpu* gpu);
typedef GrRefCnt INHERITED;
};
#endif // GrAARectRenderer_DEFINED

Просмотреть файл

@ -1,211 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrEffectStage_DEFINED
#define GrEffectStage_DEFINED
#include "GrBackendEffectFactory.h"
#include "GrEffect.h"
#include "SkMatrix.h"
#include "GrTypes.h"
#include "SkShader.h"
class GrEffectStage {
public:
GrEffectStage()
: fEffectRef (NULL) {
GR_DEBUGCODE(fSavedCoordChangeCnt = 0;)
}
~GrEffectStage() {
GrSafeUnref(fEffectRef);
GrAssert(0 == fSavedCoordChangeCnt);
}
bool operator ==(const GrEffectStage& other) const {
// first handle cases where one or the other has no effect
if (NULL == fEffectRef) {
return NULL == other.fEffectRef;
} else if (NULL == other.fEffectRef) {
return false;
}
if (!(*this->getEffect())->isEqual(*other.getEffect())) {
return false;
}
return fCoordChangeMatrix == other.fCoordChangeMatrix;
}
bool operator !=(const GrEffectStage& s) const { return !(*this == s); }
GrEffectStage& operator =(const GrEffectStage& other) {
GrSafeAssign(fEffectRef, other.fEffectRef);
if (NULL != fEffectRef) {
fCoordChangeMatrix = other.fCoordChangeMatrix;
}
return *this;
}
/**
* This is called when the coordinate system in which the geometry is specified will change.
*
* @param matrix The transformation from the old coord system in which geometry is specified
* to the new one from which it will actually be drawn.
*/
void localCoordChange(const SkMatrix& matrix) { fCoordChangeMatrix.preConcat(matrix); }
class SavedCoordChange {
private:
SkMatrix fCoordChangeMatrix;
GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectRef;)
friend class GrEffectStage;
};
/**
* This gets the current coordinate system change. It is the accumulation of
* localCoordChange calls since the effect was installed. It is used when then caller
* wants to temporarily change the source geometry coord system, draw something, and then
* restore the previous coord system (e.g. temporarily draw in device coords).
*/
void saveCoordChange(SavedCoordChange* savedCoordChange) const {
savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
GrAssert(NULL == savedCoordChange->fEffectRef.get());
GR_DEBUGCODE(GrSafeRef(fEffectRef);)
GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef);)
GR_DEBUGCODE(++fSavedCoordChangeCnt);
}
/**
* This balances the saveCoordChange call.
*/
void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef);
GR_DEBUGCODE(--fSavedCoordChangeCnt);
GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);)
}
/**
* Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its
* GrEffect to be recycled through the cache.
*/
class DeferredStage {
public:
DeferredStage() : fEffect(NULL) {
SkDEBUGCODE(fInitialized = false;)
}
~DeferredStage() {
if (NULL != fEffect) {
fEffect->decDeferredRefCounts();
}
}
void saveFrom(const GrEffectStage& stage) {
GrAssert(!fInitialized);
if (NULL != stage.fEffectRef) {
stage.fEffectRef->get()->incDeferredRefCounts();
fEffect = stage.fEffectRef->get();
fCoordChangeMatrix = stage.fCoordChangeMatrix;
fVertexAttribIndices[0] = stage.fVertexAttribIndices[0];
fVertexAttribIndices[1] = stage.fVertexAttribIndices[1];
}
SkDEBUGCODE(fInitialized = true;)
}
void restoreTo(GrEffectStage* stage) {
GrAssert(fInitialized);
const GrEffectRef* oldEffectRef = stage->fEffectRef;
if (NULL != fEffect) {
stage->fEffectRef = GrEffect::CreateEffectRef(fEffect);
stage->fCoordChangeMatrix = fCoordChangeMatrix;
stage->fVertexAttribIndices[0] = fVertexAttribIndices[0];
stage->fVertexAttribIndices[1] = fVertexAttribIndices[1];
} else {
stage->fEffectRef = NULL;
}
SkSafeUnref(oldEffectRef);
}
bool isEqual(const GrEffectStage& stage) const {
if (NULL == stage.fEffectRef) {
return NULL == fEffect;
} else if (NULL == fEffect) {
return false;
}
if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0]
|| fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) {
return false;
}
if (!(*stage.getEffect())->isEqual(*fEffect)) {
return false;
}
return fCoordChangeMatrix == stage.fCoordChangeMatrix;
}
private:
const GrEffect* fEffect;
SkMatrix fCoordChangeMatrix;
int fVertexAttribIndices[2];
SkDEBUGCODE(bool fInitialized;)
};
/**
* Gets the matrix representing all changes of coordinate system since the GrEffect was
* installed in the stage.
*/
const SkMatrix& getCoordChangeMatrix() const { return fCoordChangeMatrix; }
void reset() {
GrSafeSetNull(fEffectRef);
}
const GrEffectRef* setEffect(const GrEffectRef* EffectRef) {
GrAssert(0 == fSavedCoordChangeCnt);
GrSafeAssign(fEffectRef, EffectRef);
fCoordChangeMatrix.reset();
fVertexAttribIndices[0] = -1;
fVertexAttribIndices[1] = -1;
return EffectRef;
}
const GrEffectRef* setEffect(const GrEffectRef* EffectRef, int attr0, int attr1 = -1) {
GrAssert(0 == fSavedCoordChangeCnt);
GrSafeAssign(fEffectRef, EffectRef);
fCoordChangeMatrix.reset();
fVertexAttribIndices[0] = attr0;
fVertexAttribIndices[1] = attr1;
return EffectRef;
}
const GrEffectRef* getEffect() const { return fEffectRef; }
const int* getVertexAttribIndices() const { return fVertexAttribIndices; }
int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); }
private:
SkMatrix fCoordChangeMatrix;
const GrEffectRef* fEffectRef;
int fVertexAttribIndices[2];
GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;)
};
#endif

Просмотреть файл

@ -1,30 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrNoncopyable_DEFINED
#define GrNoncopyable_DEFINED
#include "GrTypes.h"
/**
* Base for classes that want to disallow copying themselves. It makes its
* copy-constructor and assignment operators private (and unimplemented).
*/
class GR_API GrNoncopyable {
public:
GrNoncopyable() {}
private:
// illegal
GrNoncopyable(const GrNoncopyable&);
GrNoncopyable& operator=(const GrNoncopyable&);
};
#endif

Просмотреть файл

@ -1,46 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrOvalRenderer_DEFINED
#define GrOvalRenderer_DEFINED
#include "GrContext.h"
#include "GrPaint.h"
#include "GrRefCnt.h"
#include "GrRect.h"
class GrContext;
class GrDrawTarget;
class GrPaint;
class SkStrokeRec;
/*
* This class wraps helper functions that draw ovals (filled & stroked)
*/
class GrOvalRenderer : public GrRefCnt {
public:
SK_DECLARE_INST_COUNT(GrOvalRenderer)
GrOvalRenderer() {}
~GrOvalRenderer() {}
bool drawOval(GrDrawTarget* target, const GrContext* context, const GrPaint& paint,
const GrRect& oval, const SkStrokeRec& stroke);
private:
void drawEllipse(GrDrawTarget* target, const GrPaint& paint,
const GrRect& ellipse,
const SkStrokeRec& stroke);
void drawCircle(GrDrawTarget* target, const GrPaint& paint,
const GrRect& circle,
const SkStrokeRec& stroke);
typedef GrRefCnt INHERITED;
};
#endif // GrOvalRenderer_DEFINED

Просмотреть файл

@ -1,33 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrRefCnt_DEFINED
#define GrRefCnt_DEFINED
#include "GrTypes.h"
#include "SkRefCnt.h"
typedef SkRefCnt GrRefCnt;
typedef SkAutoRef GrAutoRef;
typedef SkAutoUnref GrAutoUnref;
#define GrSafeRef SkSafeRef
#define GrSafeUnref SkSafeUnref
#define GrSafeAssign(a, b) SkRefCnt_SafeAssign(a, b)
template<typename T>
static inline void GrSafeSetNull(T*& obj) {
if (NULL != obj) {
obj->unref();
obj = NULL;
}
}
#endif

Просмотреть файл

@ -1,60 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrTextContext_DEFINED
#define GrTextContext_DEFINED
#include "GrContext.h"
#include "GrGlyph.h"
#include "GrPaint.h"
class GrContext;
class GrTextStrike;
class GrFontScaler;
class GrDrawTarget;
class GrTextContext {
public:
GrTextContext(GrContext*, const GrPaint&);
~GrTextContext();
void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
GrFontScaler*);
void flush(); // optional; automatically called by destructor
private:
GrPaint fPaint;
GrContext* fContext;
GrDrawTarget* fDrawTarget;
GrFontScaler* fScaler;
GrTextStrike* fStrike;
inline void flushGlyphs();
void setupDrawTarget();
enum {
kMinRequestedGlyphs = 1,
kDefaultRequestedGlyphs = 64,
kMinRequestedVerts = kMinRequestedGlyphs * 4,
kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
};
SkPoint* fVertices;
int32_t fMaxVertices;
GrTexture* fCurrTexture;
int fCurrVertex;
GrIRect fClipRect;
GrContext::AutoMatrix fAutoMatrix;
};
#endif

Просмотреть файл

@ -1,326 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLInterface_DEFINED
#define GrGLInterface_DEFINED
#include "GrGLFunctions.h"
#include "GrRefCnt.h"
////////////////////////////////////////////////////////////////////////////////
/**
* Classifies GL contexts (currently as Desktop vs. ES2). This is a bitfield.
* A GrGLInterface (defined below) may support multiple bindings.
*/
enum GrGLBinding {
kNone_GrGLBinding = 0x0,
kDesktop_GrGLBinding = 0x01,
kES2_GrGLBinding = 0x02,
// for iteration of GrGLBindings
kFirstGrGLBinding = kDesktop_GrGLBinding,
kLastGrGLBinding = kES2_GrGLBinding
};
////////////////////////////////////////////////////////////////////////////////
/**
* Rather than depend on platform-specific GL headers and libraries, we require
* the client to provide a struct of GL function pointers. This struct can be
* specified per-GrContext as a parameter to GrContext::Create. If NULL is
* passed to Create then the "default" GL interface is used. If the default is
* also NULL GrContext creation will fail.
*
* The default interface is returned by GrGLDefaultInterface. This function's
* implementation is platform-specific. Several have been provided, along with
* an implementation that simply returns NULL. It is implementation-specific
* whether the same GrGLInterface is returned or whether a new one is created
* at each call. Some platforms may not be able to use a single GrGLInterface
* because extension function ptrs vary across contexts. Note that GrGLInterface
* is ref-counted. So if the same object is returned by multiple calls to
* GrGLDefaultInterface, each should bump the ref count.
*
* By defining GR_GL_PER_GL_CALL_IFACE_CALLBACK to 1 the client can specify a
* callback function that will be called prior to each GL function call. See
* comments in GrGLConfig.h
*/
struct GrGLInterface;
const GrGLInterface* GrGLDefaultInterface();
/**
* Creates a GrGLInterface for a "native" GL context (e.g. WGL on windows,
* GLX on linux, AGL on Mac). On platforms that have context-specific function
* pointers for GL extensions (e.g. windows) the returned interface is only
* valid for the context that was current at creation.
*/
const GrGLInterface* GrGLCreateNativeInterface();
#if SK_MESA
/**
* Creates a GrGLInterface for an OSMesa context.
*/
const GrGLInterface* GrGLCreateMesaInterface();
#endif
#if SK_ANGLE
/**
* Creates a GrGLInterface for an ANGLE context.
*/
const GrGLInterface* GrGLCreateANGLEInterface();
#endif
/**
* Creates a null GrGLInterface that doesn't draw anything. Used for measuring
* CPU overhead.
*/
const GrGLInterface* GrGLCreateNullInterface();
/**
* Creates a debugging GrGLInterface that doesn't draw anything. Used for
* finding memory leaks and invalid memory accesses.
*/
const GrGLInterface* GrGLCreateDebugInterface();
#if GR_GL_PER_GL_FUNC_CALLBACK
typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*);
typedef intptr_t GrGLInterfaceCallbackData;
#endif
/*
* GrContext uses the following interface to make all calls into OpenGL. When a
* GrContext is created it is given a GrGLInterface. The interface's function
* pointers must be valid for the OpenGL context associated with the GrContext.
* On some platforms, such as Windows, function pointers for OpenGL extensions
* may vary between OpenGL contexts. So the caller must be careful to use a
* GrGLInterface initialized for the correct context. All functions that should
* be available based on the OpenGL's version and extension string must be
* non-NULL or GrContext creation will fail. This can be tested with the
* validate() method when the OpenGL context has been made current.
*/
struct GR_API GrGLInterface : public GrRefCnt {
private:
// simple wrapper class that exists only to initialize a pointer to NULL
template <typename FNPTR_TYPE> class GLPtr {
public:
GLPtr() : fPtr(NULL) {}
GLPtr operator =(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
operator FNPTR_TYPE() const { return fPtr; }
private:
FNPTR_TYPE fPtr;
};
typedef GrRefCnt INHERITED;
public:
SK_DECLARE_INST_COUNT(GrGLInterface)
GrGLInterface();
// Validates that the GrGLInterface supports a binding. This means that
// the GrGLinterface advertises the binding in fBindingsExported and all
// the necessary function pointers have been initialized. The interface is
// validated for the current OpenGL context.
bool validate(GrGLBinding binding) const;
// Indicator variable specifying the type of GL implementation
// exported: GLES2 and/or Desktop.
GrGLBinding fBindingsExported;
GLPtr<GrGLActiveTextureProc> fActiveTexture;
GLPtr<GrGLAttachShaderProc> fAttachShader;
GLPtr<GrGLBeginQueryProc> fBeginQuery;
GLPtr<GrGLBindAttribLocationProc> fBindAttribLocation;
GLPtr<GrGLBindBufferProc> fBindBuffer;
GLPtr<GrGLBindFragDataLocationProc> fBindFragDataLocation;
GLPtr<GrGLBindFragDataLocationIndexedProc> fBindFragDataLocationIndexed;
GLPtr<GrGLBindFramebufferProc> fBindFramebuffer;
GLPtr<GrGLBindRenderbufferProc> fBindRenderbuffer;
GLPtr<GrGLBindTextureProc> fBindTexture;
GLPtr<GrGLBindVertexArrayProc> fBindVertexArray;
GLPtr<GrGLBlendColorProc> fBlendColor;
GLPtr<GrGLBlendFuncProc> fBlendFunc;
GLPtr<GrGLBlitFramebufferProc> fBlitFramebuffer;
GLPtr<GrGLBufferDataProc> fBufferData;
GLPtr<GrGLBufferSubDataProc> fBufferSubData;
GLPtr<GrGLCheckFramebufferStatusProc> fCheckFramebufferStatus;
GLPtr<GrGLClearProc> fClear;
GLPtr<GrGLClearColorProc> fClearColor;
GLPtr<GrGLClearStencilProc> fClearStencil;
GLPtr<GrGLColorMaskProc> fColorMask;
GLPtr<GrGLCompileShaderProc> fCompileShader;
GLPtr<GrGLCompressedTexImage2DProc> fCompressedTexImage2D;
GLPtr<GrGLCreateProgramProc> fCreateProgram;
GLPtr<GrGLCreateShaderProc> fCreateShader;
GLPtr<GrGLCullFaceProc> fCullFace;
GLPtr<GrGLDeleteBuffersProc> fDeleteBuffers;
GLPtr<GrGLDeleteFramebuffersProc> fDeleteFramebuffers;
GLPtr<GrGLDeleteProgramProc> fDeleteProgram;
GLPtr<GrGLDeleteQueriesProc> fDeleteQueries;
GLPtr<GrGLDeleteRenderbuffersProc> fDeleteRenderbuffers;
GLPtr<GrGLDeleteShaderProc> fDeleteShader;
GLPtr<GrGLDeleteTexturesProc> fDeleteTextures;
GLPtr<GrGLDeleteVertexArraysProc> fDeleteVertexArrays;
GLPtr<GrGLDepthMaskProc> fDepthMask;
GLPtr<GrGLDisableProc> fDisable;
GLPtr<GrGLDisableVertexAttribArrayProc> fDisableVertexAttribArray;
GLPtr<GrGLDrawArraysProc> fDrawArrays;
GLPtr<GrGLDrawBufferProc> fDrawBuffer;
GLPtr<GrGLDrawBuffersProc> fDrawBuffers;
GLPtr<GrGLDrawElementsProc> fDrawElements;
GLPtr<GrGLEnableProc> fEnable;
GLPtr<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;
GLPtr<GrGLEndQueryProc> fEndQuery;
GLPtr<GrGLFinishProc> fFinish;
GLPtr<GrGLFlushProc> fFlush;
GLPtr<GrGLFramebufferRenderbufferProc> fFramebufferRenderbuffer;
GLPtr<GrGLFramebufferTexture2DProc> fFramebufferTexture2D;
GLPtr<GrGLFramebufferTexture2DMultisampleProc> fFramebufferTexture2DMultisample;
GLPtr<GrGLFrontFaceProc> fFrontFace;
GLPtr<GrGLGenBuffersProc> fGenBuffers;
GLPtr<GrGLGenFramebuffersProc> fGenFramebuffers;
GLPtr<GrGLGenQueriesProc> fGenQueries;
GLPtr<GrGLGenRenderbuffersProc> fGenRenderbuffers;
GLPtr<GrGLGenTexturesProc> fGenTextures;
GLPtr<GrGLGenVertexArraysProc> fGenVertexArrays;
GLPtr<GrGLGetBufferParameterivProc> fGetBufferParameteriv;
GLPtr<GrGLGetErrorProc> fGetError;
GLPtr<GrGLGetFramebufferAttachmentParameterivProc> fGetFramebufferAttachmentParameteriv;
GLPtr<GrGLGetIntegervProc> fGetIntegerv;
GLPtr<GrGLGetQueryObjecti64vProc> fGetQueryObjecti64v;
GLPtr<GrGLGetQueryObjectivProc> fGetQueryObjectiv;
GLPtr<GrGLGetQueryObjectui64vProc> fGetQueryObjectui64v;
GLPtr<GrGLGetQueryObjectuivProc> fGetQueryObjectuiv;
GLPtr<GrGLGetQueryivProc> fGetQueryiv;
GLPtr<GrGLGetProgramInfoLogProc> fGetProgramInfoLog;
GLPtr<GrGLGetProgramivProc> fGetProgramiv;
GLPtr<GrGLGetRenderbufferParameterivProc> fGetRenderbufferParameteriv;
GLPtr<GrGLGetShaderInfoLogProc> fGetShaderInfoLog;
GLPtr<GrGLGetShaderivProc> fGetShaderiv;
GLPtr<GrGLGetStringProc> fGetString;
GLPtr<GrGLGetStringiProc> fGetStringi;
GLPtr<GrGLGetTexLevelParameterivProc> fGetTexLevelParameteriv;
GLPtr<GrGLGetUniformLocationProc> fGetUniformLocation;
GLPtr<GrGLLineWidthProc> fLineWidth;
GLPtr<GrGLLinkProgramProc> fLinkProgram;
GLPtr<GrGLMapBufferProc> fMapBuffer;
GLPtr<GrGLPixelStoreiProc> fPixelStorei;
GLPtr<GrGLQueryCounterProc> fQueryCounter;
GLPtr<GrGLReadBufferProc> fReadBuffer;
GLPtr<GrGLReadPixelsProc> fReadPixels;
GLPtr<GrGLRenderbufferStorageProc> fRenderbufferStorage;
GLPtr<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisample;
GLPtr<GrGLRenderbufferStorageMultisampleCoverageProc> fRenderbufferStorageMultisampleCoverage;
GLPtr<GrGLResolveMultisampleFramebufferProc> fResolveMultisampleFramebuffer;
GLPtr<GrGLScissorProc> fScissor;
GLPtr<GrGLShaderSourceProc> fShaderSource;
GLPtr<GrGLStencilFuncProc> fStencilFunc;
GLPtr<GrGLStencilFuncSeparateProc> fStencilFuncSeparate;
GLPtr<GrGLStencilMaskProc> fStencilMask;
GLPtr<GrGLStencilMaskSeparateProc> fStencilMaskSeparate;
GLPtr<GrGLStencilOpProc> fStencilOp;
GLPtr<GrGLStencilOpSeparateProc> fStencilOpSeparate;
GLPtr<GrGLTexImage2DProc> fTexImage2D;
GLPtr<GrGLTexParameteriProc> fTexParameteri;
GLPtr<GrGLTexParameterivProc> fTexParameteriv;
GLPtr<GrGLTexSubImage2DProc> fTexSubImage2D;
GLPtr<GrGLTexStorage2DProc> fTexStorage2D;
GLPtr<GrGLUniform1fProc> fUniform1f;
GLPtr<GrGLUniform1iProc> fUniform1i;
GLPtr<GrGLUniform1fvProc> fUniform1fv;
GLPtr<GrGLUniform1ivProc> fUniform1iv;
GLPtr<GrGLUniform2fProc> fUniform2f;
GLPtr<GrGLUniform2iProc> fUniform2i;
GLPtr<GrGLUniform2fvProc> fUniform2fv;
GLPtr<GrGLUniform2ivProc> fUniform2iv;
GLPtr<GrGLUniform3fProc> fUniform3f;
GLPtr<GrGLUniform3iProc> fUniform3i;
GLPtr<GrGLUniform3fvProc> fUniform3fv;
GLPtr<GrGLUniform3ivProc> fUniform3iv;
GLPtr<GrGLUniform4fProc> fUniform4f;
GLPtr<GrGLUniform4iProc> fUniform4i;
GLPtr<GrGLUniform4fvProc> fUniform4fv;
GLPtr<GrGLUniform4ivProc> fUniform4iv;
GLPtr<GrGLUniformMatrix2fvProc> fUniformMatrix2fv;
GLPtr<GrGLUniformMatrix3fvProc> fUniformMatrix3fv;
GLPtr<GrGLUniformMatrix4fvProc> fUniformMatrix4fv;
GLPtr<GrGLUnmapBufferProc> fUnmapBuffer;
GLPtr<GrGLUseProgramProc> fUseProgram;
GLPtr<GrGLVertexAttrib4fvProc> fVertexAttrib4fv;
GLPtr<GrGLVertexAttribPointerProc> fVertexAttribPointer;
GLPtr<GrGLViewportProc> fViewport;
// Experimental: Functions for GL_NV_path_rendering. These will be
// alphabetized with the above functions once this is fully supported
// (and functions we are unlikely to use will possibly be omitted).
GLPtr<GrGLMatrixModeProc> fMatrixMode;
GLPtr<GrGLLoadIdentityProc> fLoadIdentity;
GLPtr<GrGLLoadMatrixfProc> fLoadMatrixf;
GLPtr<GrGLPathCommandsProc> fPathCommands;
GLPtr<GrGLPathCoordsProc> fPathCoords;
GLPtr<GrGLPathSubCommandsProc> fPathSubCommands;
GLPtr<GrGLPathSubCoordsProc> fPathSubCoords;
GLPtr<GrGLPathStringProc> fPathString;
GLPtr<GrGLPathGlyphsProc> fPathGlyphs;
GLPtr<GrGLPathGlyphRangeProc> fPathGlyphRange;
GLPtr<GrGLWeightPathsProc> fWeightPaths;
GLPtr<GrGLCopyPathProc> fCopyPath;
GLPtr<GrGLInterpolatePathsProc> fInterpolatePaths;
GLPtr<GrGLTransformPathProc> fTransformPath;
GLPtr<GrGLPathParameterivProc> fPathParameteriv;
GLPtr<GrGLPathParameteriProc> fPathParameteri;
GLPtr<GrGLPathParameterfvProc> fPathParameterfv;
GLPtr<GrGLPathParameterfProc> fPathParameterf;
GLPtr<GrGLPathDashArrayProc> fPathDashArray;
GLPtr<GrGLGenPathsProc> fGenPaths;
GLPtr<GrGLDeletePathsProc> fDeletePaths;
GLPtr<GrGLIsPathProc> fIsPath;
GLPtr<GrGLPathStencilFuncProc> fPathStencilFunc;
GLPtr<GrGLPathStencilDepthOffsetProc> fPathStencilDepthOffset;
GLPtr<GrGLStencilFillPathProc> fStencilFillPath;
GLPtr<GrGLStencilStrokePathProc> fStencilStrokePath;
GLPtr<GrGLStencilFillPathInstancedProc> fStencilFillPathInstanced;
GLPtr<GrGLStencilStrokePathInstancedProc> fStencilStrokePathInstanced;
GLPtr<GrGLPathCoverDepthFuncProc> fPathCoverDepthFunc;
GLPtr<GrGLPathColorGenProc> fPathColorGen;
GLPtr<GrGLPathTexGenProc> fPathTexGen;
GLPtr<GrGLPathFogGenProc> fPathFogGen;
GLPtr<GrGLCoverFillPathProc> fCoverFillPath;
GLPtr<GrGLCoverStrokePathProc> fCoverStrokePath;
GLPtr<GrGLCoverFillPathInstancedProc> fCoverFillPathInstanced;
GLPtr<GrGLCoverStrokePathInstancedProc> fCoverStrokePathInstanced;
GLPtr<GrGLGetPathParameterivProc> fGetPathParameteriv;
GLPtr<GrGLGetPathParameterfvProc> fGetPathParameterfv;
GLPtr<GrGLGetPathCommandsProc> fGetPathCommands;
GLPtr<GrGLGetPathCoordsProc> fGetPathCoords;
GLPtr<GrGLGetPathDashArrayProc> fGetPathDashArray;
GLPtr<GrGLGetPathMetricsProc> fGetPathMetrics;
GLPtr<GrGLGetPathMetricRangeProc> fGetPathMetricRange;
GLPtr<GrGLGetPathSpacingProc> fGetPathSpacing;
GLPtr<GrGLGetPathColorGenivProc> fGetPathColorGeniv;
GLPtr<GrGLGetPathColorGenfvProc> fGetPathColorGenfv;
GLPtr<GrGLGetPathTexGenivProc> fGetPathTexGeniv;
GLPtr<GrGLGetPathTexGenfvProc> fGetPathTexGenfv;
GLPtr<GrGLIsPointInFillPathProc> fIsPointInFillPath;
GLPtr<GrGLIsPointInStrokePathProc> fIsPointInStrokePath;
GLPtr<GrGLGetPathLengthProc> fGetPathLength;
GLPtr<GrGLPointAlongPathProc> fPointAlongPath;
// Per-GL func callback
#if GR_GL_PER_GL_FUNC_CALLBACK
GrGLInterfaceCallbackProc fCallback;
GrGLInterfaceCallbackData fCallbackData;
#endif
};
#endif

Просмотреть файл

@ -1,54 +0,0 @@
/*
* Copyright 2011 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBitmapRegionDecoder_DEFINED
#define SkBitmapRegionDecoder_DEFINED
#include "SkBitmap.h"
#include "SkImageDecoder.h"
#include "SkStream.h"
struct SkIRect;
/**
* SkBitmapRegionDecoder can be used to decode a specified rect from an image.
* This is particularly useful when the original image is large and you only
* need parts of the image.
*
* However, not all image codecs on all platforms support this feature so be
* prepared to fallback to standard decoding if decodeRegion(...) returns false.
*/
class SkBitmapRegionDecoder {
public:
SkBitmapRegionDecoder(SkImageDecoder* decoder, SkStream* stream,
int width, int height) {
fDecoder = decoder;
fStream = stream;
fWidth = width;
fHeight = height;
}
~SkBitmapRegionDecoder() {
SkDELETE(fDecoder);
SkSafeUnref(fStream);
}
bool decodeRegion(SkBitmap* bitmap, const SkIRect& rect,
SkBitmap::Config pref, int sampleSize);
SkImageDecoder* getDecoder() const { return fDecoder; }
int getWidth() const { return fWidth; }
int getHeight() const { return fHeight; }
private:
SkImageDecoder* fDecoder;
SkStream* fStream;
int fWidth;
int fHeight;
};
#endif

Просмотреть файл

@ -1,95 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBitmapFactory_DEFINED
#define SkBitmapFactory_DEFINED
#include "SkImage.h"
#include "SkTypes.h"
class SkBitmap;
class SkData;
class SkImageCache;
/**
* Factory for creating a bitmap from encoded data.
*/
class SkBitmapFactory {
public:
/**
* Struct containing information about a pixel destination.
*/
struct Target {
/**
* Pre-allocated memory.
*/
void* fAddr;
/**
* Rowbytes of the allocated memory.
*/
size_t fRowBytes;
};
/**
* Signature for a function to decode an image from encoded data.
*/
typedef bool (*DecodeProc)(const void* data, size_t length, SkImage::Info*, const Target*);
/**
* Create a bitmap factory which uses DecodeProc for decoding.
* @param DecodeProc Must not be NULL.
*/
SkBitmapFactory(DecodeProc);
~SkBitmapFactory();
/**
* Set an image cache to use on pixelrefs provided by installPixelRef. Mutually exclusive
* with fCacheSelector.
*/
void setImageCache(SkImageCache* cache);
/**
* Sets up an SkBitmap from encoded data. On success, the SkBitmap will have its Config,
* width, height, rowBytes and pixelref set. If fImageCache is non-NULL, or if fCacheSelector
* is set and returns non-NULL, the pixelref will lazily decode, and that SkImageCache will
* handle the pixel memory. Otherwise installPixelRef will do an immediate decode.
* @param SkData Encoded data.
* @param SkBitmap to install the pixel ref on.
* @return bool Whether or not a pixel ref was successfully installed.
*/
bool installPixelRef(SkData*, SkBitmap*);
/**
* An object for selecting an SkImageCache to use based on an SkImage::Info.
*/
class CacheSelector : public SkRefCnt {
public:
/**
* Return an SkImageCache to use based on the provided SkImage::Info. If the caller decides
* to hang on to the result, it will call ref, so the implementation should not add a ref
* as a result of this call.
*/
virtual SkImageCache* selectCache(const SkImage::Info&) = 0;
};
/**
* Set the function to be used to select which SkImageCache to use. Mutually exclusive with
* fImageCache.
*/
void setCacheSelector(CacheSelector*);
private:
DecodeProc fDecodeProc;
SkImageCache* fImageCache;
CacheSelector* fCacheSelector;
};
#endif // SkBitmapFactory_DEFINED

Просмотреть файл

@ -1,125 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImageCache_DEFINED
#define SkImageCache_DEFINED
#include "SkRefCnt.h"
#include "SkTypes.h"
/**
* Interface for a cache that manages pixel memory.
*/
class SkImageCache : public SkRefCnt {
public:
/**
* Allocate memory whose lifetime is managed by the cache. On success, MUST be balanced with a
* call to releaseCache and a call to throwAwayCache.
* @param bytes Number of bytes needed.
* @param ID Output parameter which must not be NULL. On success, ID will be set to a value
* associated with that memory which can be used as a parameter to the other functions
* in SkImageCache. On failure, ID is unchanged.
* @return Pointer to the newly allocated memory, or NULL. This memory is safe to use until
* releaseCache is called with ID.
*/
virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) = 0;
/**
* Output parameter for pinCache, stating whether the memory still contains the data it held
* when releaseCache was last called for the same ID.
*/
enum DataStatus {
/**
* The data has been purged, and therefore needs to be rewritten to the returned memory.
*/
kUninitialized_DataStatus,
/**
* The memory still contains the data it held when releaseCache was last called with the
* same ID.
*/
kRetained_DataStatus,
};
/**
* Re-request the memory associated with ID and pin it so that it will not be reclaimed until
* the next call to releaseCache with the same ID.
* @param ID Unique ID for the memory block.
* @param status Output parameter which must not be NULL. On success (i.e. the return value is
* not NULL), status will be set to one of two states representing the cached memory. If
* status is set to kRetained_DataStatus, the memory contains the same data it did
* before releaseCache was called with this ID. If status is set to
* kUninitialized_DataStatus, the memory is still pinned, but the previous data is no
* longer available. If the return value is NULL, status is unchanged.
* @return Pointer: If non-NULL, points to the previously allocated memory, in which case
* this call must be balanced with a call to releaseCache. If NULL, the memory
* has been reclaimed, and throwAwayCache MUST NOT be called.
*/
virtual void* pinCache(intptr_t ID, DataStatus* status) = 0;
/**
* Inform the cache that it is safe to free the block of memory corresponding to ID. After
* calling this function, the pointer returned by allocAndPinCache or pinCache must not be
* used again. In order to access the same memory after this, pinCache must be called with
* the same ID.
* @param ID Unique ID for the memory block which is now safe to age out of the cache.
*/
virtual void releaseCache(intptr_t ID) = 0;
/**
* Inform the cache that the block of memory associated with ID will not be asked for again.
* After this call, ID is no longer valid. Must not be called while the associated memory is
* pinned. Must be called to balance a successful allocAndPinCache.
*/
virtual void throwAwayCache(intptr_t ID) = 0;
/**
* ID which does not correspond to any valid cache.
*/
static const intptr_t UNINITIALIZED_ID = 0;
#ifdef SK_DEBUG
/**
* Debug only status of a memory block.
*/
enum MemoryStatus {
/**
* It is safe to use the pointer returned by the most recent of allocAndPinCache(ID) or
* pinCache(ID) with the same ID.
*/
kPinned_MemoryStatus,
/**
* The pointer returned by the most recent call to allocAndPinCache(ID) or pinCache(ID) has
* since been released by releaseCache(ID). In order to reuse it, pinCache(ID) must be
* called again. Note that after calling releaseCache(ID), the status of that particular
* ID may not be kUnpinned_MemoryStatus, depending on the implementation, but it will not
* be kPinned_MemoryStatus.
*/
kUnpinned_MemoryStatus,
/**
* The memory associated with ID has been thrown away. No calls should be made using the
* same ID.
*/
kFreed_MemoryStatus,
};
/**
* Debug only function to get the status of a particular block of memory. Safe to call after
* throwAwayCache has been called with this ID.
*/
virtual MemoryStatus getMemoryStatus(intptr_t ID) const = 0;
/**
* Debug only function to clear all unpinned caches.
*/
virtual void purgeAllUnpinnedCaches() = 0;
#endif
};
#endif // SkImageCache_DEFINED

Просмотреть файл

@ -1,89 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkLruImageCache_DEFINED
#define SkLruImageCache_DEFINED
#include "SkImageCache.h"
#include "SkThread.h"
#include "SkTInternalLList.h"
class CachedPixels;
/**
* SkImageCache implementation that uses an LRU cache to age out old images.
*/
class SkLruImageCache : public SkImageCache {
public:
SkLruImageCache(size_t budget);
virtual ~SkLruImageCache();
#ifdef SK_DEBUG
virtual MemoryStatus getMemoryStatus(intptr_t ID) const SK_OVERRIDE;
virtual void purgeAllUnpinnedCaches() SK_OVERRIDE;
#endif
/**
* Set the byte limit on cached pixels. If more bytes are used than this, the cache will free
* unpinned memory until under the new limit or until all unpinned memory is freed. This will
* never free pinned memory, so the cache can potentially remain over the limit. The limit is
* enforced each time memory is allocated or released.
* 0 is a special flag for an infinite budget.
* @return size_t The previous limit.
*/
size_t setImageCacheLimit(size_t newLimit);
/**
* Return the number of bytes of memory currently in use by the cache. Can include memory that
* is no longer pinned, but has not been freed.
*/
size_t getImageCacheUsed() const { return fRamUsed; }
virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) SK_OVERRIDE;
virtual void* pinCache(intptr_t ID, SkImageCache::DataStatus*) SK_OVERRIDE;
virtual void releaseCache(intptr_t ID) SK_OVERRIDE;
virtual void throwAwayCache(intptr_t ID) SK_OVERRIDE;
private:
// Linked list of recently used. Head is the most recently used, and tail is the least.
SkTInternalLList<CachedPixels> fLRU;
typedef SkTInternalLList<CachedPixels>::Iter Iter;
#ifdef SK_DEBUG
// fMutex is mutable so that getMemoryStatus can be const
mutable
#endif
SkMutex fMutex;
size_t fRamBudget;
size_t fRamUsed;
/**
* Find the CachedPixels represented by ID, or NULL if not in the cache. Mutex must be locked
* before calling.
*/
CachedPixels* findByID(intptr_t ID) const;
/**
* If over budget, throw away pixels which are not currently in use until below budget or there
* are no more pixels eligible to be thrown away. Mutex must be locked before calling.
*/
void purgeIfNeeded();
/**
* Purge until below limit. Mutex must be locked before calling.
*/
void purgeTilAtOrBelow(size_t limit);
/**
* Remove a set of CachedPixels. Mutex must be locked before calling.
*/
void removePixels(CachedPixels*);
};
#endif // SkLruImageCache_DEFINED

Просмотреть файл

@ -1,45 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPurgeableImageCache_DEFINED
#define SkPurgeableImageCache_DEFINED
#include "SkImageCache.h"
#ifdef SK_DEBUG
#include "SkTDArray.h"
#endif
/**
* Implementation for SkImageCache that uses system defined purgeable memory.
*/
class SkPurgeableImageCache : public SkImageCache {
public:
static SkImageCache* Create();
virtual void* allocAndPinCache(size_t bytes, intptr_t* ID) SK_OVERRIDE;
virtual void* pinCache(intptr_t ID, SkImageCache::DataStatus*) SK_OVERRIDE;
virtual void releaseCache(intptr_t ID) SK_OVERRIDE;
virtual void throwAwayCache(intptr_t ID) SK_OVERRIDE;
#ifdef SK_DEBUG
virtual MemoryStatus getMemoryStatus(intptr_t ID) const SK_OVERRIDE;
virtual void purgeAllUnpinnedCaches() SK_OVERRIDE;
virtual ~SkPurgeableImageCache();
#endif
private:
SkPurgeableImageCache();
#ifdef SK_DEBUG
SkTDArray<intptr_t> fRecs;
int findRec(intptr_t) const;
#endif
void removeRec(intptr_t);
};
#endif // SkPurgeableImageCache_DEFINED

Просмотреть файл

@ -1,98 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkTypeface_android_DEFINED
#define SkTypeface_android_DEFINED
#include "SkTypeface.h"
enum FallbackScripts {
kArabic_FallbackScript,
kArmenian_FallbackScript,
kBengali_FallbackScript,
kDevanagari_FallbackScript,
kEthiopic_FallbackScript,
kGeorgian_FallbackScript,
kHebrewRegular_FallbackScript,
kHebrewBold_FallbackScript,
kKannada_FallbackScript,
kMalayalam_FallbackScript,
kTamilRegular_FallbackScript,
kTamilBold_FallbackScript,
kThai_FallbackScript,
kTelugu_FallbackScript,
kFallbackScriptNumber
};
// This particular mapping will be removed after WebKit is updated to use the
// new mappings. No new caller should use the kTamil_FallbackScript but rather
// the more specific Tamil scripts in the standard enum.
#define kTamil_FallbackScript kTamilRegular_FallbackScript
#define SkTypeface_ValidScript(s) (s >= 0 && s < kFallbackScriptNumber)
/**
* Return a new typeface for a fallback script. If the script is
* not valid, or can not map to a font, returns null.
* @param script The script id.
* @return reference to the matching typeface. Caller must call
* unref() when they are done.
*/
SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script);
/**
* Return the string representation for the fallback script on Android.
* If the script is not valid, returns null.
*/
SK_API const char* SkGetFallbackScriptID(FallbackScripts script);
/**
* Return the fallback script enum for the ID on Android.
* If the ID is not valid, or can not map to a fallback
* script, returns kFallbackScriptNumber.
*/
SK_API FallbackScripts SkGetFallbackScriptFromID(const char* id);
/**
* Return a new typeface of the font in the fallback font list containing
* the specified chararacter. If no typeface is found, returns null.
*/
SK_API SkTypeface* SkCreateFallbackTypefaceForChar(SkUnichar uni,
SkTypeface::Style style);
/**
* Get the family name of the font in the fallback font list containing
* the specified chararacter. if no font is found, returns false.
*/
SK_API bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name);
/**
* For test only.
* Load font config from given xml files, instead of those from Android system.
*/
SK_API void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
const char* fontsdir);
/**
* Given a "current" fontID, return a ref to the next logical typeface
* when searching fonts for a given unicode value. Typically the caller
* will query a given font, and if a unicode value is not supported, they
* will call this, and if 0 is not returned, will search that font, and so
* on. This process must be finite, and when the fonthost sees a
* font with no logical successor, it must return NULL.
*
* The original fontID is also provided. This is the initial font that was
* stored in the typeface of the caller. It is provided as an aid to choose
* the best next logical font. e.g. If the original font was bold or serif,
* but the 2nd in the logical chain was plain, then a subsequent call to
* get the 3rd can still inspect the original, and try to match its
* stylistic attributes.
*/
SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID);
#endif

Просмотреть файл

@ -1,31 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPictureUtils_DEFINED
#define SkPictureUtils_DEFINED
#include "SkPicture.h"
class SkData;
struct SkRect;
class SK_API SkPictureUtils {
public:
/**
* Given a rectangular visible "window" into the picture, return an array
* of SkPixelRefs that might intersect that area. To keep the call fast,
* the returned list is not guaranteed to be exact, so it may miss some,
* and it may return false positives.
*
* The pixelrefs returned in the SkData are already owned by the picture,
* so the returned pointers are only valid while the picture is in scope
* and remains unchanged.
*/
static SkData* GatherPixelRefs(SkPicture* pict, const SkRect& area);
};
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,178 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkAntiRun.h"
#include "SkUtils.h"
void SkAlphaRuns::reset(int width) {
SkASSERT(width > 0);
#ifdef SK_DEBUG
sk_memset16((uint16_t*)fRuns, (uint16_t)(-42), width);
#endif
fRuns[0] = SkToS16(width);
fRuns[width] = 0;
fAlpha[0] = 0;
SkDEBUGCODE(fWidth = width;)
SkDEBUGCODE(this->validate();)
}
void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) {
SkASSERT(count > 0 && x >= 0);
// SkAlphaRuns::BreakAt(runs, alpha, x);
// SkAlphaRuns::BreakAt(&runs[x], &alpha[x], count);
int16_t* next_runs = runs + x;
uint8_t* next_alpha = alpha + x;
while (x > 0) {
int n = runs[0];
SkASSERT(n > 0);
if (x < n) {
alpha[x] = alpha[0];
runs[0] = SkToS16(x);
runs[x] = SkToS16(n - x);
break;
}
runs += n;
alpha += n;
x -= n;
}
runs = next_runs;
alpha = next_alpha;
x = count;
for (;;) {
int n = runs[0];
SkASSERT(n > 0);
if (x < n) {
alpha[x] = alpha[0];
runs[0] = SkToS16(x);
runs[x] = SkToS16(n - x);
break;
}
x -= n;
if (x <= 0) {
break;
}
runs += n;
alpha += n;
}
}
int SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha,
U8CPU maxValue, int offsetX) {
SkASSERT(middleCount >= 0);
SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth);
SkASSERT(fRuns[offsetX] >= 0);
int16_t* runs = fRuns + offsetX;
uint8_t* alpha = fAlpha + offsetX;
uint8_t* lastAlpha = alpha;
x -= offsetX;
if (startAlpha) {
SkAlphaRuns::Break(runs, alpha, x, 1);
/* I should be able to just add alpha[x] + startAlpha.
However, if the trailing edge of the previous span and the leading
edge of the current span round to the same super-sampled x value,
I might overflow to 256 with this add, hence the funny subtract (crud).
*/
unsigned tmp = alpha[x] + startAlpha;
SkASSERT(tmp <= 256);
alpha[x] = SkToU8(tmp - (tmp >> 8)); // was (tmp >> 7), but that seems wrong if we're trying to catch 256
runs += x + 1;
alpha += x + 1;
x = 0;
lastAlpha += x; // we don't want the +1
SkDEBUGCODE(this->validate();)
}
if (middleCount) {
SkAlphaRuns::Break(runs, alpha, x, middleCount);
alpha += x;
runs += x;
x = 0;
do {
alpha[0] = SkToU8(alpha[0] + maxValue);
int n = runs[0];
SkASSERT(n <= middleCount);
alpha += n;
runs += n;
middleCount -= n;
} while (middleCount > 0);
SkDEBUGCODE(this->validate();)
lastAlpha = alpha;
}
if (stopAlpha) {
SkAlphaRuns::Break(runs, alpha, x, 1);
alpha += x;
alpha[0] = SkToU8(alpha[0] + stopAlpha);
SkDEBUGCODE(this->validate();)
lastAlpha = alpha;
}
return SkToS32(lastAlpha - fAlpha); // new offsetX
}
#ifdef SK_DEBUG
void SkAlphaRuns::assertValid(int y, int maxStep) const {
int max = (y + 1) * maxStep - (y == maxStep - 1);
const int16_t* runs = fRuns;
const uint8_t* alpha = fAlpha;
while (*runs) {
SkASSERT(*alpha <= max);
alpha += *runs;
runs += *runs;
}
}
void SkAlphaRuns::dump() const {
const int16_t* runs = fRuns;
const uint8_t* alpha = fAlpha;
SkDebugf("Runs");
while (*runs) {
int n = *runs;
SkDebugf(" %02x", *alpha);
if (n > 1) {
SkDebugf(",%d", n);
}
alpha += n;
runs += n;
}
SkDebugf("\n");
}
void SkAlphaRuns::validate() const {
SkASSERT(fWidth > 0);
int count = 0;
const int16_t* runs = fRuns;
while (*runs) {
SkASSERT(*runs > 0);
count += *runs;
SkASSERT(count <= fWidth);
runs += *runs;
}
SkASSERT(count == fWidth);
}
#endif

Просмотреть файл

@ -1,92 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkAntiRun_DEFINED
#define SkAntiRun_DEFINED
#include "SkBlitter.h"
/** Sparse array of run-length-encoded alpha (supersampling coverage) values.
Sparseness allows us to independently compose several paths into the
same SkAlphaRuns buffer.
*/
class SkAlphaRuns {
public:
int16_t* fRuns;
uint8_t* fAlpha;
/// Returns true if the scanline contains only a single run,
/// of alpha value 0.
bool empty() const {
SkASSERT(fRuns[0] > 0);
return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0;
}
/// Reinitialize for a new scanline.
void reset(int width);
/**
* Insert into the buffer a run starting at (x-offsetX):
* if startAlpha > 0
* one pixel with value += startAlpha,
* max 255
* if middleCount > 0
* middleCount pixels with value += maxValue
* if stopAlpha > 0
* one pixel with value += stopAlpha
* Returns the offsetX value that should be passed on the next call,
* assuming we're on the same scanline. If the caller is switching
* scanlines, then offsetX should be 0 when this is called.
*/
int add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha,
U8CPU maxValue, int offsetX);
SkDEBUGCODE(void assertValid(int y, int maxStep) const;)
SkDEBUGCODE(void dump() const;)
/**
* Break the runs in the buffer at offsets x and x+count, properly
* updating the runs to the right and left.
* i.e. from the state AAAABBBB, run-length encoded as A4B4,
* Break(..., 2, 5) would produce AAAABBBB rle as A2A2B3B1.
* Allows add() to sum another run to some of the new sub-runs.
* i.e. adding ..CCCCC. would produce AADDEEEB, rle as A2D2E3B1.
*/
static void Break(int16_t runs[], uint8_t alpha[], int x, int count);
/**
* Cut (at offset x in the buffer) a run into two shorter runs with
* matching alpha values.
* Used by the RectClipBlitter to trim a RLE encoding to match the
* clipping rectangle.
*/
static void BreakAt(int16_t runs[], uint8_t alpha[], int x) {
while (x > 0) {
int n = runs[0];
SkASSERT(n > 0);
if (x < n) {
alpha[x] = alpha[0];
runs[0] = SkToS16(x);
runs[x] = SkToS16(n - x);
break;
}
runs += n;
alpha += n;
x -= n;
}
}
private:
SkDEBUGCODE(int fWidth;)
SkDEBUGCODE(void validate() const;)
};
#endif

Просмотреть файл

@ -1,11 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBBoxHierarchy.h"
SK_DEFINE_INST_COUNT(SkBBoxHierarchy)

Просмотреть файл

@ -1,720 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmapProcState.h"
#include "SkColorPriv.h"
#include "SkFilterProc.h"
#include "SkPaint.h"
#include "SkShader.h" // for tilemodes
#include "SkUtilsArm.h"
#if !SK_ARM_NEON_IS_NONE
// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[];
extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[];
extern void S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*);
extern void Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
extern void Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
extern void SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*);
extern void SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
extern void Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
#endif
#define NAME_WRAP(x) x
#include "SkBitmapProcState_filter.h"
#include "SkBitmapProcState_procs.h"
///////////////////////////////////////////////////////////////////////////////
/**
* For the purposes of drawing bitmaps, if a matrix is "almost" translate
* go ahead and treat it as if it were, so that subsequent code can go fast.
*/
static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) {
SkMatrix::TypeMask mask = matrix.getType();
if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
return false;
}
if (mask & SkMatrix::kScale_Mask) {
SkScalar sx = matrix[SkMatrix::kMScaleX];
SkScalar sy = matrix[SkMatrix::kMScaleY];
int w = bitmap.width();
int h = bitmap.height();
int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
return sw == w && sh == h;
}
// if we got here, we're either kTranslate_Mask or identity
return true;
}
static bool just_trans_general(const SkMatrix& matrix) {
SkMatrix::TypeMask mask = matrix.getType();
if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
return false;
}
if (mask & SkMatrix::kScale_Mask) {
const SkScalar tol = SK_Scalar1 / 32768;
if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) {
return false;
}
if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) {
return false;
}
}
// if we got here, treat us as either kTranslate_Mask or identity
return true;
}
///////////////////////////////////////////////////////////////////////////////
static bool valid_for_filtering(unsigned dimension) {
// for filtering, width and height must fit in 14bits, since we use steal
// 2 bits from each to store our 4bit subpixel data
return (dimension & ~0x3FFF) == 0;
}
bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
return false;
}
const SkMatrix* m;
bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX &&
SkShader::kClamp_TileMode == fTileModeY;
if (clamp_clamp || trivial_matrix) {
m = &inv;
} else {
fUnitInvMatrix = inv;
fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
m = &fUnitInvMatrix;
}
fBitmap = &fOrigBitmap;
if (fOrigBitmap.hasMipMap()) {
int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
SkScalarToFixed(m->getScaleX()),
SkScalarToFixed(m->getSkewY()));
if (shift > 0) {
if (m != &fUnitInvMatrix) {
fUnitInvMatrix = *m;
m = &fUnitInvMatrix;
}
SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
fUnitInvMatrix.postScale(scale, scale);
// now point here instead of fOrigBitmap
fBitmap = &fMipBitmap;
}
}
// wack our matrix to exactly no-scale, if we're really close to begin with
{
bool fixupMatrix = clamp_clamp ?
just_trans_clamp(*m, *fBitmap) : just_trans_general(*m);
if (fixupMatrix) {
// If we can be treated just like translate, construct that inverse
// such that we landed in the proper place. Given that m may have
// some slight scale, we have to invert it to compute this new
// matrix.
SkMatrix forward;
if (m->invert(&forward)) {
SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX());
SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY());
fUnitInvMatrix.setTranslate(tx, ty);
m = &fUnitInvMatrix;
// now the following code will sniff m, and decide to take the
// fast case (since m is purely translate).
}
}
}
// Below this point, we should never refer to the inv parameter, since we
// may be using a munged version for "our" inverse.
fInvMatrix = m;
fInvProc = m->getMapXYProc();
fInvType = m->getType();
fInvSx = SkScalarToFixed(m->getScaleX());
fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX());
fInvKy = SkScalarToFixed(m->getSkewY());
fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY());
fAlphaScale = SkAlpha255To256(paint.getAlpha());
// pick-up filtering from the paint, but only if the matrix is
// more complex than identity/translate (i.e. no need to pay the cost
// of filtering if we're not scaled etc.).
// note: we explicitly check inv, since m might be scaled due to unitinv
// trickery, but we don't want to see that for this test
fDoFilter = paint.isFilterBitmap() &&
(fInvType > SkMatrix::kTranslate_Mask &&
valid_for_filtering(fBitmap->width() | fBitmap->height()));
fShaderProc32 = NULL;
fShaderProc16 = NULL;
fSampleProc32 = NULL;
fSampleProc16 = NULL;
fMatrixProc = this->chooseMatrixProc(trivial_matrix);
if (NULL == fMatrixProc) {
return false;
}
///////////////////////////////////////////////////////////////////////
int index = 0;
if (fAlphaScale < 256) { // note: this distinction is not used for D16
index |= 1;
}
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
index |= 2;
}
if (fDoFilter) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
switch (fBitmap->config()) {
case SkBitmap::kARGB_8888_Config:
index |= 0;
break;
case SkBitmap::kRGB_565_Config:
index |= 8;
break;
case SkBitmap::kIndex8_Config:
index |= 16;
break;
case SkBitmap::kARGB_4444_Config:
index |= 24;
break;
case SkBitmap::kA8_Config:
index |= 32;
fPaintPMColor = SkPreMultiplyColor(paint.getColor());
break;
default:
return false;
}
#if !SK_ARM_NEON_IS_ALWAYS
static const SampleProc32 gSkBitmapProcStateSample32[] = {
S32_opaque_D32_nofilter_DXDY,
S32_alpha_D32_nofilter_DXDY,
S32_opaque_D32_nofilter_DX,
S32_alpha_D32_nofilter_DX,
S32_opaque_D32_filter_DXDY,
S32_alpha_D32_filter_DXDY,
S32_opaque_D32_filter_DX,
S32_alpha_D32_filter_DX,
S16_opaque_D32_nofilter_DXDY,
S16_alpha_D32_nofilter_DXDY,
S16_opaque_D32_nofilter_DX,
S16_alpha_D32_nofilter_DX,
S16_opaque_D32_filter_DXDY,
S16_alpha_D32_filter_DXDY,
S16_opaque_D32_filter_DX,
S16_alpha_D32_filter_DX,
SI8_opaque_D32_nofilter_DXDY,
SI8_alpha_D32_nofilter_DXDY,
SI8_opaque_D32_nofilter_DX,
SI8_alpha_D32_nofilter_DX,
SI8_opaque_D32_filter_DXDY,
SI8_alpha_D32_filter_DXDY,
SI8_opaque_D32_filter_DX,
SI8_alpha_D32_filter_DX,
S4444_opaque_D32_nofilter_DXDY,
S4444_alpha_D32_nofilter_DXDY,
S4444_opaque_D32_nofilter_DX,
S4444_alpha_D32_nofilter_DX,
S4444_opaque_D32_filter_DXDY,
S4444_alpha_D32_filter_DXDY,
S4444_opaque_D32_filter_DX,
S4444_alpha_D32_filter_DX,
// A8 treats alpha/opaque the same (equally efficient)
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DXDY,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_nofilter_DX,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DXDY,
SA8_alpha_D32_filter_DX,
SA8_alpha_D32_filter_DX
};
static const SampleProc16 gSkBitmapProcStateSample16[] = {
S32_D16_nofilter_DXDY,
S32_D16_nofilter_DX,
S32_D16_filter_DXDY,
S32_D16_filter_DX,
S16_D16_nofilter_DXDY,
S16_D16_nofilter_DX,
S16_D16_filter_DXDY,
S16_D16_filter_DX,
SI8_D16_nofilter_DXDY,
SI8_D16_nofilter_DX,
SI8_D16_filter_DXDY,
SI8_D16_filter_DX,
// Don't support 4444 -> 565
NULL, NULL, NULL, NULL,
// Don't support A8 -> 565
NULL, NULL, NULL, NULL
};
#endif
fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
index >>= 1; // shift away any opaque/alpha distinction
fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
// our special-case shaderprocs
if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
if (clamp_clamp) {
fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
} else if (SkShader::kRepeat_TileMode == fTileModeX &&
SkShader::kRepeat_TileMode == fTileModeY) {
fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
}
} else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clamp_clamp) {
fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
}
if (NULL == fShaderProc32) {
fShaderProc32 = this->chooseShaderProc32();
}
// see if our platform has any accelerated overrides
this->platformProcs();
return true;
}
static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
int x, int y,
SkPMColor* SK_RESTRICT colors,
int count) {
SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
SkASSERT(!s.fDoFilter);
const int maxX = s.fBitmap->width() - 1;
const int maxY = s.fBitmap->height() - 1;
int ix = s.fFilterOneX + x;
int iy = SkClampMax(s.fFilterOneY + y, maxY);
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY);
int ix2 = SkScalarFloorToInt(pt.fX);
SkASSERT(iy == iy2);
SkASSERT(ix == ix2);
}
#endif
const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
// clamp to the left
if (ix < 0) {
int n = SkMin32(-ix, count);
sk_memset32(colors, row[0], n);
count -= n;
if (0 == count) {
return;
}
colors += n;
SkASSERT(-ix == n);
ix = 0;
}
// copy the middle
if (ix <= maxX) {
int n = SkMin32(maxX - ix + 1, count);
memcpy(colors, row + ix, n * sizeof(SkPMColor));
count -= n;
if (0 == count) {
return;
}
colors += n;
}
SkASSERT(count > 0);
// clamp to the right
sk_memset32(colors, row[maxX], count);
}
static inline int sk_int_mod(int x, int n) {
SkASSERT(n > 0);
if ((unsigned)x >= (unsigned)n) {
if (x < 0) {
x = n + ~(~x % n);
} else {
x = x % n;
}
}
return x;
}
static inline int sk_int_mirror(int x, int n) {
x = sk_int_mod(x, 2 * n);
if (x >= n) {
x = n + ~(x - n);
}
return x;
}
static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
int x, int y,
SkPMColor* SK_RESTRICT colors,
int count) {
SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
SkASSERT(!s.fDoFilter);
const int stopX = s.fBitmap->width();
const int stopY = s.fBitmap->height();
int ix = s.fFilterOneX + x;
int iy = sk_int_mod(s.fFilterOneY + y, stopY);
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf, &pt);
int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
int ix2 = SkScalarFloorToInt(pt.fX);
SkASSERT(iy == iy2);
SkASSERT(ix == ix2);
}
#endif
const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
ix = sk_int_mod(ix, stopX);
for (;;) {
int n = SkMin32(stopX - ix, count);
memcpy(colors, row + ix, n * sizeof(SkPMColor));
count -= n;
if (0 == count) {
return;
}
colors += n;
ix = 0;
}
}
static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
int x, int y,
SkPMColor* SK_RESTRICT colors,
int count) {
SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0);
SkASSERT(s.fInvKy == 0);
SkASSERT(count > 0 && colors != NULL);
SkASSERT(1 == s.fBitmap->width());
int iY0;
int iY1 SK_INIT_TO_AVOID_WARNING;
int iSubY SK_INIT_TO_AVOID_WARNING;
if (s.fDoFilter) {
SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
uint32_t xy[2];
mproc(s, xy, 1, x, y);
iY0 = xy[0] >> 18;
iY1 = xy[0] & 0x3FFF;
iSubY = (xy[0] >> 14) & 0xF;
} else {
int yTemp;
if (s.fInvType > SkMatrix::kTranslate_Mask) {
SkPoint pt;
s.fInvProc(*s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf,
&pt);
// When the matrix has a scale component the setup code in
// chooseProcs multiples the inverse matrix by the inverse of the
// bitmap's width and height. Since this method is going to do
// its own tiling and sampling we need to undo that here.
if (SkShader::kClamp_TileMode != s.fTileModeX ||
SkShader::kClamp_TileMode != s.fTileModeY) {
yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height());
} else {
yTemp = SkScalarFloorToInt(pt.fY);
}
} else {
yTemp = s.fFilterOneY + y;
}
const int stopY = s.fBitmap->height();
switch (s.fTileModeY) {
case SkShader::kClamp_TileMode:
iY0 = SkClampMax(yTemp, stopY-1);
break;
case SkShader::kRepeat_TileMode:
iY0 = sk_int_mod(yTemp, stopY);
break;
case SkShader::kMirror_TileMode:
default:
iY0 = sk_int_mirror(yTemp, stopY);
break;
}
#ifdef SK_DEBUG
{
SkPoint pt;
s.fInvProc(*s.fInvMatrix,
SkIntToScalar(x) + SK_ScalarHalf,
SkIntToScalar(y) + SK_ScalarHalf,
&pt);
if (s.fInvType > SkMatrix::kTranslate_Mask &&
(SkShader::kClamp_TileMode != s.fTileModeX ||
SkShader::kClamp_TileMode != s.fTileModeY)) {
pt.fY *= s.fBitmap->height();
}
int iY2;
switch (s.fTileModeY) {
case SkShader::kClamp_TileMode:
iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1);
break;
case SkShader::kRepeat_TileMode:
iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
break;
case SkShader::kMirror_TileMode:
default:
iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY);
break;
}
SkASSERT(iY0 == iY2);
}
#endif
}
const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
SkPMColor color;
if (s.fDoFilter) {
const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
if (s.fAlphaScale < 256) {
Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale);
} else {
Filter_32_opaque(iSubY, *row0, *row1, &color);
}
} else {
if (s.fAlphaScale < 256) {
color = SkAlphaMulQ(*row0, s.fAlphaScale);
} else {
color = *row0;
}
}
sk_memset32(colors, color, count);
}
static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y,
SkPMColor* SK_RESTRICT colors, int count) {
// if we get called, the matrix is too tricky, so we just draw nothing
sk_memset32(colors, 0, count);
}
bool SkBitmapProcState::setupForTranslate() {
SkPoint pt;
fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
/*
* if the translate is larger than our ints, we can get random results, or
* worse, we might get 0x80000000, which wreaks havoc on us, since we can't
* negate it.
*/
const SkScalar too_big = SkIntToScalar(1 << 30);
if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) {
return false;
}
// Since we know we're not filtered, we re-purpose these fields allow
// us to go from device -> src coordinates w/ just an integer add,
// rather than running through the inverse-matrix
fFilterOneX = SkScalarFloorToInt(pt.fX);
fFilterOneY = SkScalarFloorToInt(pt.fY);
return true;
}
SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
if (SkBitmap::kARGB_8888_Config != fBitmap->config()) {
return NULL;
}
static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) {
if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) {
return DoNothing_shaderproc;
}
return S32_D32_constX_shaderproc;
}
if (fAlphaScale < 256) {
return NULL;
}
if (fInvType > SkMatrix::kTranslate_Mask) {
return NULL;
}
if (fDoFilter) {
return NULL;
}
SkShader::TileMode tx = (SkShader::TileMode)fTileModeX;
SkShader::TileMode ty = (SkShader::TileMode)fTileModeY;
if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) {
if (this->setupForTranslate()) {
return Clamp_S32_D32_nofilter_trans_shaderproc;
}
return DoNothing_shaderproc;
}
if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) {
if (this->setupForTranslate()) {
return Repeat_S32_D32_nofilter_trans_shaderproc;
}
return DoNothing_shaderproc;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
static void check_scale_nofilter(uint32_t bitmapXY[], int count,
unsigned mx, unsigned my) {
unsigned y = *bitmapXY++;
SkASSERT(y < my);
const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY);
for (int i = 0; i < count; ++i) {
SkASSERT(xptr[i] < mx);
}
}
static void check_scale_filter(uint32_t bitmapXY[], int count,
unsigned mx, unsigned my) {
uint32_t YY = *bitmapXY++;
unsigned y0 = YY >> 18;
unsigned y1 = YY & 0x3FFF;
SkASSERT(y0 < my);
SkASSERT(y1 < my);
for (int i = 0; i < count; ++i) {
uint32_t XX = bitmapXY[i];
unsigned x0 = XX >> 18;
unsigned x1 = XX & 0x3FFF;
SkASSERT(x0 < mx);
SkASSERT(x1 < mx);
}
}
static void check_affine_nofilter(uint32_t bitmapXY[], int count,
unsigned mx, unsigned my) {
for (int i = 0; i < count; ++i) {
uint32_t XY = bitmapXY[i];
unsigned x = XY & 0xFFFF;
unsigned y = XY >> 16;
SkASSERT(x < mx);
SkASSERT(y < my);
}
}
static void check_affine_filter(uint32_t bitmapXY[], int count,
unsigned mx, unsigned my) {
for (int i = 0; i < count; ++i) {
uint32_t YY = *bitmapXY++;
unsigned y0 = YY >> 18;
unsigned y1 = YY & 0x3FFF;
SkASSERT(y0 < my);
SkASSERT(y1 < my);
uint32_t XX = *bitmapXY++;
unsigned x0 = XX >> 18;
unsigned x1 = XX & 0x3FFF;
SkASSERT(x0 < mx);
SkASSERT(x1 < mx);
}
}
void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
uint32_t bitmapXY[], int count,
int x, int y) {
SkASSERT(bitmapXY);
SkASSERT(count > 0);
state.fMatrixProc(state, bitmapXY, count, x, y);
void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my);
// There are four formats possible:
// scale -vs- affine
// filter -vs- nofilter
if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter;
} else {
proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter;
}
proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
}
SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const {
return DebugMatrixProc;
}
#endif
///////////////////////////////////////////////////////////////////////////////
/*
The storage requirements for the different matrix procs are as follows,
where each X or Y is 2 bytes, and N is the number of pixels/elements:
scale/translate nofilter Y(4bytes) + N * X
affine/perspective nofilter N * (X Y)
scale/translate filter Y Y + N * (X X)
affine/perspective filter N * (Y Y X X)
*/
int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
int32_t size = static_cast<int32_t>(bufferSize);
size &= ~3; // only care about 4-byte aligned chunks
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
size -= 4; // the shared Y (or YY) coordinate
if (size < 0) {
size = 0;
}
size >>= 1;
} else {
size >>= 2;
}
if (fDoFilter) {
size >>= 1;
}
return size;
}

Просмотреть файл

@ -1,414 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmapSampler.h"
static SkTileModeProc get_tilemode_proc(SkShader::TileMode mode)
{
switch (mode) {
case SkShader::kClamp_TileMode:
return do_clamp;
case SkShader::kRepeat_TileMode:
return do_repeat_mod;
case SkShader::kMirror_TileMode:
return do_mirror_mod;
default:
SkDEBUGFAIL("unknown mode");
return NULL;
}
}
SkBitmapSampler::SkBitmapSampler(const SkBitmap& bm, bool filter,
SkShader::TileMode tmx, SkShader::TileMode tmy)
: fBitmap(bm), fFilterBitmap(filter), fTileModeX(tmx), fTileModeY(tmy)
{
SkASSERT(bm.width() > 0 && bm.height() > 0);
fMaxX = SkToU16(bm.width() - 1);
fMaxY = SkToU16(bm.height() - 1);
fTileProcX = get_tilemode_proc(tmx);
fTileProcY = get_tilemode_proc(tmy);
}
void SkBitmapSampler::setPaint(const SkPaint& paint)
{
}
class SkNullBitmapSampler : public SkBitmapSampler {
public:
SkNullBitmapSampler(const SkBitmap& bm, bool filter,
SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, filter, tmx, tmy) {}
virtual SkPMColor sample(SkFixed x, SkFixed y) const { return 0; }
};
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
#define BITMAP_CLASSNAME_PREFIX(name) ARGB32##name
#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) *bitmap.getAddr32(x, y)
#include "SkBitmapSamplerTemplate.h"
#include "SkColorPriv.h"
#define BITMAP_CLASSNAME_PREFIX(name) RGB16##name
#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) SkPixel16ToPixel32(*bitmap.getAddr16(x, y))
#include "SkBitmapSamplerTemplate.h"
#define BITMAP_CLASSNAME_PREFIX(name) Index8##name
#define BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) bitmap.getIndex8Color(x, y)
#include "SkBitmapSamplerTemplate.h"
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
///////////////// The Bilinear versions
#include "SkFilterProc.h"
class ARGB32_Bilinear_Sampler : public SkBitmapSampler {
public:
ARGB32_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, true, tmx, tmy)
{
fPtrProcTable = SkGetBilinearFilterPtrProcTable();
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
const uint32_t *p00, *p01, *p10, *p11;
// turn pixel centers into the top-left of our filter-box
x -= SK_FixedHalf;
y -= SK_FixedHalf;
// compute our pointers
{
const SkBitmap* bitmap = &fBitmap;
int ix = x >> 16;
int iy = y >> 16;
int maxX = fMaxX;
SkTileModeProc procX = fTileProcX;
int maxY = fMaxY;
SkTileModeProc procY = fTileProcY;
int tmpx = procX(ix, maxX);
int tmpy = procY(iy, maxY);
p00 = bitmap->getAddr32(tmpx, tmpy);
int tmpx1 = procX(ix + 1, maxX);
p01 = bitmap->getAddr32(tmpx1, tmpy);
int tmpy1 = procY(iy + 1, maxY);
p10 = bitmap->getAddr32(tmpx, tmpy1);
p11 = bitmap->getAddr32(tmpx1, tmpy1);
}
SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y);
return proc(p00, p01, p10, p11);
}
private:
const SkFilterPtrProc* fPtrProcTable;
};
class RGB16_Bilinear_Sampler : public SkBitmapSampler {
public:
RGB16_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, true, tmx, tmy)
{
fProcTable = SkGetBilinearFilterProcTable();
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
const uint16_t *p00, *p01, *p10, *p11;
// turn pixel centers into the top-left of our filter-box
x -= SK_FixedHalf;
y -= SK_FixedHalf;
// compute our pointers
{
const SkBitmap* bitmap = &fBitmap;
int ix = x >> 16;
int iy = y >> 16;
int maxX = fMaxX;
SkTileModeProc procX = fTileProcX;
int maxY = fMaxY;
SkTileModeProc procY = fTileProcY;
int tmpx = procX(ix, maxX);
int tmpy = procY(iy, maxY);
p00 = bitmap->getAddr16(tmpx, tmpy);
int tmpx1 = procX(ix + 1, maxX);
p01 = bitmap->getAddr16(tmpx1, tmpy);
int tmpy1 = procY(iy + 1, maxY);
p10 = bitmap->getAddr16(tmpx, tmpy1);
p11 = bitmap->getAddr16(tmpx1, tmpy1);
}
SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y);
uint32_t c = proc(SkExpand_rgb_16(*p00), SkExpand_rgb_16(*p01),
SkExpand_rgb_16(*p10), SkExpand_rgb_16(*p11));
return SkPixel16ToPixel32((uint16_t)SkCompact_rgb_16(c));
}
private:
const SkFilterProc* fProcTable;
};
// If we had a init/term method on sampler, we could avoid the per-pixel
// call to lockColors/unlockColors
class Index8_Bilinear_Sampler : public SkBitmapSampler {
public:
Index8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, true, tmx, tmy)
{
fPtrProcTable = SkGetBilinearFilterPtrProcTable();
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
const SkBitmap* bitmap = &fBitmap;
const uint8_t *p00, *p01, *p10, *p11;
// turn pixel centers into the top-left of our filter-box
x -= SK_FixedHalf;
y -= SK_FixedHalf;
// compute our pointers
{
int ix = x >> 16;
int iy = y >> 16;
int maxX = fMaxX;
SkTileModeProc procX = fTileProcX;
int maxY = fMaxY;
SkTileModeProc procY = fTileProcY;
int tmpx = procX(ix, maxX);
int tmpy = procY(iy, maxY);
p00 = bitmap->getAddr8(tmpx, tmpy);
int tmpx1 = procX(ix + 1, maxX);
p01 = bitmap->getAddr8(tmpx1, tmpy);
int tmpy1 = procY(iy + 1, maxY);
p10 = bitmap->getAddr8(tmpx, tmpy1);
p11 = bitmap->getAddr8(tmpx1, tmpy1);
}
const SkPMColor* colors = bitmap->getColorTable()->lockColors();
SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(fPtrProcTable, x, y);
uint32_t c = proc(&colors[*p00], &colors[*p01], &colors[*p10], &colors[*p11]);
bitmap->getColorTable()->unlockColors(false);
return c;
}
private:
const SkFilterPtrProc* fPtrProcTable;
};
class A8_Bilinear_Sampler : public SkBitmapSampler {
public:
A8_Bilinear_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, true, tmx, tmy)
, fColor(0)
{
fProcTable = SkGetBilinearFilterProcTable();
}
virtual void setPaint(const SkPaint& paint)
{
fColor = SkPreMultiplyColor(paint.getColor());
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
const uint8_t *p00, *p01, *p10, *p11;
// turn pixel centers into the top-left of our filter-box
x -= SK_FixedHalf;
y -= SK_FixedHalf;
// compute our pointers
{
const SkBitmap* bitmap = &fBitmap;
int ix = x >> 16;
int iy = y >> 16;
int maxX = fMaxX;
SkTileModeProc procX = fTileProcX;
int maxY = fMaxY;
SkTileModeProc procY = fTileProcY;
int tmpx = procX(ix, maxX);
int tmpy = procY(iy, maxY);
p00 = bitmap->getAddr8(tmpx, tmpy);
int tmpx1 = procX(ix + 1, maxX);
p01 = bitmap->getAddr8(tmpx1, tmpy);
int tmpy1 = procY(iy + 1, maxY);
p10 = bitmap->getAddr8(tmpx, tmpy1);
p11 = bitmap->getAddr8(tmpx1, tmpy1);
}
SkFilterProc proc = SkGetBilinearFilterProc(fProcTable, x, y);
int alpha = proc(*p00, *p01, *p10, *p11);
return SkAlphaMulQ(fColor, SkAlpha255To256(alpha));
}
private:
const SkFilterProc* fProcTable;
SkPMColor fColor;
};
class A8_NoFilter_Sampler : public SkBitmapSampler {
public:
A8_NoFilter_Sampler(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, false, tmx, tmy)
{
}
virtual void setPaint(const SkPaint& paint)
{
fColor = SkPreMultiplyColor(paint.getColor());
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
int ix = SkFixedFloor(x);
int iy = SkFixedFloor(y);
int alpha = *fBitmap.getAddr8(fTileProcX(ix, fMaxX), fTileProcY(iy, fMaxY));
return SkAlphaMulQ(fColor, SkAlpha255To256(alpha));
}
private:
SkPMColor fColor;
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SkBitmapSampler* SkBitmapSampler::Create(const SkBitmap& bm, bool doFilter,
SkShader::TileMode tmx,
SkShader::TileMode tmy)
{
switch (bm.getConfig()) {
case SkBitmap::kARGB_8888_Config:
if (doFilter)
return SkNEW_ARGS(ARGB32_Bilinear_Sampler, (bm, tmx, tmy));
if (tmx == tmy) {
switch (tmx) {
case SkShader::kClamp_TileMode:
return SkNEW_ARGS(ARGB32_Point_Clamp_Sampler, (bm));
case SkShader::kRepeat_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(ARGB32_Point_Repeat_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(ARGB32_Point_Repeat_Mod_Sampler, (bm));
case SkShader::kMirror_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(ARGB32_Point_Mirror_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(ARGB32_Point_Mirror_Mod_Sampler, (bm));
default:
SkDEBUGFAIL("unknown mode");
}
}
else { // tmx != tmy
return SkNEW_ARGS(ARGB32_Point_Sampler, (bm, tmx, tmy));
}
break;
case SkBitmap::kRGB_565_Config:
if (doFilter)
return SkNEW_ARGS(RGB16_Bilinear_Sampler, (bm, tmx, tmy));
if (tmx == tmy) {
switch (tmx) {
case SkShader::kClamp_TileMode:
return SkNEW_ARGS(RGB16_Point_Clamp_Sampler, (bm));
case SkShader::kRepeat_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(RGB16_Point_Repeat_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(RGB16_Point_Repeat_Mod_Sampler, (bm));
case SkShader::kMirror_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(RGB16_Point_Mirror_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(RGB16_Point_Mirror_Mod_Sampler, (bm));
default:
SkDEBUGFAIL("unknown mode");
}
}
else { // tmx != tmy
return SkNEW_ARGS(RGB16_Point_Sampler, (bm, tmx, tmy));
}
break;
case SkBitmap::kIndex8_Config:
if (doFilter)
return SkNEW_ARGS(Index8_Bilinear_Sampler, (bm, tmx, tmy));
if (tmx == tmy) {
switch (tmx) {
case SkShader::kClamp_TileMode:
return SkNEW_ARGS(Index8_Point_Clamp_Sampler, (bm));
case SkShader::kRepeat_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(Index8_Point_Repeat_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(Index8_Point_Repeat_Mod_Sampler, (bm));
case SkShader::kMirror_TileMode:
if (is_pow2(bm.width()) && is_pow2(bm.height()))
return SkNEW_ARGS(Index8_Point_Mirror_Pow2_Sampler, (bm));
else
return SkNEW_ARGS(Index8_Point_Mirror_Mod_Sampler, (bm));
default:
SkDEBUGFAIL("unknown mode");
}
}
else { // tmx != tmy
return SkNEW_ARGS(Index8_Point_Sampler, (bm, tmx, tmy));
}
break;
case SkBitmap::kA8_Config:
if (doFilter)
return SkNEW_ARGS(A8_Bilinear_Sampler, (bm, tmx, tmy));
else
return SkNEW_ARGS(A8_NoFilter_Sampler, (bm, tmx, tmy));
break;
default:
SkDEBUGFAIL("unknown device");
}
return SkNEW_ARGS(SkNullBitmapSampler, (bm, doFilter, tmx, tmy));
}

Просмотреть файл

@ -1,162 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBitmapSampler_DEFINED
#define SkBitmapSampler_DEFINED
#include "SkBitmap.h"
#include "SkPaint.h"
#include "SkShader.h"
typedef int (*SkTileModeProc)(int value, unsigned max);
class SkBitmapSampler {
public:
SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy);
virtual ~SkBitmapSampler() {}
const SkBitmap& getBitmap() const { return fBitmap; }
bool getFilterBitmap() const { return fFilterBitmap; }
SkShader::TileMode getTileModeX() const { return fTileModeX; }
SkShader::TileMode getTileModeY() const { return fTileModeY; }
/** Given a pixel center at [x,y], return the color sample
*/
virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0;
virtual void setPaint(const SkPaint& paint);
// This is the factory for finding an optimal subclass
static SkBitmapSampler* Create(const SkBitmap&, bool filter,
SkShader::TileMode tmx, SkShader::TileMode tmy);
protected:
const SkBitmap& fBitmap;
uint16_t fMaxX, fMaxY;
bool fFilterBitmap;
SkShader::TileMode fTileModeX;
SkShader::TileMode fTileModeY;
SkTileModeProc fTileProcX;
SkTileModeProc fTileProcY;
// illegal
SkBitmapSampler& operator=(const SkBitmapSampler&);
};
static inline int fixed_clamp(SkFixed x)
{
#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
if (x >> 16)
x = 0xFFFF;
if (x < 0)
x = 0;
#else
if (x >> 16)
{
if (x < 0)
x = 0;
else
x = 0xFFFF;
}
#endif
return x;
}
//////////////////////////////////////////////////////////////////////////////////////
static inline int fixed_repeat(SkFixed x)
{
return x & 0xFFFF;
}
static inline int fixed_mirror(SkFixed x)
{
SkFixed s = x << 15 >> 31;
// s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
return (x ^ s) & 0xFFFF;
}
static inline bool is_pow2(int count)
{
SkASSERT(count > 0);
return (count & (count - 1)) == 0;
}
static inline int do_clamp(int index, unsigned max)
{
SkASSERT((int)max >= 0);
#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
if (index > (int)max)
index = max;
if (index < 0)
index = 0;
#else
if ((unsigned)index > max)
{
if (index < 0)
index = 0;
else
index = max;
}
#endif
return index;
}
static inline int do_repeat_mod(int index, unsigned max)
{
SkASSERT((int)max >= 0);
if ((unsigned)index > max)
{
if (index < 0)
index = max - (~index % (max + 1));
else
index = index % (max + 1);
}
return index;
}
static inline int do_repeat_pow2(int index, unsigned max)
{
SkASSERT((int)max >= 0 && is_pow2(max + 1));
return index & max;
}
static inline int do_mirror_mod(int index, unsigned max)
{
SkASSERT((int)max >= 0);
// have to handle negatives so that
// -1 -> 0, -2 -> 1, -3 -> 2, etc.
// so we can't just cal abs
index ^= index >> 31;
if ((unsigned)index > max)
{
int mod = (max + 1) << 1;
index = index % mod;
if ((unsigned)index > max)
index = mod - index - 1;
}
return index;
}
static inline int do_mirror_pow2(int index, unsigned max)
{
SkASSERT((int)max >= 0 && is_pow2(max + 1));
int s = (index & (max + 1)) - 1;
s = ~(s >> 31);
// at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
return (index ^ s) & max;
}
#endif

Просмотреть файл

@ -1,108 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* this guy is pulled in multiple times, with the following symbols defined each time:
#define BITMAP_CLASSNAME_PREFIX(name) ARGB32##name
#defube BITMAP_PIXEL_TO_PMCOLOR(bitmap, x, y) *bitmap.getAddr32(x, y)
*/
class BITMAP_CLASSNAME_PREFIX(_Point_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Sampler)(const SkBitmap& bm, SkShader::TileMode tmx, SkShader::TileMode tmy)
: SkBitmapSampler(bm, false, tmx, tmy)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = fTileProcX(SkFixedFloor(x), fMaxX);
y = fTileProcY(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
class BITMAP_CLASSNAME_PREFIX(_Point_Clamp_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Clamp_Sampler)(const SkBitmap& bm)
: SkBitmapSampler(bm, false, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = do_clamp(SkFixedFloor(x), fMaxX);
y = do_clamp(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
class BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Pow2_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Pow2_Sampler)(const SkBitmap& bm)
: SkBitmapSampler(bm, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = do_repeat_pow2(SkFixedFloor(x), fMaxX);
y = do_repeat_pow2(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
class BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Mod_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Repeat_Mod_Sampler)(const SkBitmap& bm)
: SkBitmapSampler(bm, false, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = do_repeat_mod(SkFixedFloor(x), fMaxX);
y = do_repeat_mod(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
class BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Pow2_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Pow2_Sampler)(const SkBitmap& bm)
: SkBitmapSampler(bm, false, SkShader::kMirror_TileMode, SkShader::kMirror_TileMode)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = do_mirror_pow2(SkFixedFloor(x), fMaxX);
y = do_mirror_pow2(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
class BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Mod_Sampler) : public SkBitmapSampler {
public:
BITMAP_CLASSNAME_PREFIX(_Point_Mirror_Mod_Sampler)(const SkBitmap& bm)
: SkBitmapSampler(bm, false, SkShader::kMirror_TileMode, SkShader::kMirror_TileMode)
{
}
virtual SkPMColor sample(SkFixed x, SkFixed y) const
{
x = do_mirror_mod(SkFixedFloor(x), fMaxX);
y = do_mirror_mod(SkFixedFloor(y), fMaxY);
return BITMAP_PIXEL_TO_PMCOLOR(fBitmap, x, y);
}
};
#undef BITMAP_CLASSNAME_PREFIX
#undef BITMAP_PIXEL_TO_PMCOLOR

Просмотреть файл

@ -1,218 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBlitRow.h"
#include "SkColorPriv.h"
#include "SkDither.h"
///////////////////////////////////////////////////////////////////////////////
static void S32_D4444_Opaque(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 == alpha);
if (count > 0) {
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
*dst++ = SkPixel32ToPixel4444(c);
} while (--count != 0);
}
}
static void S32_D4444_Blend(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 > alpha);
if (count > 0) {
unsigned scale16 = SkAlpha255To256(alpha) >> 4;
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
uint32_t src_expand = SkExpand32_4444(c);
uint32_t dst_expand = SkExpand_4444(*dst);
dst_expand += (src_expand - dst_expand) * scale16 >> 4;
*dst++ = SkCompact_4444(dst_expand);
} while (--count != 0);
}
}
static void S32A_D4444_Opaque(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 == alpha);
if (count > 0) {
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
// if (__builtin_expect(c!=0, 1))
if (c)
{
unsigned scale16 = SkAlpha255To256(255 - SkGetPackedA32(c)) >> 4;
uint32_t src_expand = SkExpand_8888(c);
uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
*dst = SkCompact_4444((src_expand + dst_expand) >> 4);
}
dst += 1;
} while (--count != 0);
}
}
static void S32A_D4444_Blend(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
SkASSERT(255 > alpha);
if (count > 0) {
int src_scale = SkAlpha255To256(alpha) >> 4;
do {
SkPMColor sc = *src++;
SkPMColorAssert(sc);
if (sc) {
unsigned dst_scale = 16 - (SkGetPackedA32(sc) * src_scale >> 8);
uint32_t src_expand = SkExpand32_4444(sc) * src_scale;
uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
*dst = SkCompact_4444((src_expand + dst_expand) >> 4);
}
dst += 1;
} while (--count != 0);
}
}
/////////////////////////////////////////////////////////////////////////////
static void S32_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 == alpha);
if (count > 0) {
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
unsigned dither = DITHER_VALUE(x);
*dst++ = SkDitherARGB32To4444(c, dither);
DITHER_INC_X(x);
} while (--count != 0);
}
}
static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 > alpha);
if (count > 0) {
int scale16 = SkAlpha255To256(alpha) >> 4;
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
SkASSERT(SkGetPackedA32(c) == 255);
uint32_t src_expand = SkExpand32_4444(c) * scale16;
uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16);
c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor
*dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
DITHER_INC_X(x);
} while (--count != 0);
}
}
static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 == alpha);
if (count > 0) {
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
if (c) {
unsigned a = SkGetPackedA32(c);
int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
unsigned scale16 = SkAlpha255To256(255 - a) >> 4;
uint32_t src_expand = SkExpand_8888(c);
uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
// convert back to SkPMColor
c = SkCompact_8888(src_expand + dst_expand);
*dst = SkDitherARGB32To4444(c, d);
}
dst += 1;
DITHER_INC_X(x);
} while (--count != 0);
}
}
// need DitherExpand888To4444(expand, dither)
static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha, int x, int y) {
SkASSERT(255 > alpha);
if (count > 0) {
int src_scale = SkAlpha255To256(alpha) >> 4;
DITHER_4444_SCAN(y);
do {
SkPMColor c = *src++;
SkPMColorAssert(c);
if (c) {
unsigned a = SkAlpha255To256(SkGetPackedA32(c));
int d = SkAlphaMul(DITHER_VALUE(x), a);
unsigned dst_scale = 16 - SkAlphaMul(src_scale, a);
uint32_t src_expand = SkExpand32_4444(c) * src_scale;
uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
// convert back to SkPMColor
c = SkCompact_8888(src_expand + dst_expand);
*dst = SkDitherARGB32To4444(c, d);
}
dst += 1;
DITHER_INC_X(x);
} while (--count != 0);
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static const SkBlitRow::Proc gProcs4444[] = {
// no dither
S32_D4444_Opaque,
S32_D4444_Blend,
S32A_D4444_Opaque,
S32A_D4444_Blend,
// dither
S32_D4444_Opaque_Dither,
S32_D4444_Blend_Dither,
S32A_D4444_Opaque_Dither,
S32A_D4444_Blend_Dither
};
SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags)
{
SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444));
return gProcs4444[flags];
}

Просмотреть файл

@ -1,480 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCoreBlitters.h"
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkShader.h"
#include "SkTemplatesPriv.h"
#include "SkUtils.h"
#include "SkXfermode.h"
static inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst,
U8CPU aa) {
SkASSERT((unsigned)aa <= 255);
unsigned src_scale = SkAlpha255To256(aa) >> 4;
unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale));
uint32_t src32 = SkExpand_4444(src) * src_scale;
uint32_t dst32 = SkExpand_4444(dst) * dst_scale;
return SkCompact_4444((src32 + dst32) >> 4);
}
///////////////////////////////////////////////////////////////////////////////
class SkARGB4444_Blitter : public SkRasterBlitter {
public:
SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint);
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]);
virtual void blitV(int x, int y, int height, SkAlpha alpha);
virtual void blitRect(int x, int y, int width, int height);
virtual void blitMask(const SkMask&, const SkIRect&);
virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
protected:
SkPMColor16 fPMColor16, fPMColor16Other;
SkPMColor16 fRawColor16, fRawColor16Other;
uint8_t fScale16;
private:
// illegal
SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&);
typedef SkRasterBlitter INHERITED;
};
SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device,
const SkPaint& paint) : INHERITED(device) {
// cache premultiplied versions in 4444
SkPMColor c = SkPreMultiplyColor(paint.getColor());
fPMColor16 = SkPixel32ToPixel4444(c);
if (paint.isDither()) {
fPMColor16Other = SkDitherPixel32To4444(c);
} else {
fPMColor16Other = fPMColor16;
}
// cache raw versions in 4444
fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
if (paint.isDither()) {
fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
SkColorGetG(c), SkColorGetB(c));
} else {
fRawColor16Other = fRawColor16;
}
fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
if (16 == fScale16) {
// force the original to also be opaque
fPMColor16 |= (0xF << SK_A4444_SHIFT);
}
}
const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) {
if (16 == fScale16) {
*value = fPMColor16;
return &fDevice;
}
return NULL;
}
static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color,
SkPMColor16 other, unsigned invScale, int count) {
int twice = count >> 1;
while (--twice >= 0) {
*dst = color + SkAlphaMulQ4(*dst, invScale);
dst++;
*dst = other + SkAlphaMulQ4(*dst, invScale);
dst++;
}
if (count & 1) {
*dst = color + SkAlphaMulQ4(*dst, invScale);
}
}
static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) {
uint32_t c32 = SkExpand_4444(c);
return c32 | (c32 << 4);
}
static void src_over_4444x(SkPMColor16 dst[], uint32_t color,
uint32_t other, unsigned invScale, int count) {
int twice = count >> 1;
uint32_t tmp;
while (--twice >= 0) {
tmp = SkExpand_4444(*dst) * invScale;
*dst++ = SkCompact_4444((color + tmp) >> 4);
tmp = SkExpand_4444(*dst) * invScale;
*dst++ = SkCompact_4444((other + tmp) >> 4);
}
if (count & 1) {
tmp = SkExpand_4444(*dst) * invScale;
*dst = SkCompact_4444((color + tmp) >> 4);
}
}
void SkARGB4444_Blitter::blitH(int x, int y, int width) {
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
if (0 == fScale16) {
return;
}
SkPMColor16* device = fDevice.getAddr16(x, y);
SkPMColor16 color = fPMColor16;
SkPMColor16 other = fPMColor16Other;
if ((x ^ y) & 1) {
SkTSwap<SkPMColor16>(color, other);
}
if (16 == fScale16) {
sk_dither_memset16(device, color, other, width);
} else {
src_over_4444x(device, SkExpand_4444_Replicate(color),
SkExpand_4444_Replicate(other),
16 - fScale16, width);
}
}
void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
if (0 == alpha || 0 == fScale16) {
return;
}
SkPMColor16* device = fDevice.getAddr16(x, y);
SkPMColor16 color = fPMColor16;
SkPMColor16 other = fPMColor16Other;
size_t rb = fDevice.rowBytes();
if ((x ^ y) & 1) {
SkTSwap<SkPMColor16>(color, other);
}
if (16 == fScale16 && 255 == alpha) {
while (--height >= 0) {
*device = color;
device = (SkPMColor16*)((char*)device + rb);
SkTSwap<SkPMColor16>(color, other);
}
} else {
unsigned alphaScale = SkAlpha255To256(alpha);
uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4);
// need to normalize the low nibble of each expanded component
// so we don't overflow the add with d32
c32 = SkCompact_4444(c32 >> 4);
unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32));
// now re-expand and replicate
c32 = SkExpand_4444_Replicate(c32);
while (--height >= 0) {
uint32_t d32 = SkExpand_4444(*device) * invScale;
*device = SkCompact_4444((c32 + d32) >> 4);
device = (SkPMColor16*)((char*)device + rb);
}
}
}
void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) {
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() &&
y + height <= fDevice.height());
if (0 == fScale16) {
return;
}
SkPMColor16* device = fDevice.getAddr16(x, y);
SkPMColor16 color = fPMColor16;
SkPMColor16 other = fPMColor16Other;
if ((x ^ y) & 1) {
SkTSwap<SkPMColor16>(color, other);
}
if (16 == fScale16) {
while (--height >= 0) {
sk_dither_memset16(device, color, other, width);
device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
SkTSwap<SkPMColor16>(color, other);
}
} else {
unsigned invScale = 16 - fScale16;
uint32_t c32 = SkExpand_4444_Replicate(color);
uint32_t o32 = SkExpand_4444_Replicate(other);
while (--height >= 0) {
src_over_4444x(device, c32, o32, invScale, width);
device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
SkTSwap<uint32_t>(c32, o32);
}
}
}
void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
if (0 == fScale16) {
return;
}
SkPMColor16* device = fDevice.getAddr16(x, y);
SkPMColor16 color = fPMColor16;
SkPMColor16 other = fPMColor16Other;
if ((x ^ y) & 1) {
SkTSwap<SkPMColor16>(color, other);
}
for (;;) {
int count = runs[0];
SkASSERT(count >= 0);
if (count <= 0) {
return;
}
unsigned aa = antialias[0];
if (aa) {
if (0xFF == aa) {
if (16 == fScale16) {
sk_dither_memset16(device, color, other, count);
} else {
src_over_4444(device, color, other, 16 - fScale16, count);
}
} else {
// todo: respect dithering
aa = SkAlpha255To256(aa); // FIX
SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4);
unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX
int n = count;
do {
--n;
device[n] = src + SkAlphaMulQ4(device[n], dst_scale);
} while (n > 0);
}
}
runs += count;
antialias += count;
device += count;
if (count & 1) {
SkTSwap<SkPMColor16>(color, other);
}
}
}
///////////////////////////////////////////////////////////////////////////////
#define solid_8_pixels(mask, dst, color) \
do { \
if (mask & 0x80) dst[0] = color; \
if (mask & 0x40) dst[1] = color; \
if (mask & 0x20) dst[2] = color; \
if (mask & 0x10) dst[3] = color; \
if (mask & 0x08) dst[4] = color; \
if (mask & 0x04) dst[5] = color; \
if (mask & 0x02) dst[6] = color; \
if (mask & 0x01) dst[7] = color; \
} while (0)
#define SK_BLITBWMASK_NAME SkARGB4444_BlitBW
#define SK_BLITBWMASK_ARGS , SkPMColor16 color
#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
#define SK_BLITBWMASK_GETADDR getAddr16
#define SK_BLITBWMASK_DEVTYPE uint16_t
#include "SkBlitBWMaskTemplate.h"
#define blend_8_pixels(mask, dst, sc, dst_scale) \
do { \
if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \
if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \
if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \
if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \
if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \
if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \
if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \
if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \
} while (0)
#define SK_BLITBWMASK_NAME SkARGB4444_BlendBW
#define SK_BLITBWMASK_ARGS , uint16_t sc, unsigned dst_scale
#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale)
#define SK_BLITBWMASK_GETADDR getAddr16
#define SK_BLITBWMASK_DEVTYPE uint16_t
#include "SkBlitBWMaskTemplate.h"
void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
SkASSERT(mask.fBounds.contains(clip));
if (0 == fScale16) {
return;
}
if (mask.fFormat == SkMask::kBW_Format) {
if (16 == fScale16) {
SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16);
} else {
SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16);
}
return;
}
int x = clip.fLeft;
int y = clip.fTop;
int width = clip.width();
int height = clip.height();
SkPMColor16* device = fDevice.getAddr16(x, y);
const uint8_t* alpha = mask.getAddr8(x, y);
SkPMColor16 srcColor = fPMColor16;
size_t devRB = fDevice.rowBytes() - (width << 1);
unsigned maskRB = mask.fRowBytes - width;
do {
int w = width;
do {
unsigned aa = *alpha++;
*device = SkBlendARGB4444(srcColor, *device, aa);
device += 1;
} while (--w != 0);
device = (SkPMColor16*)((char*)device + devRB);
alpha += maskRB;
} while (--height != 0);
}
///////////////////////////////////////////////////////////////////////////////
class SkARGB4444_Shader_Blitter : public SkShaderBlitter {
SkXfermode* fXfermode;
SkBlitRow::Proc fOpaqueProc;
SkBlitRow::Proc fAlphaProc;
SkPMColor* fBuffer;
uint8_t* fAAExpand;
public:
SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device, paint) {
const int width = device.width();
fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width);
fAAExpand = (uint8_t*)(fBuffer + width);
fXfermode = paint.getXfermode();
SkSafeRef(fXfermode);
unsigned flags = 0;
if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
flags |= SkBlitRow::kSrcPixelAlpha_Flag;
}
if (paint.isDither()) {
flags |= SkBlitRow::kDither_Flag;
}
fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config);
fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
SkBitmap::kARGB_4444_Config);
}
virtual ~SkARGB4444_Shader_Blitter() {
SkSafeUnref(fXfermode);
sk_free(fBuffer);
}
virtual void blitH(int x, int y, int width) {
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
SkPMColor16* device = fDevice.getAddr16(x, y);
SkPMColor* span = fBuffer;
fShader->shadeSpan(x, y, span, width);
if (fXfermode) {
fXfermode->xfer4444(device, span, width, NULL);
} else {
fOpaqueProc(device, span, width, 0xFF, x, y);
}
}
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
SkPMColor* SK_RESTRICT span = fBuffer;
uint8_t* SK_RESTRICT aaExpand = fAAExpand;
SkPMColor16* device = fDevice.getAddr16(x, y);
SkShader* shader = fShader;
SkXfermode* xfer = fXfermode;
if (NULL != xfer) {
for (;;) {
int count = *runs;
if (count <= 0) {
break;
}
int aa = *antialias;
if (aa) {
shader->shadeSpan(x, y, span, count);
if (255 == aa) {
xfer->xfer4444(device, span, count, NULL);
} else {
const uint8_t* aaBuffer = antialias;
if (count > 1) {
memset(aaExpand, aa, count);
aaBuffer = aaExpand;
}
xfer->xfer4444(device, span, count, aaBuffer);
}
}
device += count;
runs += count;
antialias += count;
x += count;
}
} else { // no xfermode
for (;;) {
int count = *runs;
if (count <= 0) {
break;
}
int aa = *antialias;
if (aa) {
fShader->shadeSpan(x, y, span, count);
if (255 == aa) {
fOpaqueProc(device, span, count, aa, x, y);
} else {
fAlphaProc(device, span, count, aa, x, y);
}
}
device += count;
runs += count;
antialias += count;
x += count;
}
}
}
private:
typedef SkShaderBlitter INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device,
const SkPaint& paint,
void* storage, size_t storageSize)
{
SkBlitter* blitter;
if (paint.getShader()) {
SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint));
} else {
SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint));
}
return blitter;
}

Просмотреть файл

@ -1,50 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCoreBlitters.h"
SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device) {
fSrcA = paint.getAlpha();
}
void SkA1_Blitter::blitH(int x, int y, int width) {
SkASSERT(x >= 0 && y >= 0 &&
(unsigned)(x + width) <= (unsigned)fDevice.width());
if (fSrcA <= 0x7F) {
return;
}
uint8_t* dst = fDevice.getAddr1(x, y);
int right = x + width;
int left_mask = 0xFF >> (x & 7);
int rite_mask = 0xFF << (8 - (right & 7));
int full_runs = (right >> 3) - ((x + 7) >> 3);
// check for empty right mask, so we don't read off the end
// (or go slower than we need to)
if (rite_mask == 0) {
SkASSERT(full_runs >= 0);
full_runs -= 1;
rite_mask = 0xFF;
}
if (left_mask == 0xFF) {
full_runs -= 1;
}
if (full_runs < 0) {
SkASSERT((left_mask & rite_mask) != 0);
*dst |= (left_mask & rite_mask);
} else {
*dst++ |= left_mask;
memset(dst, 0xFF, full_runs);
dst += full_runs;
*dst |= rite_mask;
}
}

Просмотреть файл

@ -1,159 +0,0 @@
/*
* Copyright 2009 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkColorTable.h"
#include "SkFlattenableBuffers.h"
#include "SkStream.h"
#include "SkTemplates.h"
SK_DEFINE_INST_COUNT(SkColorTable)
SkColorTable::SkColorTable(int count)
: f16BitCache(NULL), fFlags(0)
{
if (count < 0)
count = 0;
else if (count > 256)
count = 256;
fCount = SkToU16(count);
fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
memset(fColors, 0, count * sizeof(SkPMColor));
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
}
// As copy constructor is hidden in the class hierarchy, we need to call
// default constructor explicitly to suppress a compiler warning.
SkColorTable::SkColorTable(const SkColorTable& src) : INHERITED() {
f16BitCache = NULL;
fFlags = src.fFlags;
int count = src.count();
fCount = SkToU16(count);
fColors = reinterpret_cast<SkPMColor*>(
sk_malloc_throw(count * sizeof(SkPMColor)));
memcpy(fColors, src.fColors, count * sizeof(SkPMColor));
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
}
SkColorTable::SkColorTable(const SkPMColor colors[], int count)
: f16BitCache(NULL), fFlags(0)
{
if (count < 0)
count = 0;
else if (count > 256)
count = 256;
fCount = SkToU16(count);
fColors = reinterpret_cast<SkPMColor*>(
sk_malloc_throw(count * sizeof(SkPMColor)));
if (colors)
memcpy(fColors, colors, count * sizeof(SkPMColor));
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
}
SkColorTable::~SkColorTable()
{
SkASSERT(fColorLockCount == 0);
SkASSERT(f16BitCacheLockCount == 0);
sk_free(fColors);
sk_free(f16BitCache);
}
void SkColorTable::setFlags(unsigned flags)
{
fFlags = SkToU8(flags);
}
void SkColorTable::unlockColors(bool changed)
{
SkASSERT(fColorLockCount != 0);
SkDEBUGCODE(sk_atomic_dec(&fColorLockCount);)
if (changed)
this->inval16BitCache();
}
void SkColorTable::inval16BitCache()
{
SkASSERT(f16BitCacheLockCount == 0);
if (f16BitCache)
{
sk_free(f16BitCache);
f16BitCache = NULL;
}
}
#include "SkColorPriv.h"
static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
{
while (--count >= 0)
*dst++ = SkPixel32ToPixel16_ToU16(*src++);
}
const uint16_t* SkColorTable::lock16BitCache()
{
if (fFlags & kColorsAreOpaque_Flag)
{
if (f16BitCache == NULL) // build the cache
{
f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
build_16bitcache(f16BitCache, fColors, fCount);
}
}
else // our colors have alpha, so no cache
{
this->inval16BitCache();
if (f16BitCache)
{
sk_free(f16BitCache);
f16BitCache = NULL;
}
}
SkDEBUGCODE(f16BitCacheLockCount += 1);
return f16BitCache;
}
void SkColorTable::setIsOpaque(bool isOpaque) {
if (isOpaque) {
fFlags |= kColorsAreOpaque_Flag;
} else {
fFlags &= ~kColorsAreOpaque_Flag;
}
}
///////////////////////////////////////////////////////////////////////////////
SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
f16BitCache = NULL;
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
fFlags = buffer.readUInt();
fCount = buffer.getArrayCount();
fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
SkDEBUGCODE(const uint32_t countRead =) buffer.readColorArray(fColors);
#ifdef SK_DEBUG
SkASSERT((unsigned)fCount <= 256);
SkASSERT(countRead == fCount);
#endif
}
void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeUInt(fFlags);
buffer.writeColorArray(fColors, fCount);
}

Просмотреть файл

@ -1,323 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkData.h"
#include "SkFlattenableBuffers.h"
#if SK_MMAP_SUPPORT
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#endif
SK_DEFINE_INST_COUNT(SkData)
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
fPtr = ptr;
fSize = size;
fReleaseProc = proc;
fReleaseProcContext = context;
}
SkData::~SkData() {
if (fReleaseProc) {
fReleaseProc(fPtr, fSize, fReleaseProcContext);
}
}
bool SkData::equals(const SkData* other) const {
if (NULL == other) {
return false;
}
return fSize == other->fSize && !memcmp(fPtr, other->fPtr, fSize);
}
size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
size_t available = fSize;
if (offset >= available || 0 == length) {
return 0;
}
available -= offset;
if (length > available) {
length = available;
}
SkASSERT(length > 0);
memcpy(buffer, this->bytes() + offset, length);
return length;
}
///////////////////////////////////////////////////////////////////////////////
SkData* SkData::NewEmpty() {
static SkData* gEmptyRef;
if (NULL == gEmptyRef) {
gEmptyRef = new SkData(NULL, 0, NULL, NULL);
}
gEmptyRef->ref();
return gEmptyRef;
}
// assumes fPtr was allocated via sk_malloc
static void sk_free_releaseproc(const void* ptr, size_t, void*) {
sk_free((void*)ptr);
}
SkData* SkData::NewFromMalloc(const void* data, size_t length) {
return new SkData(data, length, sk_free_releaseproc, NULL);
}
SkData* SkData::NewWithCopy(const void* data, size_t length) {
if (0 == length) {
return SkData::NewEmpty();
}
void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
memcpy(copy, data, length);
return new SkData(copy, length, sk_free_releaseproc, NULL);
}
SkData* SkData::NewWithProc(const void* data, size_t length,
ReleaseProc proc, void* context) {
return new SkData(data, length, proc, context);
}
// assumes context is a SkData
static void sk_dataref_releaseproc(const void*, size_t, void* context) {
SkData* src = reinterpret_cast<SkData*>(context);
src->unref();
}
SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
/*
We could, if we wanted/need to, just make a deep copy of src's data,
rather than referencing it. This would duplicate the storage (of the
subset amount) but would possibly allow src to go out of scope sooner.
*/
size_t available = src->size();
if (offset >= available || 0 == length) {
return SkData::NewEmpty();
}
available -= offset;
if (length > available) {
length = available;
}
SkASSERT(length > 0);
src->ref(); // this will be balanced in sk_dataref_releaseproc
return new SkData(src->bytes() + offset, length, sk_dataref_releaseproc,
const_cast<SkData*>(src));
}
SkData* SkData::NewWithCString(const char cstr[]) {
size_t size;
if (NULL == cstr) {
cstr = "";
size = 1;
} else {
size = strlen(cstr) + 1;
}
return NewWithCopy(cstr, size);
}
#if SK_MMAP_SUPPORT
static void sk_munmap_releaseproc(const void* addr, size_t length, void*) {
munmap(const_cast<void*>(addr), length);
}
SkData* SkData::NewFromMMap(const void* addr, size_t length) {
return SkNEW_ARGS(SkData, (addr, length, sk_munmap_releaseproc, NULL));
}
#else
SkData* SkData::NewFromMMap(const void* addr, size_t length) {
return NULL;
}
#endif
///////////////////////////////////////////////////////////////////////////////
void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeByteArray(fPtr, fSize);
}
SkData::SkData(SkFlattenableReadBuffer& buffer) {
fSize = buffer.getArrayCount();
fReleaseProcContext = NULL;
if (fSize > 0) {
fPtr = sk_malloc_throw(fSize);
fReleaseProc = sk_free_releaseproc;
} else {
fPtr = NULL;
fReleaseProc = NULL;
}
buffer.readByteArray(const_cast<void*>(fPtr));
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "SkDataSet.h"
#include "SkFlattenable.h"
#include "SkStream.h"
static SkData* dupdata(SkData* data) {
if (data) {
data->ref();
} else {
data = SkData::NewEmpty();
}
return data;
}
static SkData* findValue(const char key[], const SkDataSet::Pair array[], int n) {
for (int i = 0; i < n; ++i) {
if (!strcmp(key, array[i].fKey)) {
return array[i].fValue;
}
}
return NULL;
}
static SkDataSet::Pair* allocatePairStorage(int count, size_t storage) {
size_t size = count * sizeof(SkDataSet::Pair) + storage;
return (SkDataSet::Pair*)sk_malloc_throw(size);
}
SkDataSet::SkDataSet(const char key[], SkData* value) {
size_t keyLen = strlen(key);
fCount = 1;
fKeySize = keyLen + 1;
fPairs = allocatePairStorage(1, keyLen + 1);
fPairs[0].fKey = (char*)(fPairs + 1);
memcpy(const_cast<char*>(fPairs[0].fKey), key, keyLen + 1);
fPairs[0].fValue = dupdata(value);
}
SkDataSet::SkDataSet(const Pair array[], int count) {
if (count < 1) {
fCount = 0;
fKeySize = 0;
fPairs = NULL;
return;
}
int i;
size_t keySize = 0;
for (i = 0; i < count; ++i) {
keySize += strlen(array[i].fKey) + 1;
}
Pair* pairs = fPairs = allocatePairStorage(count, keySize);
char* keyStorage = (char*)(pairs + count);
keySize = 0; // reset this, so we can compute the size for unique keys
int uniqueCount = 0;
for (int i = 0; i < count; ++i) {
if (!findValue(array[i].fKey, pairs, uniqueCount)) {
size_t len = strlen(array[i].fKey);
memcpy(keyStorage, array[i].fKey, len + 1);
pairs[uniqueCount].fKey = keyStorage;
keyStorage += len + 1;
keySize += len + 1;
pairs[uniqueCount].fValue = dupdata(array[i].fValue);
uniqueCount += 1;
}
}
fCount = uniqueCount;
fKeySize = keySize;
}
SkDataSet::~SkDataSet() {
for (int i = 0; i < fCount; ++i) {
fPairs[i].fValue->unref();
}
sk_free(fPairs); // this also frees the key storage
}
SkData* SkDataSet::find(const char key[]) const {
return findValue(key, fPairs, fCount);
}
void SkDataSet::writeToStream(SkWStream* stream) const {
stream->write32(fCount);
if (fCount > 0) {
stream->write32(fKeySize);
// our first key points to all the key storage
stream->write(fPairs[0].fKey, fKeySize);
for (int i = 0; i < fCount; ++i) {
stream->writeData(fPairs[i].fValue);
}
}
}
void SkDataSet::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeInt(fCount);
if (fCount > 0) {
buffer.writeByteArray(fPairs[0].fKey, fKeySize);
for (int i = 0; i < fCount; ++i) {
buffer.writeFlattenable(fPairs[i].fValue);
}
}
}
SkDataSet::SkDataSet(SkStream* stream) {
fCount = stream->readU32();
if (fCount > 0) {
fKeySize = stream->readU32();
fPairs = allocatePairStorage(fCount, fKeySize);
char* keyStorage = (char*)(fPairs + fCount);
stream->read(keyStorage, fKeySize);
for (int i = 0; i < fCount; ++i) {
fPairs[i].fKey = keyStorage;
keyStorage += strlen(keyStorage) + 1;
fPairs[i].fValue = stream->readData();
}
} else {
fKeySize = 0;
fPairs = NULL;
}
}
SkDataSet::SkDataSet(SkFlattenableReadBuffer& buffer) {
fCount = buffer.readInt();
if (fCount > 0) {
fKeySize = buffer.getArrayCount();
fPairs = allocatePairStorage(fCount, fKeySize);
char* keyStorage = (char*)(fPairs + fCount);
buffer.readByteArray(keyStorage);
for (int i = 0; i < fCount; ++i) {
fPairs[i].fKey = keyStorage;
keyStorage += strlen(keyStorage) + 1;
fPairs[i].fValue = buffer.readFlattenableT<SkData>();
}
} else {
fKeySize = 0;
fPairs = NULL;
}
}
SkDataSet* SkDataSet::NewEmpty() {
static SkDataSet* gEmptySet;
if (NULL == gEmptySet) {
gEmptySet = SkNEW_ARGS(SkDataSet, (NULL, 0));
}
gEmptySet->ref();
return gEmptySet;
}

Просмотреть файл

@ -1,546 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkDevice.h"
#include "SkDeviceProperties.h"
#include "SkDraw.h"
#include "SkImageFilter.h"
#include "SkMetaData.h"
#include "SkRasterClip.h"
#include "SkRect.h"
#include "SkShader.h"
SK_DEFINE_INST_COUNT(SkDevice)
///////////////////////////////////////////////////////////////////////////////
#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
///////////////////////////////////////////////////////////////////////////////
SkDevice::SkDevice(const SkBitmap& bitmap)
: fBitmap(bitmap), fLeakyProperties(SkDeviceProperties::MakeDefault())
#ifdef SK_DEBUG
, fAttachedToCanvas(false)
#endif
{
fOrigin.setZero();
fMetaData = NULL;
}
SkDevice::SkDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
: fBitmap(bitmap), fLeakyProperties(deviceProperties)
#ifdef SK_DEBUG
, fAttachedToCanvas(false)
#endif
{
fOrigin.setZero();
fMetaData = NULL;
}
SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque)
: fLeakyProperties(SkDeviceProperties::MakeDefault())
#ifdef SK_DEBUG
, fAttachedToCanvas(false)
#endif
{
fOrigin.setZero();
fMetaData = NULL;
fBitmap.setConfig(config, width, height);
fBitmap.allocPixels();
fBitmap.setIsOpaque(isOpaque);
if (!isOpaque) {
fBitmap.eraseColor(SK_ColorTRANSPARENT);
}
}
SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
const SkDeviceProperties& deviceProperties)
: fLeakyProperties(deviceProperties)
#ifdef SK_DEBUG
, fAttachedToCanvas(false)
#endif
{
fOrigin.setZero();
fMetaData = NULL;
fBitmap.setConfig(config, width, height);
fBitmap.allocPixels();
fBitmap.setIsOpaque(isOpaque);
if (!isOpaque) {
fBitmap.eraseColor(SK_ColorTRANSPARENT);
}
}
SkDevice::~SkDevice() {
delete fMetaData;
}
void SkDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
SkASSERT(bm.width() == fBitmap.width());
SkASSERT(bm.height() == fBitmap.height());
fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
fBitmap.lockPixels();
}
SkDevice* SkDevice::createCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque) {
return this->onCreateCompatibleDevice(config, width, height,
isOpaque, kGeneral_Usage);
}
SkDevice* SkDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
int width, int height,
bool isOpaque) {
return this->onCreateCompatibleDevice(config, width, height,
isOpaque, kSaveLayer_Usage);
}
SkDevice* SkDevice::onCreateCompatibleDevice(SkBitmap::Config config,
int width, int height,
bool isOpaque,
Usage usage) {
return SkNEW_ARGS(SkDevice,(config, width, height, isOpaque, fLeakyProperties));
}
SkMetaData& SkDevice::getMetaData() {
// metadata users are rare, so we lazily allocate it. If that changes we
// can decide to just make it a field in the device (rather than a ptr)
if (NULL == fMetaData) {
fMetaData = new SkMetaData;
}
return *fMetaData;
}
void SkDevice::lockPixels() {
if (fBitmap.lockPixelsAreWritable()) {
fBitmap.lockPixels();
}
}
void SkDevice::unlockPixels() {
if (fBitmap.lockPixelsAreWritable()) {
fBitmap.unlockPixels();
}
}
const SkBitmap& SkDevice::accessBitmap(bool changePixels) {
const SkBitmap& bitmap = this->onAccessBitmap(&fBitmap);
if (changePixels) {
bitmap.notifyPixelsChanged();
}
return bitmap;
}
void SkDevice::getGlobalBounds(SkIRect* bounds) const {
if (bounds) {
bounds->setXYWH(fOrigin.x(), fOrigin.y(),
fBitmap.width(), fBitmap.height());
}
}
void SkDevice::clear(SkColor color) {
fBitmap.eraseColor(color);
}
const SkBitmap& SkDevice::onAccessBitmap(SkBitmap* bitmap) {return *bitmap;}
void SkDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& region,
const SkClipStack& clipStack) {
}
bool SkDevice::canHandleImageFilter(SkImageFilter*) {
return false;
}
bool SkDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
const SkMatrix& ctm, SkBitmap* result,
SkIPoint* offset) {
return false;
}
bool SkDevice::allowImageFilter(SkImageFilter*) {
return true;
}
///////////////////////////////////////////////////////////////////////////////
bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y,
SkCanvas::Config8888 config8888) {
if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
NULL != bitmap->getTexture()) {
return false;
}
const SkBitmap& src = this->accessBitmap(false);
SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(),
bitmap->height());
SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height());
if (!srcRect.intersect(devbounds)) {
return false;
}
SkBitmap tmp;
SkBitmap* bmp;
if (bitmap->isNull()) {
tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
bitmap->height());
if (!tmp.allocPixels()) {
return false;
}
bmp = &tmp;
} else {
bmp = bitmap;
}
SkIRect subrect = srcRect;
subrect.offset(-x, -y);
SkBitmap bmpSubset;
bmp->extractSubset(&bmpSubset, subrect);
bool result = this->onReadPixels(bmpSubset,
srcRect.fLeft,
srcRect.fTop,
config8888);
if (result && bmp == &tmp) {
tmp.swap(*bitmap);
}
return result;
}
#ifdef SK_CPU_LENDIAN
#if 24 == SK_A32_SHIFT && 16 == SK_R32_SHIFT && \
8 == SK_G32_SHIFT && 0 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kBGRA_Premul_Config8888;
#elif 24 == SK_A32_SHIFT && 0 == SK_R32_SHIFT && \
8 == SK_G32_SHIFT && 16 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kRGBA_Premul_Config8888;
#else
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
(SkCanvas::Config8888) -1;
#endif
#else
#if 0 == SK_A32_SHIFT && 8 == SK_R32_SHIFT && \
16 == SK_G32_SHIFT && 24 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kBGRA_Premul_Config8888;
#elif 0 == SK_A32_SHIFT && 24 == SK_R32_SHIFT && \
16 == SK_G32_SHIFT && 8 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kRGBA_Premul_Config8888;
#else
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
(SkCanvas::Config8888) -1;
#endif
#endif
#include <SkConfig8888.h>
bool SkDevice::onReadPixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888) {
SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
SkASSERT(!bitmap.isNull());
SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(),
bitmap.height());
const SkBitmap& src = this->accessBitmap(false);
SkBitmap subset;
if (!src.extractSubset(&subset, srcRect)) {
return false;
}
if (SkBitmap::kARGB_8888_Config != subset.config()) {
// It'd be preferable to do this directly to bitmap.
subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
}
SkAutoLockPixels alp(bitmap);
uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
return true;
}
void SkDevice::writePixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888) {
if (bitmap.isNull() || bitmap.getTexture()) {
return;
}
const SkBitmap* sprite = &bitmap;
// check whether we have to handle a config8888 that doesn't match SkPMColor
if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
SkCanvas::kNative_Premul_Config8888 != config8888 &&
kPMColorAlias != config8888) {
// We're going to have to convert from a config8888 to the native config
// First we clip to the device bounds.
SkBitmap dstBmp = this->accessBitmap(true);
SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
bitmap.width(), bitmap.height());
SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
if (!spriteRect.intersect(devRect)) {
return;
}
// write directly to the device if it has pixels and is SkPMColor
bool drawSprite;
if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
// we can write directly to the dst when doing the conversion
dstBmp.extractSubset(&dstBmp, spriteRect);
drawSprite = false;
} else {
// we convert to a temporary bitmap and draw that as a sprite
dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
spriteRect.width(),
spriteRect.height());
if (!dstBmp.allocPixels()) {
return;
}
drawSprite = true;
}
// copy pixels to dstBmp and convert from config8888 to native config.
SkAutoLockPixels alp(bitmap);
uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
spriteRect.fTop - y);
SkCopyConfig8888ToBitmap(dstBmp,
srcPixels,
bitmap.rowBytes(),
config8888);
if (drawSprite) {
// we've clipped the sprite when we made a copy
x = spriteRect.fLeft;
y = spriteRect.fTop;
sprite = &dstBmp;
} else {
return;
}
}
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
SkDraw draw;
draw.fRC = &clip;
draw.fClip = &clip.bwRgn();
draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
draw.fMatrix = &SkMatrix::I();
this->drawSprite(draw, *sprite, x, y, paint);
}
///////////////////////////////////////////////////////////////////////////////
void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
draw.drawPaint(paint);
}
void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
const SkPoint pts[], const SkPaint& paint) {
CHECK_FOR_NODRAW_ANNOTATION(paint);
draw.drawPoints(mode, count, pts, paint);
}
void SkDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
CHECK_FOR_NODRAW_ANNOTATION(paint);
draw.drawRect(r, paint);
}
void SkDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
CHECK_FOR_NODRAW_ANNOTATION(paint);
SkPath path;
path.addOval(oval);
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
// required to override drawOval.
this->drawPath(draw, path, paint, NULL, true);
}
void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
const SkPaint& paint, const SkMatrix* prePathMatrix,
bool pathIsMutable) {
CHECK_FOR_NODRAW_ANNOTATION(paint);
draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
}
void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
const SkIRect* srcRect,
const SkMatrix& matrix, const SkPaint& paint) {
SkBitmap tmp; // storage if we need a subset of bitmap
const SkBitmap* bitmapPtr = &bitmap;
if (srcRect) {
if (!bitmap.extractSubset(&tmp, *srcRect)) {
return; // extraction failed
}
bitmapPtr = &tmp;
}
draw.drawBitmap(*bitmapPtr, matrix, paint);
}
void SkDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
const SkRect* src, const SkRect& dst,
const SkPaint& paint) {
SkMatrix matrix;
SkRect bitmapBounds, tmpSrc, tmpDst;
SkBitmap tmpBitmap;
bitmapBounds.isetWH(bitmap.width(), bitmap.height());
// Compute matrix from the two rectangles
if (src) {
tmpSrc = *src;
} else {
tmpSrc = bitmapBounds;
}
matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
const SkRect* dstPtr = &dst;
const SkBitmap* bitmapPtr = &bitmap;
// clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
// needed (if the src was clipped). No check needed if src==null.
if (src) {
if (!bitmapBounds.contains(*src)) {
if (!tmpSrc.intersect(bitmapBounds)) {
return; // nothing to draw
}
// recompute dst, based on the smaller tmpSrc
matrix.mapRect(&tmpDst, tmpSrc);
dstPtr = &tmpDst;
}
// since we may need to clamp to the borders of the src rect within
// the bitmap, we extract a subset.
SkIRect srcIR;
tmpSrc.roundOut(&srcIR);
if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
return;
}
bitmapPtr = &tmpBitmap;
// Since we did an extract, we need to adjust the matrix accordingly
SkScalar dx = 0, dy = 0;
if (srcIR.fLeft > 0) {
dx = SkIntToScalar(srcIR.fLeft);
}
if (srcIR.fTop > 0) {
dy = SkIntToScalar(srcIR.fTop);
}
if (dx || dy) {
matrix.preTranslate(dx, dy);
}
SkRect extractedBitmapBounds;
extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
if (extractedBitmapBounds == tmpSrc) {
// no fractional part in src, we can just call drawBitmap
goto USE_DRAWBITMAP;
}
} else {
USE_DRAWBITMAP:
// We can go faster by just calling drawBitmap, which will concat the
// matrix with the CTM, and try to call drawSprite if it can. If not,
// it will make a shader and call drawRect, as we do below.
this->drawBitmap(draw, *bitmapPtr, NULL, matrix, paint);
return;
}
// construct a shader, so we can call drawRect with the dst
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode);
if (NULL == s) {
return;
}
s->setLocalMatrix(matrix);
SkPaint paintWithShader(paint);
paintWithShader.setStyle(SkPaint::kFill_Style);
paintWithShader.setShader(s)->unref();
// Call ourself, in case the subclass wanted to share this setup code
// but handle the drawRect code themselves.
this->drawRect(draw, *dstPtr, paintWithShader);
}
void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) {
draw.drawSprite(bitmap, x, y, paint);
}
void SkDevice::drawText(const SkDraw& draw, const void* text, size_t len,
SkScalar x, SkScalar y, const SkPaint& paint) {
draw.drawText((const char*)text, len, x, y, paint);
}
void SkDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
const SkScalar xpos[], SkScalar y,
int scalarsPerPos, const SkPaint& paint) {
draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
}
void SkDevice::drawTextOnPath(const SkDraw& draw, const void* text,
size_t len, const SkPath& path,
const SkMatrix* matrix,
const SkPaint& paint) {
draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
}
#ifdef SK_BUILD_FOR_ANDROID
void SkDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
const SkPoint pos[], const SkPaint& paint,
const SkPath& path, const SkMatrix* matrix) {
draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
}
#endif
void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
int vertexCount,
const SkPoint verts[], const SkPoint textures[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
indices, indexCount, paint);
}
void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
int x, int y, const SkPaint& paint) {
const SkBitmap& src = device->accessBitmap(false);
draw.drawSprite(src, x, y, paint);
}
///////////////////////////////////////////////////////////////////////////////
bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
// we're cool with the paint as is
return false;
}
if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
paint.getRasterizer() ||
paint.getPathEffect() ||
paint.isFakeBoldText() ||
paint.getStyle() != SkPaint::kFill_Style ||
!SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
// turn off lcd
flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
flags->fHinting = paint.getHinting();
return true;
}
// we're cool with the paint as is
return false;
}

Просмотреть файл

@ -1,104 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkStream.h"
#ifdef SK_BUILD_FOR_WIN
// -1 means isValid() will return false
SkFDStream::SkFDStream(int, bool) : fFD(-1), fCloseWhenDone(false) {}
SkFDStream::~SkFDStream() {}
bool SkFDStream::rewind() { return false; }
size_t SkFDStream::read(void*, size_t) { return 0; }
#else
#include <unistd.h>
//#define TRACE_FDSTREAM
SkFDStream::SkFDStream(int fileDesc, bool closeWhenDone)
: fFD(fileDesc), fCloseWhenDone(closeWhenDone) {
}
SkFDStream::~SkFDStream() {
if (fFD >= 0 && fCloseWhenDone) {
::close(fFD);
}
}
bool SkFDStream::rewind() {
if (fFD >= 0) {
off_t value = ::lseek(fFD, 0, SEEK_SET);
#ifdef TRACE_FDSTREAM
if (value) {
SkDebugf("xxxxxxxxxxxxxx rewind failed %d\n", value);
}
#endif
return value == 0;
}
return false;
}
size_t SkFDStream::read(void* buffer, size_t size) {
if (fFD >= 0) {
if (buffer == NULL && size == 0) { // request total size
off_t curr = ::lseek(fFD, 0, SEEK_CUR);
if (curr < 0) {
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx lseek failed 0 CURR\n");
#endif
return 0; // error
}
off_t size = ::lseek(fFD, 0, SEEK_END);
if (size < 0) {
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx lseek failed 0 END\n");
#endif
size = 0; // error
}
if (::lseek(fFD, curr, SEEK_SET) != curr) {
// can't restore, error
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx lseek failed %d SET\n", curr);
#endif
return 0;
}
return (size_t) size;
} else if (NULL == buffer) { // skip
off_t oldCurr = ::lseek(fFD, 0, SEEK_CUR);
if (oldCurr < 0) {
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx lseek1 failed %d CUR\n", oldCurr);
#endif
return 0; // error;
}
off_t newCurr = ::lseek(fFD, size, SEEK_CUR);
if (newCurr < 0) {
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx lseek2 failed %d CUR\n", newCurr);
#endif
return 0; // error;
}
// return the actual amount we skipped
return (size_t) (newCurr - oldCurr);
} else { // read
ssize_t actual = ::read(fFD, buffer, size);
// our API can't return an error, so we return 0
if (actual < 0) {
#ifdef TRACE_FDSTREAM
SkDebugf("xxxxxxxxxxxxx read failed %d actual %d\n", size, actual);
#endif
actual = 0;
}
return actual;
}
}
return 0;
}
#endif

Просмотреть файл

@ -1,56 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkFlattenableBuffers.h"
#include "SkPaint.h"
#include "SkTypeface.h"
SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
// Set default values. These should be explicitly set by our client
// via setFlags() if the buffer came from serialization.
fFlags = 0;
#ifdef SK_SCALAR_IS_FLOAT
fFlags |= kScalarIsFloat_Flag;
#endif
if (8 == sizeof(void*)) {
fFlags |= kPtrIs64Bit_Flag;
}
}
SkFlattenableReadBuffer::~SkFlattenableReadBuffer() { }
void* SkFlattenableReadBuffer::readFunctionPtr() {
void* proc;
SkASSERT(sizeof(void*) == this->getArrayCount());
this->readByteArray(&proc);
return proc;
}
void SkFlattenableReadBuffer::readPaint(SkPaint* paint) {
paint->unflatten(*this);
}
///////////////////////////////////////////////////////////////////////////////
SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
fFlags = (Flags)0;
}
SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { }
void SkFlattenableWriteBuffer::writeFunctionPtr(void* ptr) {
void* ptrStorage[] = { ptr };
this->writeByteArray(ptrStorage, sizeof(void*));
}
void SkFlattenableWriteBuffer::writePaint(const SkPaint& paint) {
paint.flatten(*this);
}
void SkFlattenableWriteBuffer::flattenObject(SkFlattenable* obj, SkFlattenableWriteBuffer& buffer) {
obj->flatten(buffer);
}

Просмотреть файл

@ -1,175 +0,0 @@
/*
* Copyright 2009 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkFontLCDConfig.h"
static SkFontLCDConfig::LCDOrientation gLCDOrientation = SkFontLCDConfig::kHorizontal_LCDOrientation;
static SkFontLCDConfig::LCDOrder gLCDOrder = SkFontLCDConfig::kRGB_LCDOrder;
SkFontLCDConfig::LCDOrientation SkFontLCDConfig::GetSubpixelOrientation() {
return gLCDOrientation;
}
void SkFontLCDConfig::SetSubpixelOrientation(LCDOrientation orientation) {
gLCDOrientation = orientation;
}
SkFontLCDConfig::LCDOrder SkFontLCDConfig::GetSubpixelOrder() {
return gLCDOrder;
}
void SkFontLCDConfig::SetSubpixelOrder(LCDOrder order) {
gLCDOrder = order;
}
///////////////////////////////////////////////////////////////////////////////
// Legacy wrappers : remove from SkFontHost when webkit switches to new API
#include "SkFontHost.h"
SkFontHost::LCDOrientation SkFontHost::GetSubpixelOrientation() {
return (SkFontHost::LCDOrientation)SkFontLCDConfig::GetSubpixelOrientation();
}
void SkFontHost::SetSubpixelOrientation(LCDOrientation orientation) {
SkFontLCDConfig::SetSubpixelOrientation((SkFontLCDConfig::LCDOrientation)orientation);
}
SkFontHost::LCDOrder SkFontHost::GetSubpixelOrder() {
return (SkFontHost::LCDOrder)SkFontLCDConfig::GetSubpixelOrder();
}
void SkFontHost::SetSubpixelOrder(LCDOrder order) {
SkFontLCDConfig::SetSubpixelOrder((SkFontLCDConfig::LCDOrder)order);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "SkFontStyle.h"
SkFontStyle::SkFontStyle() {
fUnion.fU32 = 0;
fUnion.fR.fWeight = kNormal_Weight;
fUnion.fR.fWidth = kNormal_Width;
fUnion.fR.fSlant = kUpright_Slant;
}
SkFontStyle::SkFontStyle(int weight, int width, Slant slant) {
fUnion.fU32 = 0;
fUnion.fR.fWeight = SkPin32(weight, kThin_Weight, kBlack_Weight);
fUnion.fR.fWidth = SkPin32(width, kUltraCondensed_Width, kUltaExpanded_Width);
fUnion.fR.fSlant = SkPin32(slant, kUpright_Slant, kItalic_Slant);
}
#include "SkFontMgr.h"
class SkEmptyFontStyleSet : public SkFontStyleSet {
public:
virtual int count() SK_OVERRIDE { return 0; }
virtual void getStyle(int, SkFontStyle*, SkString*) SK_OVERRIDE {
SkASSERT(!"SkFontStyleSet::getStyle called on empty set");
}
virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
SkASSERT(!"SkFontStyleSet::createTypeface called on empty set");
return NULL;
}
virtual SkTypeface* matchStyle(const SkFontStyle&) SK_OVERRIDE {
return NULL;
}
};
SkFontStyleSet* SkFontStyleSet::CreateEmpty() {
return SkNEW(SkEmptyFontStyleSet);
}
///////////////////////////////////////////////////////////////////////////////
class SkEmptyFontMgr : public SkFontMgr {
protected:
virtual int onCountFamilies() SK_OVERRIDE {
return 0;
}
virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
SkASSERT(!"onGetFamilyName called with bad index");
}
virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
SkASSERT(!"onCreateStyleSet called with bad index");
return NULL;
}
virtual SkFontStyleSet* onMatchFamily(const char[]) SK_OVERRIDE {
return SkFontStyleSet::CreateEmpty();
}
virtual SkTypeface* onMatchFamilyStyle(const char[],
const SkFontStyle&) SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
const SkFontStyle&) SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onCreateFromData(SkData*, int) SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onCreateFromStream(SkStream*, int) SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onCreateFromFile(const char[], int) SK_OVERRIDE {
return NULL;
}
};
int SkFontMgr::countFamilies() {
return this->onCountFamilies();
}
void SkFontMgr::getFamilyName(int index, SkString* familyName) {
this->onGetFamilyName(index, familyName);
}
SkFontStyleSet* SkFontMgr::createStyleSet(int index) {
return this->onCreateStyleSet(index);
}
SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) {
return this->onMatchFamily(familyName);
}
SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
const SkFontStyle& fs) {
return this->onMatchFamilyStyle(familyName, fs);
}
SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face,
const SkFontStyle& fs) {
return this->onMatchFaceStyle(face, fs);
}
SkTypeface* SkFontMgr::createFromData(SkData* data, int ttcIndex) {
return this->onCreateFromData(data, ttcIndex);
}
SkTypeface* SkFontMgr::createFromStream(SkStream* stream, int ttcIndex) {
return this->onCreateFromStream(stream, ttcIndex);
}
SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) {
return this->onCreateFromFile(path, ttcIndex);
}
SkFontMgr* SkFontMgr::RefDefault() {
static SkFontMgr* gFM;
if (NULL == gFM) {
gFM = SkFontMgr::Factory();
// we never want to return NULL
if (NULL == gFM) {
gFM = SkNEW(SkEmptyFontMgr);
}
}
return SkRef(gFM);
}

Просмотреть файл

@ -1,127 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkImageFilter.h"
#include "SkBitmap.h"
#include "SkFlattenableBuffers.h"
#include "SkRect.h"
SK_DEFINE_INST_COUNT(SkImageFilter)
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs)
: fInputCount(inputCount), fInputs(new SkImageFilter*[inputCount]) {
for (int i = 0; i < inputCount; ++i) {
fInputs[i] = inputs[i];
SkSafeRef(fInputs[i]);
}
}
SkImageFilter::SkImageFilter(SkImageFilter* input)
: fInputCount(1), fInputs(new SkImageFilter*[1]) {
fInputs[0] = input;
SkSafeRef(fInputs[0]);
}
SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2)
: fInputCount(2), fInputs(new SkImageFilter*[2]) {
fInputs[0] = input1;
fInputs[1] = input2;
SkSafeRef(fInputs[0]);
SkSafeRef(fInputs[1]);
}
SkImageFilter::~SkImageFilter() {
for (int i = 0; i < fInputCount; i++) {
SkSafeUnref(fInputs[i]);
}
delete[] fInputs;
}
SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer)
: fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) {
for (int i = 0; i < fInputCount; i++) {
if (buffer.readBool()) {
fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable());
} else {
fInputs[i] = NULL;
}
}
}
void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeInt(fInputCount);
for (int i = 0; i < fInputCount; i++) {
SkImageFilter* input = getInput(i);
buffer.writeBool(input != NULL);
if (input != NULL) {
buffer.writeFlattenable(input);
}
}
}
SkBitmap SkImageFilter::getInputResult(int index, Proxy* proxy,
const SkBitmap& src, const SkMatrix& ctm,
SkIPoint* loc) {
SkASSERT(index < fInputCount);
SkImageFilter* input = getInput(index);
SkBitmap result;
if (input && input->filterImage(proxy, src, ctm, &result, loc)) {
return result;
} else {
return src;
}
}
bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* result, SkIPoint* loc) {
SkASSERT(result);
SkASSERT(loc);
/*
* Give the proxy first shot at the filter. If it returns false, ask
* the filter to do it.
*/
return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
this->onFilterImage(proxy, src, ctm, result, loc);
}
bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) {
SkASSERT(&src);
SkASSERT(dst);
return this->onFilterBounds(src, ctm, dst);
}
bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
SkBitmap*, SkIPoint*) {
return false;
}
bool SkImageFilter::canFilterImageGPU() const {
return false;
}
bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
SkASSERT(false); // Should never be called, since canFilterImageGPU() returned false.
return false;
}
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) {
*dst = src;
return true;
}
bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*) const {
return false;
}
bool SkImageFilter::asColorFilter(SkColorFilter**) const {
return false;
}

Просмотреть файл

@ -1,66 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkMallocPixelRef.h"
#include "SkBitmap.h"
#include "SkFlattenableBuffers.h"
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
SkColorTable* ctable, bool ownPixels) {
if (NULL == storage) {
SkASSERT(ownPixels);
storage = sk_malloc_throw(size);
}
fStorage = storage;
fSize = size;
fCTable = ctable;
SkSafeRef(ctable);
fOwnPixels = ownPixels;
this->setPreLocked(fStorage, fCTable);
}
SkMallocPixelRef::~SkMallocPixelRef() {
SkSafeUnref(fCTable);
if (fOwnPixels) {
sk_free(fStorage);
}
}
void* SkMallocPixelRef::onLockPixels(SkColorTable** ct) {
*ct = fCTable;
return fStorage;
}
void SkMallocPixelRef::onUnlockPixels() {
// nothing to do
}
void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeByteArray(fStorage, fSize);
buffer.writeBool(fCTable != NULL);
if (fCTable) {
buffer.writeFlattenable(fCTable);
}
}
SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer, NULL) {
fSize = buffer.getArrayCount();
fStorage = sk_malloc_throw(fSize);
buffer.readByteArray(fStorage);
if (buffer.readBool()) {
fCTable = buffer.readFlattenableT<SkColorTable>();
} else {
fCTable = NULL;
}
fOwnPixels = true;
this->setPreLocked(fStorage, fCTable);
}

Просмотреть файл

@ -1,267 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTypes.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef SK_DEBUG
#define SK_TAG_BLOCKS
// #define SK_TRACK_ALLOC // enable to see a printf for every alloc/free
// #define SK_CHECK_TAGS // enable to double-check debugging link list
#endif
#ifdef SK_TAG_BLOCKS
#include "SkThread.h"
// size this (as a multiple of 4) so that the total offset to the internal data
// is at least a multiple of 8 (since some clients of our malloc may require
// that.
static const char kBlockHeaderTag[] = { 's', 'k', 'i', 'a', '1', '2', '3', '4' };
static const char kBlockTrailerTag[] = { 'a', 'i', 'k', 's' };
#define kByteFill 0xCD
#define kDeleteFill 0xEF
static SkBaseMutex& get_block_mutex() {
static SkMutex* gBlockMutex;
if (NULL == gBlockMutex) {
gBlockMutex = new SkMutex;
}
return *gBlockMutex;
}
static struct SkBlockHeader* gHeader;
struct SkBlockHeader {
SkBlockHeader* fNext;
#ifdef SK_CHECK_TAGS
SkBlockHeader** fTop; // set to verify in debugger that block was alloc'd / freed with same gHeader
SkBlockHeader* fPrevious; // set to see in debugger previous block when corruption happens
#endif
size_t fSize;
char fHeader[sizeof(kBlockHeaderTag)];
// data goes here. The offset to this point must be a multiple of 8
char fTrailer[sizeof(kBlockTrailerTag)];
void* add(size_t realSize)
{
SkAutoMutexAcquire ac(get_block_mutex());
InMutexValidate();
fNext = gHeader;
#ifdef SK_CHECK_TAGS
fTop = &gHeader;
fPrevious = NULL;
if (fNext != NULL)
fNext->fPrevious = this;
#endif
gHeader = this;
fSize = realSize;
memcpy(fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag));
void* result = fTrailer;
void* trailer = (char*)result + realSize;
memcpy(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag));
return result;
}
static void Dump()
{
SkAutoMutexAcquire ac(get_block_mutex());
InMutexValidate();
SkBlockHeader* header = gHeader;
int count = 0;
size_t size = 0;
while (header != NULL) {
char scratch[256];
char* pos = scratch;
size_t size = header->fSize;
int* data = (int*)(void*)header->fTrailer;
pos += sprintf(pos, "%p 0x%08zx (%7zd) ",
data, size, size);
size >>= 2;
size_t ints = size > 4 ? 4 : size;
size_t index;
for (index = 0; index < ints; index++)
pos += sprintf(pos, "0x%08x ", data[index]);
pos += sprintf(pos, " (");
for (index = 0; index < ints; index++)
pos += sprintf(pos, "%g ", data[index] / 65536.0f);
if (ints > 0)
--pos;
pos += sprintf(pos, ") \"");
size_t chars = size > 16 ? 16 : size;
char* chPtr = (char*) data;
for (index = 0; index < chars; index++) {
char ch = chPtr[index];
pos += sprintf(pos, "%c", ch >= ' ' && ch < 0x7f ? ch : '?');
}
pos += sprintf(pos, "\"");
SkDebugf("%s\n", scratch);
count++;
size += header->fSize;
header = header->fNext;
}
SkDebugf("--- count %d size 0x%08x (%zd) ---\n", count, size, size);
}
void remove() const
{
SkAutoMutexAcquire ac(get_block_mutex());
SkBlockHeader** findPtr = &gHeader;
do {
SkBlockHeader* find = *findPtr;
SkASSERT(find != NULL);
if (find == this) {
*findPtr = fNext;
break;
}
findPtr = &find->fNext;
} while (true);
InMutexValidate();
SkASSERT(memcmp(fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag)) == 0);
const char* trailer = fTrailer + fSize;
SkASSERT(memcmp(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag)) == 0);
}
static void Validate()
{
SkAutoMutexAcquire ac(get_block_mutex());
InMutexValidate();
}
private:
static void InMutexValidate()
{
SkBlockHeader* header = gHeader;
while (header != NULL) {
SkASSERT(memcmp(header->fHeader, kBlockHeaderTag, sizeof(kBlockHeaderTag)) == 0);
char* trailer = header->fTrailer + header->fSize;
SkASSERT(memcmp(trailer, kBlockTrailerTag, sizeof(kBlockTrailerTag)) == 0);
header = header->fNext;
}
}
};
void ValidateHeap();
void ValidateHeap()
{
SkBlockHeader::Validate();
}
#else
void ValidateHeap() {}
#endif
void sk_throw()
{
SkDEBUGFAIL("sk_throw");
abort();
}
void sk_out_of_memory(void)
{
SkDEBUGFAIL("sk_out_of_memory");
abort();
}
void* sk_malloc_throw(size_t size)
{
return sk_malloc_flags(size, SK_MALLOC_THROW);
}
void* sk_realloc_throw(void* addr, size_t size)
{
#ifdef SK_TAG_BLOCKS
ValidateHeap();
if (addr != NULL) {
SkBlockHeader* header = (SkBlockHeader*)
((char*)addr - SK_OFFSETOF(SkBlockHeader, fTrailer));
header->remove();
#ifdef SK_TRACK_ALLOC
printf("sk_realloc_throw %p oldSize=%zd\n", addr, header->fSize);
#endif
addr = header;
}
size_t realSize = size;
if (size)
size += sizeof(SkBlockHeader);
#endif
void* p = realloc(addr, size);
if (size == 0)
{
ValidateHeap();
return p;
}
if (p == NULL)
sk_throw();
#ifdef SK_TAG_BLOCKS
else
{
SkBlockHeader* header = (SkBlockHeader*) p;
p = header->add(realSize);
#ifdef SK_TRACK_ALLOC
printf("sk_realloc_throw %p size=%zd\n", p, realSize);
#endif
}
#endif
ValidateHeap();
return p;
}
void sk_free(void* p)
{
if (p)
{
ValidateHeap();
#ifdef SK_TAG_BLOCKS
SkBlockHeader* header = (SkBlockHeader*)
((char*)p - SK_OFFSETOF(SkBlockHeader, fTrailer));
header->remove();
#ifdef SK_TRACK_ALLOC
printf("sk_free %p size=%zd\n", p, header->fSize);
#endif
size_t size = header->fSize + sizeof(SkBlockHeader);
memset(header, kDeleteFill, size);
p = header;
#endif
ValidateHeap();
free(p);
ValidateHeap();
}
}
void* sk_malloc_flags(size_t size, unsigned flags)
{
ValidateHeap();
#ifdef SK_TAG_BLOCKS
size_t realSize = size;
size += sizeof(SkBlockHeader);
#endif
void* p = malloc(size);
if (p == NULL)
{
if (flags & SK_MALLOC_THROW)
sk_throw();
}
#ifdef SK_TAG_BLOCKS
else
{
SkBlockHeader* header = (SkBlockHeader*) p;
p = header->add(realSize);
memset(p, kByteFill, realSize);
#ifdef SK_TRACK_ALLOC
printf("sk_malloc_flags %p size=%zd\n", p, realSize);
#endif
}
#endif
ValidateHeap();
return p;
}

Просмотреть файл

@ -1,256 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkOrderedReadBuffer.h"
#include "SkStream.h"
#include "SkTypeface.h"
SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() {
fMemoryPtr = NULL;
fBitmapStorage = NULL;
fTFArray = NULL;
fTFCount = 0;
fFactoryTDArray = NULL;
fFactoryArray = NULL;
fFactoryCount = 0;
fBitmapDecoder = NULL;
}
SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() {
fReader.setMemory(data, size);
fMemoryPtr = NULL;
fBitmapStorage = NULL;
fTFArray = NULL;
fTFCount = 0;
fFactoryTDArray = NULL;
fFactoryArray = NULL;
fFactoryCount = 0;
fBitmapDecoder = NULL;
}
SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
const size_t length = stream->getLength();
fMemoryPtr = sk_malloc_throw(length);
stream->read(fMemoryPtr, length);
fReader.setMemory(fMemoryPtr, length);
fBitmapStorage = NULL;
fTFArray = NULL;
fTFCount = 0;
fFactoryTDArray = NULL;
fFactoryArray = NULL;
fFactoryCount = 0;
fBitmapDecoder = NULL;
}
SkOrderedReadBuffer::~SkOrderedReadBuffer() {
sk_free(fMemoryPtr);
SkSafeUnref(fBitmapStorage);
}
bool SkOrderedReadBuffer::readBool() {
return fReader.readBool();
}
SkColor SkOrderedReadBuffer::readColor() {
return fReader.readInt();
}
SkFixed SkOrderedReadBuffer::readFixed() {
return fReader.readS32();
}
int32_t SkOrderedReadBuffer::readInt() {
return fReader.readInt();
}
SkScalar SkOrderedReadBuffer::readScalar() {
return fReader.readScalar();
}
uint32_t SkOrderedReadBuffer::readUInt() {
return fReader.readU32();
}
int32_t SkOrderedReadBuffer::read32() {
return fReader.readInt();
}
char* SkOrderedReadBuffer::readString() {
const char* string = fReader.readString();
const size_t length = strlen(string);
char* value = (char*)sk_malloc_throw(length + 1);
strcpy(value, string);
return value;
}
void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
SkDEBUGCODE(int32_t encodingType = ) fReader.readInt();
SkASSERT(encodingType == encoding);
*length = fReader.readInt();
void* data = sk_malloc_throw(*length);
memcpy(data, fReader.skip(SkAlign4(*length)), *length);
return data;
}
void SkOrderedReadBuffer::readPoint(SkPoint* point) {
point->fX = fReader.readScalar();
point->fY = fReader.readScalar();
}
void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) {
fReader.readMatrix(matrix);
}
void SkOrderedReadBuffer::readIRect(SkIRect* rect) {
memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect));
}
void SkOrderedReadBuffer::readRect(SkRect* rect) {
memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect));
}
void SkOrderedReadBuffer::readRegion(SkRegion* region) {
fReader.readRegion(region);
}
void SkOrderedReadBuffer::readPath(SkPath* path) {
fReader.readPath(path);
}
uint32_t SkOrderedReadBuffer::readByteArray(void* value) {
const uint32_t length = fReader.readU32();
memcpy(value, fReader.skip(SkAlign4(length)), length);
return length;
}
uint32_t SkOrderedReadBuffer::readColorArray(SkColor* colors) {
const uint32_t count = fReader.readU32();
const uint32_t byteLength = count * sizeof(SkColor);
memcpy(colors, fReader.skip(SkAlign4(byteLength)), byteLength);
return count;
}
uint32_t SkOrderedReadBuffer::readIntArray(int32_t* values) {
const uint32_t count = fReader.readU32();
const uint32_t byteLength = count * sizeof(int32_t);
memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength);
return count;
}
uint32_t SkOrderedReadBuffer::readPointArray(SkPoint* points) {
const uint32_t count = fReader.readU32();
const uint32_t byteLength = count * sizeof(SkPoint);
memcpy(points, fReader.skip(SkAlign4(byteLength)), byteLength);
return count;
}
uint32_t SkOrderedReadBuffer::readScalarArray(SkScalar* values) {
const uint32_t count = fReader.readU32();
const uint32_t byteLength = count * sizeof(SkScalar);
memcpy(values, fReader.skip(SkAlign4(byteLength)), byteLength);
return count;
}
uint32_t SkOrderedReadBuffer::getArrayCount() {
return *(uint32_t*)fReader.peek();
}
void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
const size_t length = this->readUInt();
if (length > 0) {
// Bitmap was encoded.
const void* data = this->skip(length);
const int width = this->readInt();
const int height = this->readInt();
if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
SkASSERT(bitmap->width() == width && bitmap->height() == height);
} else {
// This bitmap was encoded when written, but we are unable to decode, possibly due to
// not having a decoder. Use a placeholder bitmap.
SkDebugf("Could not decode bitmap. Resulting bitmap will be red.\n");
bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap->allocPixels();
bitmap->eraseColor(SK_ColorRED);
}
} else {
if (fBitmapStorage) {
const uint32_t index = fReader.readU32();
fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap)
*bitmap = *fBitmapStorage->getBitmap(index);
fBitmapStorage->releaseRef(index);
} else {
bitmap->unflatten(*this);
}
}
}
SkTypeface* SkOrderedReadBuffer::readTypeface() {
uint32_t index = fReader.readU32();
if (0 == index || index > (unsigned)fTFCount) {
if (index) {
SkDebugf("====== typeface index %d\n", index);
}
return NULL;
} else {
SkASSERT(fTFArray);
return fTFArray[index - 1];
}
}
SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
SkFlattenable::Factory factory = NULL;
if (fFactoryCount > 0) {
int32_t index = fReader.readU32();
if (0 == index) {
return NULL; // writer failed to give us the flattenable
}
index -= 1; // we stored the index-base-1
SkASSERT(index < fFactoryCount);
factory = fFactoryArray[index];
} else if (fFactoryTDArray) {
int32_t index = fReader.readU32();
if (0 == index) {
return NULL; // writer failed to give us the flattenable
}
index -= 1; // we stored the index-base-1
factory = (*fFactoryTDArray)[index];
} else {
factory = (SkFlattenable::Factory)readFunctionPtr();
if (NULL == factory) {
return NULL; // writer failed to give us the flattenable
}
}
// if we get here, factory may still be null, but if that is the case, the
// failure was ours, not the writer.
SkFlattenable* obj = NULL;
uint32_t sizeRecorded = fReader.readU32();
if (factory) {
uint32_t offset = fReader.offset();
obj = (*factory)(*this);
// check that we read the amount we expected
uint32_t sizeRead = fReader.offset() - offset;
if (sizeRecorded != sizeRead) {
// we could try to fix up the offset...
sk_throw();
}
} else {
// we must skip the remaining data
fReader.skip(sizeRecorded);
}
return obj;
}

Просмотреть файл

@ -1,128 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkOrderedReadBuffer_DEFINED
#define SkOrderedReadBuffer_DEFINED
#include "SkRefCnt.h"
#include "SkBitmapHeap.h"
#include "SkFlattenableBuffers.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkReader32.h"
class SkBitmap;
class SkOrderedReadBuffer : public SkFlattenableReadBuffer {
public:
SkOrderedReadBuffer();
SkOrderedReadBuffer(const void* data, size_t size);
SkOrderedReadBuffer(SkStream* stream);
virtual ~SkOrderedReadBuffer();
virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() SK_OVERRIDE { return this; }
SkReader32* getReader32() { return &fReader; }
uint32_t size() { return fReader.size(); }
uint32_t offset() { return fReader.offset(); }
bool eof() { return fReader.eof(); }
const void* skip(size_t size) { return fReader.skip(size); }
// primitives
virtual bool readBool() SK_OVERRIDE;
virtual SkColor readColor() SK_OVERRIDE;
virtual SkFixed readFixed() SK_OVERRIDE;
virtual int32_t readInt() SK_OVERRIDE;
virtual SkScalar readScalar() SK_OVERRIDE;
virtual uint32_t readUInt() SK_OVERRIDE;
virtual int32_t read32() SK_OVERRIDE;
// strings -- the caller is responsible for freeing the string contents
virtual char* readString() SK_OVERRIDE;
virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE;
// common data structures
virtual SkFlattenable* readFlattenable() SK_OVERRIDE;
virtual void readPoint(SkPoint* point) SK_OVERRIDE;
virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE;
virtual void readIRect(SkIRect* rect) SK_OVERRIDE;
virtual void readRect(SkRect* rect) SK_OVERRIDE;
virtual void readRegion(SkRegion* region) SK_OVERRIDE;
virtual void readPath(SkPath* path) SK_OVERRIDE;
// binary data and arrays
virtual uint32_t readByteArray(void* value) SK_OVERRIDE;
virtual uint32_t readColorArray(SkColor* colors) SK_OVERRIDE;
virtual uint32_t readIntArray(int32_t* values) SK_OVERRIDE;
virtual uint32_t readPointArray(SkPoint* points) SK_OVERRIDE;
virtual uint32_t readScalarArray(SkScalar* values) SK_OVERRIDE;
// helpers to get info about arrays and binary data
virtual uint32_t getArrayCount() SK_OVERRIDE;
virtual void readBitmap(SkBitmap* bitmap) SK_OVERRIDE;
virtual SkTypeface* readTypeface() SK_OVERRIDE;
void setBitmapStorage(SkBitmapHeapReader* bitmapStorage) {
SkRefCnt_SafeAssign(fBitmapStorage, bitmapStorage);
}
void setTypefaceArray(SkTypeface* array[], int count) {
fTFArray = array;
fTFCount = count;
}
/**
* Call this with a pre-loaded array of Factories, in the same order as
* were created/written by the writer. SkPicture uses this.
*/
void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
fFactoryTDArray = NULL;
fFactoryArray = array;
fFactoryCount = count;
}
/**
* Call this with an initially empty array, so the reader can cache each
* factory it sees by name. Used by the pipe code in conjunction with
* SkOrderedWriteBuffer::setNamedFactoryRecorder.
*/
void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
fFactoryTDArray = array;
fFactoryArray = NULL;
fFactoryCount = 0;
}
/**
* Provide a function to decode an SkBitmap from encoded data. Only used if the writer
* encoded the SkBitmap. If the proper decoder cannot be used, a red bitmap with the
* appropriate size will be used.
*/
void setBitmapDecoder(SkPicture::InstallPixelRefProc bitmapDecoder) {
fBitmapDecoder = bitmapDecoder;
}
private:
SkReader32 fReader;
void* fMemoryPtr;
SkBitmapHeapReader* fBitmapStorage;
SkTypeface** fTFArray;
int fTFCount;
SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
SkFlattenable::Factory* fFactoryArray;
int fFactoryCount;
SkPicture::InstallPixelRefProc fBitmapDecoder;
typedef SkFlattenableReadBuffer INHERITED;
};
#endif // SkOrderedReadBuffer_DEFINED

Просмотреть файл

@ -1,606 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPathRef_DEFINED
#define SkPathRef_DEFINED
#include "SkRefCnt.h"
#include <stddef.h> // ptrdiff_t
// When we're ready to break the picture format. Changes:
// * Write genID.
// * SkPathRef read/write counts (which will change the field order)
// * SkPathRef reads/writes verbs backwards.
#define NEW_PICTURE_FORMAT 0
/**
* Holds the path verbs and points. It is versioned by a generation ID. None of its public methods
* modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an
* SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs
* copy-on-write if the SkPathRef is shared by multipls SkPaths. The caller passes the Editor's
* constructor a SkAutoTUnref, which may be updated to point to a new SkPathRef after the editor's
* constructor returns.
*
* The points and verbs are stored in a single allocation. The points are at the begining of the
* allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points
* and verbs both grow into the middle of the allocation until the meet. To access verb i in the
* verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first
* logical verb or the last verb in memory).
*/
class SkPathRef;
// This path ref should never be deleted once it is created. It should not be global but was made
// so for checks when SK_DEBUG_PATH_REF is enabled. It we be re-hidden when the debugging code is
// reverted.
SkPathRef* gEmptyPathRef;
// Temporary hackery to try to nail down http://code.google.com/p/chromium/issues/detail?id=148637
#if SK_DEBUG_PATH_REF
#define PR_CONTAINER SkPath::PathRefDebugRef
#define SkDEBUGCODE_X(code) code
#define SkASSERT_X(cond) SK_DEBUGBREAK(cond)
// We put the mutex in a factory function to protect against static-initializion order
// fiasco when SkPaths are created before main().
static SkMutex* owners_mutex() {
static SkMutex* gOwnersMutex;
if (!gOwnersMutex) {
gOwnersMutex = new SkMutex(); // leak!
}
return gOwnersMutex;
}
// We have a static initializer that calls owners_mutex before main() so that
// hopefully that we only wind up with one mutex (assuming no threads created
// before static initialization is finished.)
static const SkMutex* gOwnersMutexForce = owners_mutex();
#else
#define PR_CONTAINER SkAutoTUnref<SkPathRef>
#define SkDEBUGCODE_X(code) SkDEBUGCODE(code)
#define SkASSERT_X(cond) SkASSERT(cond)
#endif
class SkPathRef : public ::SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkPathRef);
class Editor {
public:
Editor(PR_CONTAINER* pathRef,
int incReserveVerbs = 0,
int incReservePoints = 0) {
if (pathRef->get()->getRefCnt() > 1) {
SkPathRef* copy = SkNEW(SkPathRef);
copy->copy(*pathRef->get(), incReserveVerbs, incReservePoints);
pathRef->reset(copy);
} else {
(*pathRef)->incReserve(incReserveVerbs, incReservePoints);
}
fPathRef = pathRef->get();
fPathRef->fGenerationID = 0;
SkDEBUGCODE_X(sk_atomic_inc(&fPathRef->fEditorsAttached);)
}
~Editor() { SkDEBUGCODE_X(sk_atomic_dec(&fPathRef->fEditorsAttached);) }
/**
* Returns the array of points.
*/
SkPoint* points() { return fPathRef->fPoints; }
/**
* Gets the ith point. Shortcut for this->points() + i
*/
SkPoint* atPoint(int i) {
SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
return this->points() + i;
};
/**
* Adds the verb and allocates space for the number of points indicated by the verb. The
* return value is a pointer to where the points for the verb should be written.
*/
SkPoint* growForVerb(SkPath::Verb verb) {
fPathRef->validate();
return fPathRef->growForVerb(verb);
}
/**
* Allocates space for additional verbs and points and returns pointers to the new verbs and
* points. verbs will point one beyond the first new verb (index it using [~<i>]). pts points
* at the first new point (indexed normally [<i>]).
*/
void grow(int newVerbs, int newPts, uint8_t** verbs, SkPoint** pts) {
SkASSERT(NULL != verbs);
SkASSERT(NULL != pts);
fPathRef->validate();
int oldVerbCnt = fPathRef->fVerbCnt;
int oldPointCnt = fPathRef->fPointCnt;
SkASSERT(verbs && pts);
fPathRef->grow(newVerbs, newPts);
*verbs = fPathRef->fVerbs - oldVerbCnt;
*pts = fPathRef->fPoints + oldPointCnt;
fPathRef->validate();
}
/**
* Resets the path ref to a new verb and point count. The new verbs and points are
* uninitialized.
*/
void resetToSize(int newVerbCnt, int newPointCnt) {
fPathRef->resetToSize(newVerbCnt, newPointCnt);
}
/**
* Gets the path ref that is wrapped in the Editor.
*/
SkPathRef* pathRef() { return fPathRef; }
private:
SkPathRef* fPathRef;
};
public:
#if SK_DEBUG_PATH_REF
void addOwner(SkPath* owner) {
SkAutoMutexAcquire ac(owners_mutex());
for (int i = 0; i < fOwners.count(); ++i) {
SkASSERT_X(fOwners[i] != owner);
}
*fOwners.append() = owner;
SkASSERT_X((this->getRefCnt() == fOwners.count()) ||
(this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1));
}
void removeOwner(SkPath* owner) {
SkAutoMutexAcquire ac(owners_mutex());
SkASSERT_X((this->getRefCnt() == fOwners.count()) ||
(this == gEmptyPathRef && this->getRefCnt() == fOwners.count() + 1));
bool found = false;
for (int i = 0; !found && i < fOwners.count(); ++i) {
found = (owner == fOwners[i]);
if (found) {
fOwners.remove(i);
}
}
SkASSERT_X(found);
}
#endif
/**
* Gets a path ref with no verbs or points.
*/
static SkPathRef* CreateEmpty() {
if (!gEmptyPathRef) {
gEmptyPathRef = SkNEW(SkPathRef); // leak!
}
return SkRef(gEmptyPathRef);
}
/**
* Transforms a path ref by a matrix, allocating a new one only if necessary.
*/
static void CreateTransformedCopy(PR_CONTAINER* dst,
const SkPathRef& src,
const SkMatrix& matrix) {
src.validate();
if (matrix.isIdentity()) {
if (dst->get() != &src) {
src.ref();
dst->reset(const_cast<SkPathRef*>(&src));
(*dst)->validate();
}
return;
}
int32_t rcnt = dst->get()->getRefCnt();
if (&src == dst->get() && 1 == rcnt) {
matrix.mapPoints((*dst)->fPoints, (*dst)->fPointCnt);
return;
} else if (rcnt > 1) {
dst->reset(SkNEW(SkPathRef));
}
(*dst)->resetToSize(src.fVerbCnt, src.fPointCnt);
memcpy((*dst)->verbsMemWritable(), src.verbsMemBegin(), src.fVerbCnt * sizeof(uint8_t));
matrix.mapPoints((*dst)->fPoints, src.points(), src.fPointCnt);
(*dst)->validate();
}
#if NEW_PICTURE_FORMAT
static SkPathRef* CreateFromBuffer(SkRBuffer* buffer) {
SkPathRef* ref = SkNEW(SkPathRef);
ref->fGenerationID = buffer->readU32();
int32_t verbCount = buffer->readS32();
int32_t pointCount = buffer->readS32();
ref->resetToSize(verbCount, pointCount);
SkASSERT(verbCount == ref->countVerbs());
SkASSERT(pointCount == ref->countPoints());
buffer->read(ref->verbsMemWritable(), verbCount * sizeof(uint8_t));
buffer->read(ref->fPoints, pointCount * sizeof(SkPoint));
return ref;
}
#else
static SkPathRef* CreateFromBuffer(int verbCount, int pointCount, SkRBuffer* buffer) {
SkPathRef* ref = SkNEW(SkPathRef);
ref->resetToSize(verbCount, pointCount);
SkASSERT(verbCount == ref->countVerbs());
SkASSERT(pointCount == ref->countPoints());
buffer->read(ref->fPoints, pointCount * sizeof(SkPoint));
for (int i = 0; i < verbCount; ++i) {
ref->fVerbs[~i] = buffer->readU8();
}
return ref;
}
#endif
/**
* Rollsback a path ref to zero verbs and points with the assumption that the path ref will be
* repopulated with approximately the same number of verbs and points. A new path ref is created
* only if necessary.
*/
static void Rewind(PR_CONTAINER* pathRef) {
if (1 == (*pathRef)->getRefCnt()) {
(*pathRef)->validate();
(*pathRef)->fVerbCnt = 0;
(*pathRef)->fPointCnt = 0;
(*pathRef)->fFreeSpace = (*pathRef)->currSize();
(*pathRef)->fGenerationID = 0;
(*pathRef)->validate();
} else {
int oldVCnt = (*pathRef)->countVerbs();
int oldPCnt = (*pathRef)->countPoints();
pathRef->reset(SkNEW(SkPathRef));
(*pathRef)->resetToSize(0, 0, oldVCnt, oldPCnt);
}
}
virtual ~SkPathRef() {
SkASSERT_X(this != gEmptyPathRef);
#if SK_DEBUG_PATH_REF
SkASSERT_X(!fOwners.count());
#endif
this->validate();
sk_free(fPoints);
SkDEBUGCODE_X(fPoints = NULL;)
SkDEBUGCODE_X(fVerbs = NULL;)
SkDEBUGCODE_X(fVerbCnt = 0x9999999;)
SkDEBUGCODE_X(fPointCnt = 0xAAAAAAA;)
SkDEBUGCODE_X(fPointCnt = 0xBBBBBBB;)
SkDEBUGCODE_X(fGenerationID = 0xEEEEEEEE;)
SkDEBUGCODE_X(fEditorsAttached = 0x7777777;)
}
int countPoints() const { this->validate(); return fPointCnt; }
int countVerbs() const { this->validate(); return fVerbCnt; }
/**
* Returns a pointer one beyond the first logical verb (last verb in memory order).
*/
const uint8_t* verbs() const { this->validate(); return fVerbs; }
/**
* Returns a const pointer to the first verb in memory (which is the last logical verb).
*/
const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; }
/**
* Returns a const pointer to the first point.
*/
const SkPoint* points() const { this->validate(); return fPoints; }
/**
* Shortcut for this->points() + this->countPoints()
*/
const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); }
/**
* Convenience methods for getting to a verb or point by index.
*/
uint8_t atVerb(int index) {
SkASSERT((unsigned) index < (unsigned) fVerbCnt);
return this->verbs()[~index];
}
const SkPoint& atPoint(int index) const {
SkASSERT((unsigned) index < (unsigned) fPointCnt);
return this->points()[index];
}
bool operator== (const SkPathRef& ref) const {
this->validate();
ref.validate();
bool genIDMatch = fGenerationID && fGenerationID == ref.fGenerationID;
#ifdef SK_RELEASE
if (genIDMatch) {
return true;
}
#endif
if (fPointCnt != ref.fPointCnt ||
fVerbCnt != ref.fVerbCnt) {
SkASSERT(!genIDMatch);
return false;
}
if (0 != memcmp(this->verbsMemBegin(),
ref.verbsMemBegin(),
ref.fVerbCnt * sizeof(uint8_t))) {
SkASSERT(!genIDMatch);
return false;
}
if (0 != memcmp(this->points(),
ref.points(),
ref.fPointCnt * sizeof(SkPoint))) {
SkASSERT(!genIDMatch);
return false;
}
// We've done the work to determine that these are equal. If either has a zero genID, copy
// the other's. If both are 0 then genID() will compute the next ID.
if (0 == fGenerationID) {
fGenerationID = ref.genID();
} else if (0 == ref.fGenerationID) {
ref.fGenerationID = this->genID();
}
return true;
}
/**
* Writes the path points and verbs to a buffer.
*/
#if NEW_PICTURE_FORMAT
void writeToBuffer(SkWBuffer* buffer) {
this->validate();
SkDEBUGCODE_X(size_t beforePos = buffer->pos();)
// TODO: write gen ID here. Problem: We don't know if we're cross process or not from
// SkWBuffer. Until this is fixed we write 0.
buffer->write32(0);
buffer->write32(this->fVerbCnt);
buffer->write32(this->fPointCnt);
buffer->write(this->verbsMemBegin(), fVerbCnt * sizeof(uint8_t));
buffer->write(fPoints, fPointCnt * sizeof(SkPoint));
SkASSERT(buffer->pos() - beforePos == (size_t) this->writeSize());
}
/**
* Gets the number of bytes that would be written in writeBuffer()
*/
uint32_t writeSize() {
return 3 * sizeof(uint32_t) + fVerbCnt * sizeof(uint8_t) + fPointCnt * sizeof(SkPoint);
}
#else
void writeToBuffer(SkWBuffer* buffer) {
this->validate();
buffer->write(fPoints, fPointCnt * sizeof(SkPoint));
for (int i = 0; i < fVerbCnt; ++i) {
buffer->write8(fVerbs[~i]);
}
}
#endif
private:
SkPathRef() {
fPointCnt = 0;
fVerbCnt = 0;
fVerbs = NULL;
fPoints = NULL;
fFreeSpace = 0;
fGenerationID = kEmptyGenID;
SkDEBUGCODE_X(fEditorsAttached = 0;)
this->validate();
}
void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints) {
this->validate();
this->resetToSize(ref.fVerbCnt, ref.fPointCnt,
additionalReserveVerbs, additionalReservePoints);
memcpy(this->verbsMemWritable(), ref.verbsMemBegin(), ref.fVerbCnt * sizeof(uint8_t));
memcpy(this->fPoints, ref.fPoints, ref.fPointCnt * sizeof(SkPoint));
// We could call genID() here to force a real ID (instead of 0). However, if we're making
// a copy then presumably we intend to make a modification immediately afterwards.
fGenerationID = ref.fGenerationID;
this->validate();
}
/** Makes additional room but does not change the counts or change the genID */
void incReserve(int additionalVerbs, int additionalPoints) {
this->validate();
size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint);
this->makeSpace(space);
this->validate();
}
/** Resets the path ref with verbCount verbs and pointCount points, all unitialized. Also
* allocates space for reserveVerb additional verbs and reservePoints additional points.*/
void resetToSize(int verbCount, int pointCount, int reserveVerbs = 0, int reservePoints = 0) {
this->validate();
fGenerationID = 0;
size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount;
size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints;
size_t minSize = newSize + newReserve;
ptrdiff_t sizeDelta = this->currSize() - minSize;
if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) {
sk_free(fPoints);
fPoints = NULL;
fVerbs = NULL;
fFreeSpace = 0;
fVerbCnt = 0;
fPointCnt = 0;
this->makeSpace(minSize);
fVerbCnt = verbCount;
fPointCnt = pointCount;
fFreeSpace -= newSize;
} else {
fPointCnt = pointCount;
fVerbCnt = verbCount;
fFreeSpace = this->currSize() - minSize;
}
this->validate();
}
/**
* Increases the verb count by newVerbs and the point count be newPoints. New verbs and points
* are uninitialized.
*/
void grow(int newVerbs, int newPoints) {
this->validate();
size_t space = newVerbs * sizeof(uint8_t) + newPoints * sizeof (SkPoint);
this->makeSpace(space);
fVerbCnt += newVerbs;
fPointCnt += newPoints;
fFreeSpace -= space;
this->validate();
}
/**
* Increases the verb count 1, records the new verb, and creates room for the requisite number
* of additional points. A pointer to the first point is returned. Any new points are
* uninitialized.
*/
SkPoint* growForVerb(SkPath::Verb verb) {
this->validate();
int pCnt;
switch (verb) {
case SkPath::kMove_Verb:
pCnt = 1;
break;
case SkPath::kLine_Verb:
pCnt = 1;
break;
case SkPath::kQuad_Verb:
pCnt = 2;
break;
case SkPath::kCubic_Verb:
pCnt = 3;
break;
default:
pCnt = 0;
}
size_t space = sizeof(uint8_t) + pCnt * sizeof (SkPoint);
this->makeSpace(space);
this->fVerbs[~fVerbCnt] = verb;
SkPoint* ret = fPoints + fPointCnt;
fVerbCnt += 1;
fPointCnt += pCnt;
fFreeSpace -= space;
this->validate();
return ret;
}
/**
* Ensures that the free space available in the path ref is >= size. The verb and point counts
* are not changed.
*/
void makeSpace(size_t size) {
this->validate();
ptrdiff_t growSize = size - fFreeSpace;
if (growSize <= 0) {
return;
}
size_t oldSize = this->currSize();
// round to next multiple of 8 bytes
growSize = (growSize + 7) & ~static_cast<size_t>(7);
// we always at least double the allocation
if (static_cast<size_t>(growSize) < oldSize) {
growSize = oldSize;
}
if (growSize < kMinSize) {
growSize = kMinSize;
}
size_t newSize = oldSize + growSize;
// Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO:
// encapsulate this.
fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize));
size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);
void* newVerbsDst = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize);
void* oldVerbsSrc = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize);
memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);
fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize);
fFreeSpace += growSize;
this->validate();
}
/**
* Private, non-const-ptr version of the public function verbsMemBegin().
*/
uint8_t* verbsMemWritable() {
this->validate();
return fVerbs - fVerbCnt;
}
/**
* Gets the total amount of space allocated for verbs, points, and reserve.
*/
size_t currSize() const {
return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints);
}
/**
* Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the
* same ID then they have the same verbs and points. However, two path refs may have the same
* contents but different genIDs. Zero is reserved and means an ID has not yet been determined
* for the path ref.
*/
int32_t genID() const {
SkASSERT_X(!fEditorsAttached);
if (!fGenerationID) {
if (0 == fPointCnt && 0 == fVerbCnt) {
fGenerationID = kEmptyGenID;
} else {
static int32_t gPathRefGenerationID;
// do a loop in case our global wraps around, as we never want to return a 0 or the
// empty ID
do {
fGenerationID = sk_atomic_inc(&gPathRefGenerationID) + 1;
} while (fGenerationID <= kEmptyGenID);
}
}
return fGenerationID;
}
void validate() const {
SkASSERT(static_cast<ptrdiff_t>(fFreeSpace) >= 0);
SkASSERT(reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints) >= 0);
SkASSERT((NULL == fPoints) == (NULL == fVerbs));
SkASSERT(!(NULL == fPoints && 0 != fFreeSpace));
SkASSERT(!(NULL == fPoints && 0 != fFreeSpace));
SkASSERT(!(NULL == fPoints && fPointCnt));
SkASSERT(!(NULL == fVerbs && fVerbCnt));
SkASSERT(this->currSize() ==
fFreeSpace + sizeof(SkPoint) * fPointCnt + sizeof(uint8_t) * fVerbCnt);
}
enum {
kMinSize = 256,
};
SkPoint* fPoints; // points to begining of the allocation
uint8_t* fVerbs; // points just past the end of the allocation (verbs grow backwards)
int fVerbCnt;
int fPointCnt;
size_t fFreeSpace; // redundant but saves computation
enum {
kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs.
};
mutable int32_t fGenerationID;
SkDEBUGCODE_X(int32_t fEditorsAttached;) // assert that only one editor in use at any time.
#if SK_DEBUG_PATH_REF
SkTDArray<SkPath*> fOwners;
#endif
typedef SkRefCnt INHERITED;
};
SK_DEFINE_INST_COUNT(SkPathRef);
#endif

Просмотреть файл

@ -1,718 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPictureFlat_DEFINED
#define SkPictureFlat_DEFINED
//#define SK_DEBUG_SIZE
#include "SkChunkAlloc.h"
#include "SkBitmap.h"
#include "SkBitmapHeap.h"
#include "SkOrderedReadBuffer.h"
#include "SkOrderedWriteBuffer.h"
#include "SkPicture.h"
#include "SkPtrRecorder.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkTRefArray.h"
#include "SkTSearch.h"
enum DrawType {
UNUSED,
CLIP_PATH,
CLIP_REGION,
CLIP_RECT,
CLIP_RRECT,
CONCAT,
DRAW_BITMAP,
DRAW_BITMAP_MATRIX,
DRAW_BITMAP_NINE,
DRAW_BITMAP_RECT_TO_RECT,
DRAW_CLEAR,
DRAW_DATA,
DRAW_OVAL,
DRAW_PAINT,
DRAW_PATH,
DRAW_PICTURE,
DRAW_POINTS,
DRAW_POS_TEXT,
DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
DRAW_POS_TEXT_H,
DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
DRAW_RECT,
DRAW_RRECT,
DRAW_SPRITE,
DRAW_TEXT,
DRAW_TEXT_ON_PATH,
DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT
DRAW_VERTICES,
RESTORE,
ROTATE,
SAVE,
SAVE_LAYER,
SCALE,
SET_MATRIX,
SKEW,
TRANSLATE,
NOOP,
LAST_DRAWTYPE_ENUM = NOOP
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
static const int kDRAW_BITMAP_FLAVOR = LAST_DRAWTYPE_ENUM+1;
enum DrawVertexFlags {
DRAW_VERTICES_HAS_TEXS = 0x01,
DRAW_VERTICES_HAS_COLORS = 0x02,
DRAW_VERTICES_HAS_INDICES = 0x04
};
///////////////////////////////////////////////////////////////////////////////
// clipparams are packed in 5 bits
// doAA:1 | regionOp:4
static inline uint32_t ClipParams_pack(SkRegion::Op op, bool doAA) {
unsigned doAABit = doAA ? 1 : 0;
return (doAABit << 4) | op;
}
static inline SkRegion::Op ClipParams_unpackRegionOp(uint32_t packed) {
return (SkRegion::Op)(packed & 0xF);
}
static inline bool ClipParams_unpackDoAA(uint32_t packed) {
return SkToBool((packed >> 4) & 1);
}
///////////////////////////////////////////////////////////////////////////////
class SkTypefacePlayback {
public:
SkTypefacePlayback();
virtual ~SkTypefacePlayback();
int count() const { return fCount; }
void reset(const SkRefCntSet*);
void setCount(int count);
SkRefCnt* set(int index, SkRefCnt*);
void setupBuffer(SkOrderedReadBuffer& buffer) const {
buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
}
protected:
int fCount;
SkRefCnt** fArray;
};
class SkFactoryPlayback {
public:
SkFactoryPlayback(int count) : fCount(count) {
fArray = SkNEW_ARRAY(SkFlattenable::Factory, count);
}
~SkFactoryPlayback() {
SkDELETE_ARRAY(fArray);
}
SkFlattenable::Factory* base() const { return fArray; }
void setupBuffer(SkOrderedReadBuffer& buffer) const {
buffer.setFactoryPlayback(fArray, fCount);
}
private:
int fCount;
SkFlattenable::Factory* fArray;
};
///////////////////////////////////////////////////////////////////////////////
//
//
// The following templated classes provide an efficient way to store and compare
// objects that have been flattened (i.e. serialized in an ordered binary
// format).
//
// SkFlatData: is a simple indexable container for the flattened data
// which is agnostic to the type of data is is indexing. It is
// also responsible for flattening/unflattening objects but
// details of that operation are hidden in the provided procs
// SkFlatDictionary: is an abstract templated dictionary that maintains a
// searchable set of SkFlataData objects of type T.
// SkFlatController: is an interface provided to SkFlatDictionary which handles
// allocation and unallocation in some cases. It also holds
// ref count recorders and the like.
//
// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary
// must subclass the dictionary and provide the necessary flattening procs.
// The end of this header contains dictionary subclasses for some common classes
// like SkBitmap, SkMatrix, SkPaint, and SkRegion. SkFlatController must also
// be implemented, or SkChunkFlatController can be used to use an
// SkChunkAllocator and never do replacements.
//
//
///////////////////////////////////////////////////////////////////////////////
class SkFlatData;
class SkFlatController : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkFlatController)
SkFlatController();
virtual ~SkFlatController();
/**
* Provide a new block of memory for the SkFlatDictionary to use.
*/
virtual void* allocThrow(size_t bytes) = 0;
/**
* Unallocate a previously allocated block, returned by allocThrow.
* Implementation should at least perform an unallocation if passed the last
* pointer returned by allocThrow. If findAndReplace() is intended to be
* used, unalloc should also be able to unallocate the SkFlatData that is
* provided.
*/
virtual void unalloc(void* ptr) = 0;
/**
* Used during creation and unflattening of SkFlatData objects. If the
* objects being flattened contain bitmaps they are stored in this heap
* and the flattenable stores the index to the bitmap on the heap.
* This should be set by the protected setBitmapHeap.
*/
SkBitmapHeap* getBitmapHeap() { return fBitmapHeap; }
/**
* Used during creation of SkFlatData objects. If a typeface recorder is
* required to flatten the objects being flattened (i.e. for SkPaints), this
* should be set by the protected setTypefaceSet.
*/
SkRefCntSet* getTypefaceSet() { return fTypefaceSet; }
/**
* Used during unflattening of the SkFlatData objects in the
* SkFlatDictionary. Needs to be set by the protected setTypefacePlayback
* and needs to be reset to the SkRefCntSet passed to setTypefaceSet.
*/
SkTypefacePlayback* getTypefacePlayback() { return fTypefacePlayback; }
/**
* Optional factory recorder used during creation of SkFlatData objects. Set
* using the protected method setNamedFactorySet.
*/
SkNamedFactorySet* getNamedFactorySet() { return fFactorySet; }
/**
* Flags to use during creation of SkFlatData objects. Defaults to zero.
*/
uint32_t getWriteBufferFlags() { return fWriteBufferFlags; }
protected:
/**
* Set an SkBitmapHeap to be used to store/read SkBitmaps. Ref counted.
*/
void setBitmapHeap(SkBitmapHeap*);
/**
* Set an SkRefCntSet to be used to store SkTypefaces during flattening. Ref
* counted.
*/
void setTypefaceSet(SkRefCntSet*);
/**
* Set an SkTypefacePlayback to be used to find references to SkTypefaces
* during unflattening. Should be reset to the set provided to
* setTypefaceSet.
*/
void setTypefacePlayback(SkTypefacePlayback*);
/**
* Set an SkNamedFactorySet to be used to store Factorys and their
* corresponding names during flattening. Ref counted. Returns the same
* set as a convenience.
*/
SkNamedFactorySet* setNamedFactorySet(SkNamedFactorySet*);
/**
* Set the flags to be used during flattening.
*/
void setWriteBufferFlags(uint32_t flags) { fWriteBufferFlags = flags; }
private:
SkBitmapHeap* fBitmapHeap;
SkRefCntSet* fTypefaceSet;
SkTypefacePlayback* fTypefacePlayback;
SkNamedFactorySet* fFactorySet;
uint32_t fWriteBufferFlags;
typedef SkRefCnt INHERITED;
};
class SkFlatData {
public:
/**
* Compare two SkFlatData ptrs, returning -1, 0, 1 to allow them to be
* sorted.
*
* Note: this assumes that a and b have different sentinel values, either
* InCache or AsCandidate, otherwise the loop will go beyond the end of
* the buffers.
*
* dataToCompare() returns 2 fields before the flattened data:
* - checksum
* - size
* This ensures that if we see two blocks of different length, we will
* notice that right away, and not read any further. It also ensures that
* we see the checksum right away, so that most of the time it is enough
* to short-circuit our comparison.
*/
static int Compare(const SkFlatData* a, const SkFlatData* b) {
const uint32_t* stop = a->dataStop();
const uint32_t* a_ptr = a->dataToCompare() - 1;
const uint32_t* b_ptr = b->dataToCompare() - 1;
// We use -1 above, so we can pre-increment our pointers in the loop
while (*++a_ptr == *++b_ptr) {}
if (a_ptr == stop) { // sentinel
SkASSERT(b->dataStop() == b_ptr);
return 0;
}
SkASSERT(a_ptr < a->dataStop());
SkASSERT(b_ptr < b->dataStop());
return (*a_ptr < *b_ptr) ? -1 : 1;
}
int index() const { return fIndex; }
const void* data() const { return (const char*)this + sizeof(*this); }
void* data() { return (char*)this + sizeof(*this); }
// Our data is always 32bit aligned, so we can offer this accessor
uint32_t* data32() { return (uint32_t*)this->data(); }
// Returns the size of the flattened data.
size_t flatSize() const { return fFlatSize; }
void setSentinelInCache() {
this->setSentinel(kInCache_Sentinel);
}
void setSentinelAsCandidate() {
this->setSentinel(kCandidate_Sentinel);
}
uint32_t checksum() const { return fChecksum; }
#ifdef SK_DEBUG_SIZE
// returns the logical size of our data. Does not return any sentinel or
// padding we might have.
size_t size() const {
return sizeof(SkFlatData) + fFlatSize;
}
#endif
static SkFlatData* Create(SkFlatController* controller, const void* obj, int index,
void (*flattenProc)(SkOrderedWriteBuffer&, const void*));
void unflatten(void* result,
void (*unflattenProc)(SkOrderedReadBuffer&, void*),
SkBitmapHeap* bitmapHeap = NULL,
SkTypefacePlayback* facePlayback = NULL) const;
// When we purge an entry, we want to reuse an old index for the new entry,
// so we expose this setter.
void setIndex(int index) { fIndex = index; }
// for unittesting
friend bool operator==(const SkFlatData& a, const SkFlatData& b) {
size_t N = (const char*)a.dataStop() - (const char*)a.dataToCompare();
return !memcmp(a.dataToCompare(), b.dataToCompare(), N);
}
// returns true if fTopBot[] has been recorded
bool isTopBotWritten() const {
return !SkScalarIsNaN(fTopBot[0]);
}
// Returns fTopBot array, so it can be passed to a routine to compute them.
// For efficiency, we assert that fTopBot have not been recorded yet.
SkScalar* writableTopBot() const {
SkASSERT(!this->isTopBotWritten());
return fTopBot;
}
// return the topbot[] after it has been recorded
const SkScalar* topBot() const {
SkASSERT(this->isTopBotWritten());
return fTopBot;
}
private:
// This is *not* part of the key for search/sort
int fIndex;
// Cache of paint's FontMetrics fTop,fBottom
// initialied to [NaN,NaN] as a sentinel that they have not been recorded yet
//
// This is *not* part of the key for search/sort
mutable SkScalar fTopBot[2];
// marks fTopBot[] as unrecorded
void setTopBotUnwritten() {
this->fTopBot[0] = SK_ScalarNaN; // initial to sentinel values
}
// From here down is the data we look at in the search/sort. We always begin
// with the checksum and then length.
uint32_t fChecksum;
int32_t fFlatSize; // size of flattened data
// uint32_t flattenedData[]
// uint32_t sentinelValue
const uint32_t* dataToCompare() const {
return (const uint32_t*)&fChecksum;
}
const uint32_t* dataStop() const {
SkASSERT(SkIsAlign4(fFlatSize));
return (const uint32_t*)((const char*)this->data() + fFlatSize);
}
enum {
kInCache_Sentinel = 0,
kCandidate_Sentinel = ~0U,
};
void setSentinel(uint32_t value) {
SkASSERT(SkIsAlign4(fFlatSize));
this->data32()[fFlatSize >> 2] = value;
}
};
template <class T>
class SkFlatDictionary {
public:
SkFlatDictionary(SkFlatController* controller)
: fController(controller) {
fFlattenProc = NULL;
fUnflattenProc = NULL;
SkASSERT(controller);
fController->ref();
// set to 1 since returning a zero from find() indicates failure
fNextIndex = 1;
sk_bzero(fHash, sizeof(fHash));
// index 0 is always empty since it is used as a signal that find failed
fIndexedData.push(NULL);
}
virtual ~SkFlatDictionary() {
fController->unref();
}
int count() const {
SkASSERT(fIndexedData.count() == fSortedData.count()+1);
return fSortedData.count();
}
const SkFlatData* operator[](int index) const {
SkASSERT(index >= 0 && index < fSortedData.count());
return fSortedData[index];
}
/**
* Clears the dictionary of all entries. However, it does NOT free the
* memory that was allocated for each entry.
*/
void reset() {
fSortedData.reset();
fIndexedData.rewind();
// index 0 is always empty since it is used as a signal that find failed
fIndexedData.push(NULL);
fNextIndex = 1;
sk_bzero(fHash, sizeof(fHash));
}
/**
* Similar to find. Allows the caller to specify an SkFlatData to replace in
* the case of an add. Also tells the caller whether a new SkFlatData was
* added and whether the old one was replaced. The parameters added and
* replaced are required to be non-NULL. Rather than returning the index of
* the entry in the dictionary, it returns the actual SkFlatData.
*/
const SkFlatData* findAndReplace(const T& element,
const SkFlatData* toReplace, bool* added,
bool* replaced) {
SkASSERT(added != NULL && replaced != NULL);
int oldCount = fSortedData.count();
const SkFlatData* flat = this->findAndReturnFlat(element);
*added = fSortedData.count() == oldCount + 1;
*replaced = false;
if (*added && toReplace != NULL) {
// First, find the index of the one to replace
int indexToReplace = fSortedData.find(toReplace);
if (indexToReplace >= 0) {
// findAndReturnFlat set the index to fNextIndex and increased
// fNextIndex by one. Reuse the index from the one being
// replaced and reset fNextIndex to the proper value.
int oldIndex = flat->index();
const_cast<SkFlatData*>(flat)->setIndex(toReplace->index());
fIndexedData[toReplace->index()] = flat;
fNextIndex--;
// Remove from the arrays.
fSortedData.remove(indexToReplace);
fIndexedData.remove(oldIndex);
// Remove from the hash table.
int oldHash = ChecksumToHashIndex(toReplace->checksum());
if (fHash[oldHash] == toReplace) {
fHash[oldHash] = NULL;
}
// Delete the actual object.
fController->unalloc((void*)toReplace);
*replaced = true;
SkASSERT(fIndexedData.count() == fSortedData.count()+1);
}
}
return flat;
}
/**
* Given an element of type T return its 1-based index in the dictionary. If
* the element wasn't previously in the dictionary it is automatically
* added.
*
* To make the Compare function fast, we write a sentinel value at the end
* of each block. The blocks in our fSortedData[] all have a 0 sentinel. The
* newly created block we're comparing against has a -1 in the sentinel.
*
* This trick allows Compare to always loop until failure. If it fails on
* the sentinal value, we know the blocks are equal.
*/
int find(const T& element) {
return this->findAndReturnFlat(element)->index();
}
/**
* Unflatten the objects and return them in SkTRefArray, or return NULL
* if there no objects (instead of an empty array).
*/
SkTRefArray<T>* unflattenToArray() const {
int count = fSortedData.count();
SkTRefArray<T>* array = NULL;
if (count > 0) {
array = SkTRefArray<T>::Create(count);
this->unflattenIntoArray(&array->writableAt(0));
}
return array;
}
/**
* Unflatten the specific object at the given index
*/
T* unflatten(int index) const {
SkASSERT(fIndexedData.count() == fSortedData.count()+1);
const SkFlatData* element = fIndexedData[index];
SkASSERT(index == element->index());
T* dst = new T;
this->unflatten(dst, element);
return dst;
}
const SkFlatData* findAndReturnFlat(const T& element) {
SkFlatData* flat = SkFlatData::Create(fController, &element, fNextIndex, fFlattenProc);
int hashIndex = ChecksumToHashIndex(flat->checksum());
const SkFlatData* candidate = fHash[hashIndex];
if (candidate && !SkFlatData::Compare(flat, candidate)) {
fController->unalloc(flat);
return candidate;
}
int index = SkTSearch<SkFlatData>((const SkFlatData**) fSortedData.begin(),
fSortedData.count(), flat, sizeof(flat),
&SkFlatData::Compare);
if (index >= 0) {
fController->unalloc(flat);
fHash[hashIndex] = fSortedData[index];
return fSortedData[index];
}
index = ~index;
*fSortedData.insert(index) = flat;
*fIndexedData.insert(flat->index()) = flat;
SkASSERT(fSortedData.count() == fNextIndex);
fNextIndex++;
flat->setSentinelInCache();
fHash[hashIndex] = flat;
SkASSERT(fIndexedData.count() == fSortedData.count()+1);
return flat;
}
protected:
void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*);
void (*fUnflattenProc)(SkOrderedReadBuffer&, void*);
private:
void unflatten(T* dst, const SkFlatData* element) const {
element->unflatten(dst, fUnflattenProc,
fController->getBitmapHeap(),
fController->getTypefacePlayback());
}
void unflattenIntoArray(T* array) const {
const int count = fSortedData.count();
SkASSERT(fIndexedData.count() == fSortedData.count()+1);
const SkFlatData* const* iter = fSortedData.begin();
for (int i = 0; i < count; ++i) {
const SkFlatData* element = iter[i];
int index = element->index() - 1;
SkASSERT((unsigned)index < (unsigned)count);
unflatten(&array[index], element);
}
}
SkFlatController * const fController;
int fNextIndex;
// SkFlatDictionary has two copies of the data one indexed by the
// SkFlatData's index and the other sorted. The sorted data is used
// for finding and uniquification while the indexed copy is used
// for standard array-style lookups based on the SkFlatData's index
// (as in 'unflatten').
SkTDArray<const SkFlatData*> fIndexedData;
// fSortedData is sorted by checksum/size/data.
SkTDArray<const SkFlatData*> fSortedData;
enum {
// Determined by trying diff values on picture-recording benchmarks
// (e.g. PictureRecordBench.cpp), choosing the smallest value that
// showed a big improvement. Even better would be to benchmark diff
// values on recording representative web-pages or other "real" content.
HASH_BITS = 7,
HASH_MASK = (1 << HASH_BITS) - 1,
HASH_COUNT = 1 << HASH_BITS
};
const SkFlatData* fHash[HASH_COUNT];
static int ChecksumToHashIndex(uint32_t checksum) {
int n = checksum;
if (HASH_BITS < 32) {
n ^= n >> 16;
}
if (HASH_BITS < 16) {
n ^= n >> 8;
}
if (HASH_BITS < 8) {
n ^= n >> 4;
}
return n & HASH_MASK;
}
};
///////////////////////////////////////////////////////////////////////////////
// Some common dictionaries are defined here for both reference and convenience
///////////////////////////////////////////////////////////////////////////////
template <class T>
static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) {
((T*)obj)->flatten(buffer);
}
template <class T>
static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) {
((T*)obj)->unflatten(buffer);
}
class SkChunkFlatController : public SkFlatController {
public:
SkChunkFlatController(size_t minSize)
: fHeap(minSize)
, fTypefaceSet(SkNEW(SkRefCntSet)) {
this->setTypefaceSet(fTypefaceSet);
this->setTypefacePlayback(&fTypefacePlayback);
}
~SkChunkFlatController() {
fTypefaceSet->unref();
}
virtual void* allocThrow(size_t bytes) SK_OVERRIDE {
return fHeap.allocThrow(bytes);
}
virtual void unalloc(void* ptr) SK_OVERRIDE {
(void) fHeap.unalloc(ptr);
}
void setupPlaybacks() const {
fTypefacePlayback.reset(fTypefaceSet);
}
void setBitmapStorage(SkBitmapHeap* heap) {
this->setBitmapHeap(heap);
}
private:
SkChunkAlloc fHeap;
SkRefCntSet* fTypefaceSet;
mutable SkTypefacePlayback fTypefacePlayback;
};
class SkBitmapDictionary : public SkFlatDictionary<SkBitmap> {
public:
SkBitmapDictionary(SkFlatController* controller)
: SkFlatDictionary<SkBitmap>(controller) {
fFlattenProc = &SkFlattenObjectProc<SkBitmap>;
fUnflattenProc = &SkUnflattenObjectProc<SkBitmap>;
}
};
class SkMatrixDictionary : public SkFlatDictionary<SkMatrix> {
public:
SkMatrixDictionary(SkFlatController* controller)
: SkFlatDictionary<SkMatrix>(controller) {
fFlattenProc = &flattenMatrix;
fUnflattenProc = &unflattenMatrix;
}
static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) {
buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj);
}
static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) {
buffer.getReader32()->readMatrix((SkMatrix*)obj);
}
};
class SkPaintDictionary : public SkFlatDictionary<SkPaint> {
public:
SkPaintDictionary(SkFlatController* controller)
: SkFlatDictionary<SkPaint>(controller) {
fFlattenProc = &SkFlattenObjectProc<SkPaint>;
fUnflattenProc = &SkUnflattenObjectProc<SkPaint>;
}
};
class SkRegionDictionary : public SkFlatDictionary<SkRegion> {
public:
SkRegionDictionary(SkFlatController* controller)
: SkFlatDictionary<SkRegion>(controller) {
fFlattenProc = &flattenRegion;
fUnflattenProc = &unflattenRegion;
}
static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) {
buffer.getWriter32()->writeRegion(*(SkRegion*)obj);
}
static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) {
buffer.getReader32()->readRegion((SkRegion*)obj);
}
};
#endif

Просмотреть файл

@ -1,187 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkPixelRef.h"
#include "SkFlattenableBuffers.h"
#include "SkThread.h"
SK_DEFINE_INST_COUNT(SkPixelRef)
// must be a power-of-2. undef to just use 1 mutex
#define PIXELREF_MUTEX_RING_COUNT 32
#ifdef PIXELREF_MUTEX_RING_COUNT
static int32_t gPixelRefMutexRingIndex;
static SK_DECLARE_MUTEX_ARRAY(gPixelRefMutexRing, PIXELREF_MUTEX_RING_COUNT);
#else
SK_DECLARE_STATIC_MUTEX(gPixelRefMutex);
#endif
static SkBaseMutex* get_default_mutex() {
#ifdef PIXELREF_MUTEX_RING_COUNT
// atomic_inc might be overkill here. It may be fine if once in a while
// we hit a race-condition and two subsequent calls get the same index...
int index = sk_atomic_inc(&gPixelRefMutexRingIndex);
return &gPixelRefMutexRing[index & (PIXELREF_MUTEX_RING_COUNT - 1)];
#else
return &gPixelRefMutex;
#endif
}
///////////////////////////////////////////////////////////////////////////////
int32_t SkNextPixelRefGenerationID();
int32_t SkNextPixelRefGenerationID() {
static int32_t gPixelRefGenerationID;
// do a loop in case our global wraps around, as we never want to
// return a 0
int32_t genID;
do {
genID = sk_atomic_inc(&gPixelRefGenerationID) + 1;
} while (0 == genID);
return genID;
}
///////////////////////////////////////////////////////////////////////////////
void SkPixelRef::setMutex(SkBaseMutex* mutex) {
if (NULL == mutex) {
mutex = get_default_mutex();
}
fMutex = mutex;
}
// just need a > 0 value, so pick a funny one to aid in debugging
#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789
SkPixelRef::SkPixelRef(SkBaseMutex* mutex) : fPreLocked(false) {
this->setMutex(mutex);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this
fLockCount = 0;
fGenerationID = 0; // signal to rebuild
fIsImmutable = false;
fPreLocked = false;
}
SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
: INHERITED(buffer) {
this->setMutex(mutex);
fPixels = NULL;
fColorTable = NULL; // we do not track ownership of this
fLockCount = 0;
fIsImmutable = buffer.readBool();
fGenerationID = buffer.readUInt();
fPreLocked = false;
}
void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
// only call me in your constructor, otherwise fLockCount tracking can get
// out of sync.
fPixels = pixels;
fColorTable = ctable;
fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
fPreLocked = true;
#endif
}
void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeBool(fIsImmutable);
// We write the gen ID into the picture for within-process recording. This
// is safe since the same genID will never refer to two different sets of
// pixels (barring overflow). However, each process has its own "namespace"
// of genIDs. So for cross-process recording we write a zero which will
// trigger assignment of a new genID in playback.
if (buffer.isCrossProcess()) {
buffer.writeUInt(0);
} else {
buffer.writeUInt(fGenerationID);
}
}
void SkPixelRef::lockPixels() {
SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
if (!fPreLocked) {
SkAutoMutexAcquire ac(*fMutex);
if (1 == ++fLockCount) {
fPixels = this->onLockPixels(&fColorTable);
}
}
}
void SkPixelRef::unlockPixels() {
SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
if (!fPreLocked) {
SkAutoMutexAcquire ac(*fMutex);
SkASSERT(fLockCount > 0);
if (0 == --fLockCount) {
this->onUnlockPixels();
fPixels = NULL;
fColorTable = NULL;
}
}
}
bool SkPixelRef::lockPixelsAreWritable() const {
return this->onLockPixelsAreWritable();
}
bool SkPixelRef::onLockPixelsAreWritable() const {
return true;
}
uint32_t SkPixelRef::getGenerationID() const {
if (0 == fGenerationID) {
fGenerationID = SkNextPixelRefGenerationID();
}
return fGenerationID;
}
void SkPixelRef::notifyPixelsChanged() {
#ifdef SK_DEBUG
if (fIsImmutable) {
SkDebugf("========== notifyPixelsChanged called on immutable pixelref");
}
#endif
// this signals us to recompute this next time around
fGenerationID = 0;
}
void SkPixelRef::setImmutable() {
fIsImmutable = true;
}
bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) {
return this->onReadPixels(dst, subset);
}
bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
return false;
}
SkData* SkPixelRef::onRefEncodedData() {
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_BUILD_FOR_ANDROID
void SkPixelRef::globalRef(void* data) {
this->ref();
}
void SkPixelRef::globalUnref() {
this->unref();
}
#endif

Просмотреть файл

@ -1,473 +0,0 @@
/*
* Copyright 2008 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkPoint.h"
void SkIPoint::rotateCW(SkIPoint* dst) const {
SkASSERT(dst);
// use a tmp in case this == dst
int32_t tmp = fX;
dst->fX = -fY;
dst->fY = tmp;
}
void SkIPoint::rotateCCW(SkIPoint* dst) const {
SkASSERT(dst);
// use a tmp in case this == dst
int32_t tmp = fX;
dst->fX = fY;
dst->fY = -tmp;
}
///////////////////////////////////////////////////////////////////////////////
void SkPoint::setIRectFan(int l, int t, int r, int b, size_t stride) {
SkASSERT(stride >= sizeof(SkPoint));
((SkPoint*)((intptr_t)this + 0 * stride))->set(SkIntToScalar(l),
SkIntToScalar(t));
((SkPoint*)((intptr_t)this + 1 * stride))->set(SkIntToScalar(l),
SkIntToScalar(b));
((SkPoint*)((intptr_t)this + 2 * stride))->set(SkIntToScalar(r),
SkIntToScalar(b));
((SkPoint*)((intptr_t)this + 3 * stride))->set(SkIntToScalar(r),
SkIntToScalar(t));
}
void SkPoint::setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b,
size_t stride) {
SkASSERT(stride >= sizeof(SkPoint));
((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t);
((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b);
((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b);
((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t);
}
void SkPoint::rotateCW(SkPoint* dst) const {
SkASSERT(dst);
// use a tmp in case this == dst
SkScalar tmp = fX;
dst->fX = -fY;
dst->fY = tmp;
}
void SkPoint::rotateCCW(SkPoint* dst) const {
SkASSERT(dst);
// use a tmp in case this == dst
SkScalar tmp = fX;
dst->fX = fY;
dst->fY = -tmp;
}
void SkPoint::scale(SkScalar scale, SkPoint* dst) const {
SkASSERT(dst);
dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale));
}
bool SkPoint::normalize() {
return this->setLength(fX, fY, SK_Scalar1);
}
bool SkPoint::setNormalize(SkScalar x, SkScalar y) {
return this->setLength(x, y, SK_Scalar1);
}
bool SkPoint::setLength(SkScalar length) {
return this->setLength(fX, fY, length);
}
#ifdef SK_SCALAR_IS_FLOAT
// Returns the square of the Euclidian distance to (dx,dy).
static inline float getLengthSquared(float dx, float dy) {
return dx * dx + dy * dy;
}
// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
// *lengthSquared. Returns true if the distance is judged to be "nearly zero".
//
// This logic is encapsulated in a helper method to make it explicit that we
// always perform this check in the same manner, to avoid inconsistencies
// (see http://code.google.com/p/skia/issues/detail?id=560 ).
static inline bool isLengthNearlyZero(float dx, float dy,
float *lengthSquared) {
*lengthSquared = getLengthSquared(dx, dy);
return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
}
SkScalar SkPoint::Normalize(SkPoint* pt) {
float mag2;
if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) {
float mag = sk_float_sqrt(mag2);
float scale = 1.0f / mag;
pt->fX = pt->fX * scale;
pt->fY = pt->fY * scale;
return mag;
}
return 0;
}
SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
return sk_float_sqrt(getLengthSquared(dx, dy));
}
bool SkPoint::setLength(float x, float y, float length) {
float mag2;
if (!isLengthNearlyZero(x, y, &mag2)) {
float scale = length / sk_float_sqrt(mag2);
fX = x * scale;
fY = y * scale;
return true;
}
return false;
}
#else
#include "Sk64.h"
// Returns the square of the Euclidian distance to (dx,dy) in *result.
static inline void getLengthSquared(SkScalar dx, SkScalar dy, Sk64 *result) {
Sk64 dySqr;
result->setMul(dx, dx);
dySqr.setMul(dy, dy);
result->add(dySqr);
}
// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
// *lengthSquared. Returns true if the distance is judged to be "nearly zero".
//
// This logic is encapsulated in a helper method to make it explicit that we
// always perform this check in the same manner, to avoid inconsistencies
// (see http://code.google.com/p/skia/issues/detail?id=560 ).
static inline bool isLengthNearlyZero(SkScalar dx, SkScalar dy,
Sk64 *lengthSquared) {
Sk64 tolSqr;
getLengthSquared(dx, dy, lengthSquared);
// we want nearlyzero^2, but to compute it fast we want to just do a
// 32bit multiply, so we require that it not exceed 31bits. That is true
// if nearlyzero is <= 0xB504, which should be trivial, since usually
// nearlyzero is a very small fixed-point value.
SkASSERT(SK_ScalarNearlyZero <= 0xB504);
tolSqr.set(0, SK_ScalarNearlyZero * SK_ScalarNearlyZero);
return *lengthSquared <= tolSqr;
}
SkScalar SkPoint::Normalize(SkPoint* pt) {
Sk64 mag2;
if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) {
SkScalar mag = mag2.getSqrt();
SkScalar scale = SkScalarInvert(mag);
pt->fX = SkScalarMul(pt->fX, scale);
pt->fY = SkScalarMul(pt->fY, scale);
return mag;
}
return 0;
}
bool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) {
Sk64 mag2_unused;
return !isLengthNearlyZero(dx, dy, &mag2_unused);
}
SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
Sk64 tmp;
getLengthSquared(dx, dy, &tmp);
return tmp.getSqrt();
}
#ifdef SK_DEBUGx
static SkFixed fixlen(SkFixed x, SkFixed y) {
float fx = (float)x;
float fy = (float)y;
return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f);
}
#endif
static inline uint32_t squarefixed(unsigned x) {
x >>= 16;
return x*x;
}
#if 1 // Newton iter for setLength
static inline unsigned invsqrt_iter(unsigned V, unsigned U) {
unsigned x = V * U >> 14;
x = x * U >> 14;
x = (3 << 14) - x;
x = (U >> 1) * x >> 14;
return x;
}
static const uint16_t gInvSqrt14GuessTable[] = {
0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061,
0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780,
0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235,
0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99,
0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee,
0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc,
0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830,
0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce
};
#define BUILD_INVSQRT_TABLEx
#ifdef BUILD_INVSQRT_TABLE
static void build_invsqrt14_guess_table() {
for (int i = 8; i <= 63; i++) {
unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25));
printf("0x%x, ", x);
}
printf("\n");
}
#endif
static unsigned fast_invsqrt(uint32_t x) {
#ifdef BUILD_INVSQRT_TABLE
unsigned top2 = x >> 25;
SkASSERT(top2 >= 8 && top2 <= 63);
static bool gOnce;
if (!gOnce) {
build_invsqrt14_guess_table();
gOnce = true;
}
#endif
unsigned V = x >> 14; // make V .14
unsigned top = x >> 25;
SkASSERT(top >= 8 && top <= 63);
SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable));
unsigned U = gInvSqrt14GuessTable[top - 8];
U = invsqrt_iter(V, U);
return invsqrt_iter(V, U);
}
/* We "normalize" x,y to be .14 values (so we can square them and stay 32bits.
Then we Newton-iterate this in .14 space to compute the invser-sqrt, and
scale by it at the end. The .14 space means we can execute our iterations
and stay in 32bits as well, making the multiplies much cheaper than calling
SkFixedMul.
*/
bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
if (ox == 0) {
if (oy == 0) {
return false;
}
this->set(0, SkApplySign(length, SkExtractSign(oy)));
return true;
}
if (oy == 0) {
this->set(SkApplySign(length, SkExtractSign(ox)), 0);
return true;
}
unsigned x = SkAbs32(ox);
unsigned y = SkAbs32(oy);
int zeros = SkCLZ(x | y);
// make x,y 1.14 values so our fast sqr won't overflow
if (zeros > 17) {
x <<= zeros - 17;
y <<= zeros - 17;
} else {
x >>= 17 - zeros;
y >>= 17 - zeros;
}
SkASSERT((x | y) <= 0x7FFF);
unsigned invrt = fast_invsqrt(x*x + y*y);
x = x * invrt >> 12;
y = y * invrt >> 12;
if (length != SK_Fixed1) {
x = SkFixedMul(x, length);
y = SkFixedMul(y, length);
}
this->set(SkApplySign(x, SkExtractSign(ox)),
SkApplySign(y, SkExtractSign(oy)));
return true;
}
#else
/*
Normalize x,y, and then scale them by length.
The obvious way to do this would be the following:
S64 tmp1, tmp2;
tmp1.setMul(x,x);
tmp2.setMul(y,y);
tmp1.add(tmp2);
len = tmp1.getSqrt();
x' = SkFixedDiv(x, len);
y' = SkFixedDiv(y, len);
This is fine, but slower than what we do below.
The present technique does not compute the starting length, but
rather fiddles with x,y iteratively, all the while checking its
magnitude^2 (avoiding a sqrt).
We normalize by first shifting x,y so that at least one of them
has bit 31 set (after taking the abs of them).
Then we loop, refining x,y by squaring them and comparing
against a very large 1.0 (1 << 28), and then adding or subtracting
a delta (which itself is reduced by half each time through the loop).
For speed we want the squaring to be with a simple integer mul. To keep
that from overflowing we shift our coordinates down until we are dealing
with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits)
When our square is close to 1.0, we shift x,y down into fixed range.
*/
bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
if (ox == 0) {
if (oy == 0)
return false;
this->set(0, SkApplySign(length, SkExtractSign(oy)));
return true;
}
if (oy == 0) {
this->set(SkApplySign(length, SkExtractSign(ox)), 0);
return true;
}
SkFixed x = SkAbs32(ox);
SkFixed y = SkAbs32(oy);
// shift x,y so that the greater of them is 15bits (1.14 fixed point)
{
int shift = SkCLZ(x | y);
// make them .30
x <<= shift - 1;
y <<= shift - 1;
}
SkFixed dx = x;
SkFixed dy = y;
for (int i = 0; i < 17; i++) {
dx >>= 1;
dy >>= 1;
U32 len2 = squarefixed(x) + squarefixed(y);
if (len2 >> 28) {
x -= dx;
y -= dy;
} else {
x += dx;
y += dy;
}
}
x >>= 14;
y >>= 14;
#ifdef SK_DEBUGx // measure how far we are from unit-length
{
static int gMaxError;
static int gMaxDiff;
SkFixed len = fixlen(x, y);
int err = len - SK_Fixed1;
err = SkAbs32(err);
if (err > gMaxError) {
gMaxError = err;
SkDebugf("gMaxError %d\n", err);
}
float fx = SkAbs32(ox)/65536.0f;
float fy = SkAbs32(oy)/65536.0f;
float mag = sqrtf(fx*fx + fy*fy);
fx /= mag;
fy /= mag;
SkFixed xx = (int)floorf(fx * 65536 + 0.5f);
SkFixed yy = (int)floorf(fy * 65536 + 0.5f);
err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y));
if (err > gMaxDiff) {
gMaxDiff = err;
SkDebugf("gMaxDiff %d\n", err);
}
}
#endif
x = SkApplySign(x, SkExtractSign(ox));
y = SkApplySign(y, SkExtractSign(oy));
if (length != SK_Fixed1) {
x = SkFixedMul(x, length);
y = SkFixedMul(y, length);
}
this->set(x, y);
return true;
}
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
SkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
const SkPoint& b,
Side* side) const {
SkVector u = b - a;
SkVector v = *this - a;
SkScalar uLengthSqd = u.lengthSqd();
SkScalar det = u.cross(v);
if (NULL != side) {
SkASSERT(-1 == SkPoint::kLeft_Side &&
0 == SkPoint::kOn_Side &&
1 == kRight_Side);
*side = (Side) SkScalarSignAsInt(det);
}
return SkScalarMulDiv(det, det, uLengthSqd);
}
SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
const SkPoint& b) const {
// See comments to distanceToLineBetweenSqd. If the projection of c onto
// u is between a and b then this returns the same result as that
// function. Otherwise, it returns the distance to the closer of a and
// b. Let the projection of v onto u be v'. There are three cases:
// 1. v' points opposite to u. c is not between a and b and is closer
// to a than b.
// 2. v' points along u and has magnitude less than y. c is between
// a and b and the distance to the segment is the same as distance
// to the line ab.
// 3. v' points along u and has greater magnitude than u. c is not
// not between a and b and is closer to b than a.
// v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
// in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
// we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
// avoid a sqrt to compute |u|.
SkVector u = b - a;
SkVector v = *this - a;
SkScalar uLengthSqd = u.lengthSqd();
SkScalar uDotV = SkPoint::DotProduct(u, v);
if (uDotV <= 0) {
return v.lengthSqd();
} else if (uDotV > uLengthSqd) {
return b.distanceToSqd(*this);
} else {
SkScalar det = u.cross(v);
return SkScalarMulDiv(det, det, uLengthSqd);
}
}

Просмотреть файл

@ -1,200 +0,0 @@
/*
* Copyright 2011 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkAdvancedTypefaceMetrics.h"
#include "SkFontDescriptor.h"
#include "SkFontHost.h"
#include "SkFontStream.h"
#include "SkStream.h"
#include "SkTypeface.h"
SK_DEFINE_INST_COUNT(SkTypeface)
//#define TRACE_LIFECYCLE
#ifdef TRACE_LIFECYCLE
static int32_t gTypefaceCounter;
#endif
SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedPitch)
: fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) {
#ifdef TRACE_LIFECYCLE
SkDebugf("SkTypeface: create %p fontID %d total %d\n",
this, fontID, ++gTypefaceCounter);
#endif
}
SkTypeface::~SkTypeface() {
#ifdef TRACE_LIFECYCLE
SkDebugf("SkTypeface: destroy %p fontID %d total %d\n",
this, fUniqueID, --gTypefaceCounter);
#endif
}
///////////////////////////////////////////////////////////////////////////////
SkTypeface* SkTypeface::GetDefaultTypeface() {
// we keep a reference to this guy for all time, since if we return its
// fontID, the font cache may later on ask to resolve that back into a
// typeface object.
static SkTypeface* gDefaultTypeface;
if (NULL == gDefaultTypeface) {
gDefaultTypeface =
SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal);
}
return gDefaultTypeface;
}
SkTypeface* SkTypeface::RefDefault() {
return SkRef(GetDefaultTypeface());
}
uint32_t SkTypeface::UniqueID(const SkTypeface* face) {
if (NULL == face) {
face = GetDefaultTypeface();
}
return face->uniqueID();
}
bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) {
return SkTypeface::UniqueID(facea) == SkTypeface::UniqueID(faceb);
}
///////////////////////////////////////////////////////////////////////////////
SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) {
return SkFontHost::CreateTypeface(NULL, name, style);
}
SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) {
if (family && family->style() == s) {
family->ref();
return const_cast<SkTypeface*>(family);
}
return SkFontHost::CreateTypeface(family, NULL, s);
}
SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) {
return SkFontHost::CreateTypefaceFromStream(stream);
}
SkTypeface* SkTypeface::CreateFromFile(const char path[]) {
return SkFontHost::CreateTypefaceFromFile(path);
}
///////////////////////////////////////////////////////////////////////////////
void SkTypeface::serialize(SkWStream* wstream) const {
bool isLocal = false;
SkFontDescriptor desc(this->style());
this->onGetFontDescriptor(&desc, &isLocal);
desc.serialize(wstream);
if (isLocal) {
int ttcIndex; // TODO: write this to the stream?
SkAutoTUnref<SkStream> rstream(this->openStream(&ttcIndex));
if (rstream.get()) {
size_t length = rstream->getLength();
wstream->writePackedUInt(length);
wstream->writeStream(rstream, length);
} else {
wstream->writePackedUInt(0);
}
} else {
wstream->writePackedUInt(0);
}
}
SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
SkFontDescriptor desc(stream);
size_t length = stream->readPackedUInt();
if (length > 0) {
void* addr = sk_malloc_flags(length, 0);
if (addr) {
SkAutoTUnref<SkStream> localStream(SkNEW_ARGS(SkMemoryStream,
(addr, length, false)));
return SkTypeface::CreateFromStream(localStream.get());
}
// failed to allocate, so just skip and create-from-name
stream->skip(length);
}
return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle());
}
///////////////////////////////////////////////////////////////////////////////
int SkTypeface::countTables() const {
return this->onGetTableTags(NULL);
}
int SkTypeface::getTableTags(SkFontTableTag tags[]) const {
return this->onGetTableTags(tags);
}
size_t SkTypeface::getTableSize(SkFontTableTag tag) const {
return this->onGetTableData(tag, 0, ~0U, NULL);
}
size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length,
void* data) const {
return this->onGetTableData(tag, offset, length, data);
}
SkStream* SkTypeface::openStream(int* ttcIndex) const {
int ttcIndexStorage;
if (NULL == ttcIndex) {
// So our subclasses don't need to check for null param
ttcIndex = &ttcIndexStorage;
}
return this->onOpenStream(ttcIndex);
}
int SkTypeface::getUnitsPerEm() const {
// should we try to cache this in the base-class?
return this->onGetUPEM();
}
SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
SkAdvancedTypefaceMetrics::PerGlyphInfo info,
const uint32_t* glyphIDs,
uint32_t glyphIDsCount) const {
return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int SkTypeface::onGetUPEM() const {
int upem = 0;
SkAdvancedTypefaceMetrics* metrics;
metrics = this->getAdvancedTypefaceMetrics(
SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo,
NULL, 0);
if (metrics) {
upem = metrics->fEmSize;
metrics->unref();
}
return upem;
}
int SkTypeface::onGetTableTags(SkFontTableTag tags[]) const {
int ttcIndex;
SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
}
size_t SkTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
size_t length, void* data) const {
int ttcIndex;
SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
return stream.get()
? SkFontStream::GetTableData(stream, ttcIndex, tag, offset, length, data)
: 0;
}

Просмотреть файл

@ -1,296 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkWriter32.h"
SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) {
fMinSize = minSize;
fSize = 0;
fWrittenBeforeLastBlock = 0;
fHead = fTail = NULL;
if (storageSize) {
this->reset(storage, storageSize);
}
}
SkWriter32::~SkWriter32() {
this->reset();
}
void SkWriter32::reset() {
Block* block = fHead;
if (this->isHeadExternallyAllocated()) {
SkASSERT(block);
// don't 'free' the first block, since it is owned by the caller
block = block->fNext;
}
while (block) {
Block* next = block->fNext;
sk_free(block);
block = next;
}
fSize = 0;
fWrittenBeforeLastBlock = 0;
fHead = fTail = NULL;
}
void SkWriter32::reset(void* storage, size_t storageSize) {
this->reset();
storageSize &= ~3; // trunc down to multiple of 4
if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) {
fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize);
}
}
SkWriter32::Block* SkWriter32::doReserve(size_t size) {
SkASSERT(SkAlign4(size) == size);
Block* block = fTail;
SkASSERT(NULL == block || block->available() < size);
if (NULL == block) {
SkASSERT(NULL == fHead);
fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
SkASSERT(0 == fWrittenBeforeLastBlock);
} else {
SkASSERT(fSize > 0);
fWrittenBeforeLastBlock = fSize;
fTail = Block::Create(SkMax32(size, fMinSize));
block->fNext = fTail;
block = fTail;
}
return block;
}
uint32_t* SkWriter32::peek32(size_t offset) {
SkDEBUGCODE(this->validate();)
SkASSERT(SkAlign4(offset) == offset);
SkASSERT(offset <= fSize);
// try the fast case, where offset is within fTail
if (offset >= fWrittenBeforeLastBlock) {
return fTail->peek32(offset - fWrittenBeforeLastBlock);
}
Block* block = fHead;
SkASSERT(NULL != block);
while (offset >= block->fAllocatedSoFar) {
offset -= block->fAllocatedSoFar;
block = block->fNext;
SkASSERT(NULL != block);
}
return block->peek32(offset);
}
void SkWriter32::rewindToOffset(size_t offset) {
if (offset >= fSize) {
return;
}
if (0 == offset) {
this->reset();
return;
}
SkDEBUGCODE(this->validate();)
SkASSERT(SkAlign4(offset) == offset);
SkASSERT(offset <= fSize);
fSize = offset;
// Try the fast case, where offset is within fTail
if (offset >= fWrittenBeforeLastBlock) {
fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock;
} else {
// Similar to peek32, except that we free up any following blocks.
// We have to re-compute fWrittenBeforeLastBlock as well.
size_t globalOffset = offset;
Block* block = fHead;
SkASSERT(NULL != block);
while (offset >= block->fAllocatedSoFar) {
offset -= block->fAllocatedSoFar;
block = block->fNext;
SkASSERT(NULL != block);
}
// this has to be recomputed, since we may free up fTail
fWrittenBeforeLastBlock = globalOffset - offset;
// update the size on the "last" block
block->fAllocatedSoFar = offset;
// end our list
fTail = block;
Block* next = block->fNext;
block->fNext = NULL;
// free up any trailing blocks
block = next;
while (block) {
Block* next = block->fNext;
sk_free(block);
block = next;
}
}
SkDEBUGCODE(this->validate();)
}
void SkWriter32::flatten(void* dst) const {
const Block* block = fHead;
SkDEBUGCODE(size_t total = 0;)
while (block) {
size_t allocated = block->fAllocatedSoFar;
memcpy(dst, block->base(), allocated);
dst = (char*)dst + allocated;
block = block->fNext;
SkDEBUGCODE(total += allocated;)
SkASSERT(total <= fSize);
}
SkASSERT(total == fSize);
}
uint32_t* SkWriter32::reservePad(size_t size) {
if (size > 0) {
size_t alignedSize = SkAlign4(size);
char* dst = (char*)this->reserve(alignedSize);
// Pad the last four bytes with zeroes in one step.
uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4));
*padding = 0;
return (uint32_t*) dst;
}
return this->reserve(0);
}
void SkWriter32::writePad(const void* src, size_t size) {
if (size > 0) {
char* dst = (char*)this->reservePad(size);
// Copy the actual data.
memcpy(dst, src, size);
}
}
#include "SkStream.h"
size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
char scratch[1024];
const size_t MAX = sizeof(scratch);
size_t remaining = length;
while (remaining != 0) {
size_t n = remaining;
if (n > MAX) {
n = MAX;
}
size_t bytes = stream->read(scratch, n);
this->writePad(scratch, bytes);
remaining -= bytes;
if (bytes != n) {
break;
}
}
return length - remaining;
}
bool SkWriter32::writeToStream(SkWStream* stream) {
const Block* block = fHead;
while (block) {
if (!stream->write(block->base(), block->fAllocatedSoFar)) {
return false;
}
block = block->fNext;
}
return true;
}
#ifdef SK_DEBUG
void SkWriter32::validate() const {
SkASSERT(SkIsAlign4(fSize));
size_t accum = 0;
const Block* block = fHead;
while (block) {
SkASSERT(SkIsAlign4(block->fSizeOfBlock));
SkASSERT(SkIsAlign4(block->fAllocatedSoFar));
SkASSERT(block->fAllocatedSoFar <= block->fSizeOfBlock);
if (NULL == block->fNext) {
SkASSERT(fTail == block);
SkASSERT(fWrittenBeforeLastBlock == accum);
}
accum += block->fAllocatedSoFar;
SkASSERT(accum <= fSize);
block = block->fNext;
}
SkASSERT(accum == fSize);
}
#endif
///////////////////////////////////////////////////////////////////////////////
#include "SkReader32.h"
#include "SkString.h"
/*
* Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
*/
const char* SkReader32::readString(size_t* outLen) {
size_t len = this->readInt();
const void* ptr = this->peek();
// skip over teh string + '\0' and then pad to a multiple of 4
size_t alignedSize = SkAlign4(len + 1);
this->skip(alignedSize);
if (outLen) {
*outLen = len;
}
return (const char*)ptr;
}
size_t SkReader32::readIntoString(SkString* copy) {
size_t len;
const char* ptr = this->readString(&len);
if (copy) {
copy->set(ptr, len);
}
return len;
}
void SkWriter32::writeString(const char str[], size_t len) {
if ((long)len < 0) {
SkASSERT(str);
len = strlen(str);
}
this->write32(len);
// add 1 since we also write a terminating 0
size_t alignedLen = SkAlign4(len + 1);
char* ptr = (char*)this->reserve(alignedLen);
{
// Write the terminating 0 and fill in the rest with zeroes
uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4));
*padding = 0;
}
// Copy the string itself.
memcpy(ptr, str, len);
}
size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
if ((long)len < 0) {
SkASSERT(str);
len = strlen(str);
}
const size_t lenBytes = 4; // we use 4 bytes to record the length
// add 1 since we also write a terminating 0
return SkAlign4(lenBytes + len + 1);
}

Просмотреть файл

@ -1,193 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkArithmeticMode.h"
#include "SkColorPriv.h"
#include "SkString.h"
#include "SkUnPreMultiply.h"
class SkArithmeticMode_scalar : public SkXfermode {
public:
SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) {
fK[0] = k1;
fK[1] = k2;
fK[2] = k3;
fK[3] = k4;
}
virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
const SkAlpha aa[]) const SK_OVERRIDE;
SK_DEVELOPER_TO_STRING()
SK_DECLARE_UNFLATTENABLE_OBJECT()
private:
SkScalar fK[4];
typedef SkXfermode INHERITED;
};
static int pinToByte(int value) {
if (value < 0) {
value = 0;
} else if (value > 255) {
value = 255;
}
return value;
}
static int arith(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
int src, int dst) {
SkScalar result = SkScalarMul(k1, src * dst) +
SkScalarMul(k2, src) +
SkScalarMul(k3, dst) +
k4;
int res = SkScalarRoundToInt(result);
return pinToByte(res);
}
static int blend(int src, int dst, int scale) {
return dst + ((src - dst) * scale >> 8);
}
static bool needsUnpremul(int alpha) {
return 0 != alpha && 0xFF != alpha;
}
void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
int count, const SkAlpha aaCoverage[]) const {
SkScalar k1 = fK[0] / 255;
SkScalar k2 = fK[1];
SkScalar k3 = fK[2];
SkScalar k4 = fK[3] * 255;
for (int i = 0; i < count; ++i) {
if ((NULL == aaCoverage) || aaCoverage[i]) {
SkPMColor sc = src[i];
SkPMColor dc = dst[i];
int sa = SkGetPackedA32(sc);
int da = SkGetPackedA32(dc);
int srcNeedsUnpremul = needsUnpremul(sa);
int dstNeedsUnpremul = needsUnpremul(sa);
int a, r, g, b;
if (!srcNeedsUnpremul && !dstNeedsUnpremul) {
a = arith(k1, k2, k3, k4, sa, sa);
r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
} else {
int sr = SkGetPackedR32(sc);
int sg = SkGetPackedG32(sc);
int sb = SkGetPackedB32(sc);
if (srcNeedsUnpremul) {
SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(sa);
sr = SkUnPreMultiply::ApplyScale(scale, sr);
sg = SkUnPreMultiply::ApplyScale(scale, sg);
sb = SkUnPreMultiply::ApplyScale(scale, sb);
}
int dr = SkGetPackedR32(dc);
int dg = SkGetPackedG32(dc);
int db = SkGetPackedB32(dc);
if (dstNeedsUnpremul) {
SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(da);
dr = SkUnPreMultiply::ApplyScale(scale, dr);
dg = SkUnPreMultiply::ApplyScale(scale, dg);
db = SkUnPreMultiply::ApplyScale(scale, db);
}
a = arith(k1, k2, k3, k4, sa, sa);
r = arith(k1, k2, k3, k4, sr, dr);
g = arith(k1, k2, k3, k4, sg, dg);
b = arith(k1, k2, k3, k4, sb, db);
}
// apply antialias coverage if necessary
if (aaCoverage && 0xFF != aaCoverage[i]) {
int scale = aaCoverage[i] + (aaCoverage[i] >> 7);
a = blend(a, SkGetPackedA32(sc), scale);
r = blend(r, SkGetPackedR32(sc), scale);
g = blend(g, SkGetPackedG32(sc), scale);
b = blend(b, SkGetPackedB32(sc), scale);
}
// turn the result back into premul
if (0xFF != a) {
int scale = a + (a >> 7);
r = SkAlphaMul(r, scale);
g = SkAlphaMul(g, scale);
b = SkAlphaMul(b, scale);
}
dst[i] = SkPackARGB32(a, r, g, b);
}
}
}
#ifdef SK_DEVELOPER
void SkArithmeticMode_scalar::toString(SkString* str) const {
str->append("SkArithmeticMode_scalar: ");
for (int i = 0; i < 4; ++i) {
str->appendScalar(fK[i]);
if (i < 3) {
str->append(" ");
}
}
}
#endif
///////////////////////////////////////////////////////////////////////////////
static bool fitsInBits(SkScalar x, int bits) {
#ifdef SK_SCALAR_IS_FIXED
x = SkAbs32(x);
x += 1 << 7;
x >>= 8;
return x < (1 << (bits - 1));
#else
return SkScalarAbs(x) < (1 << (bits - 1));
#endif
}
#if 0 // UNUSED
static int32_t toDot8(SkScalar x) {
#ifdef SK_SCALAR_IS_FIXED
x += 1 << 7;
x >>= 8;
return x;
#else
return (int32_t)(x * 256);
#endif
}
#endif
SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
SkScalar k3, SkScalar k4) {
if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
#if 0 // UNUSED
int32_t i1 = toDot8(k1);
int32_t i2 = toDot8(k2);
int32_t i3 = toDot8(k3);
int32_t i4 = toDot8(k4);
if (i1) {
return SkNEW_ARGS(SkArithmeticMode_quad, (i1, i2, i3, i4));
}
if (0 == i2) {
return SkNEW_ARGS(SkArithmeticMode_dst, (i3, i4));
}
if (0 == i3) {
return SkNEW_ARGS(SkArithmeticMode_src, (i2, i4));
}
return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
#endif
}
return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4));
}

Просмотреть файл

@ -1,372 +0,0 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBicubicImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkMatrix.h"
#include "SkRect.h"
#include "SkUnPreMultiply.h"
#if SK_SUPPORT_GPU
#include "gl/GrGLEffectMatrix.h"
#include "effects/GrSingleTextureEffect.h"
#include "GrTBackendEffectFactory.h"
#include "GrContext.h"
#include "GrTexture.h"
#include "SkImageFilterUtils.h"
#endif
SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar coefficients[16], SkImageFilter* input)
: INHERITED(input),
fScale(scale) {
memcpy(fCoefficients, coefficients, sizeof(fCoefficients));
}
#define DS(x) SkDoubleToScalar(x)
SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale,
SkImageFilter* input) {
static const SkScalar coefficients[16] = {
DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0),
};
return SkNEW_ARGS(SkBicubicImageFilter, (scale, coefficients, input));
}
SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients);
SkASSERT(readSize == 16);
fScale.fWidth = buffer.readScalar();
fScale.fHeight = buffer.readScalar();
}
void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalarArray(fCoefficients, 16);
buffer.writeScalar(fScale.fWidth);
buffer.writeScalar(fScale.fHeight);
}
SkBicubicImageFilter::~SkBicubicImageFilter() {
}
inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPMColor c1, SkPMColor c2, SkPMColor c3) {
SkScalar t2 = t * t, t3 = t2 * t;
SkScalar cc[4];
// FIXME: For the fractx case, this should be refactored out of this function.
cc[0] = c[0] + SkScalarMul(c[1], t) + SkScalarMul(c[2], t2) + SkScalarMul(c[3], t3);
cc[1] = c[4] + SkScalarMul(c[5], t) + SkScalarMul(c[6], t2) + SkScalarMul(c[7], t3);
cc[2] = c[8] + SkScalarMul(c[9], t) + SkScalarMul(c[10], t2) + SkScalarMul(c[11], t3);
cc[3] = c[12] + SkScalarMul(c[13], t) + SkScalarMul(c[14], t2) + SkScalarMul(c[15], t3);
SkScalar a = SkScalarClampMax(SkScalarMul(cc[0], SkGetPackedA32(c0)) + SkScalarMul(cc[1], SkGetPackedA32(c1)) + SkScalarMul(cc[2], SkGetPackedA32(c2)) + SkScalarMul(cc[3], SkGetPackedA32(c3)), 255);
SkScalar r = SkScalarMul(cc[0], SkGetPackedR32(c0)) + SkScalarMul(cc[1], SkGetPackedR32(c1)) + SkScalarMul(cc[2], SkGetPackedR32(c2)) + SkScalarMul(cc[3], SkGetPackedR32(c3));
SkScalar g = SkScalarMul(cc[0], SkGetPackedG32(c0)) + SkScalarMul(cc[1], SkGetPackedG32(c1)) + SkScalarMul(cc[2], SkGetPackedG32(c2)) + SkScalarMul(cc[3], SkGetPackedG32(c3));
SkScalar b = SkScalarMul(cc[0], SkGetPackedB32(c0)) + SkScalarMul(cc[1], SkGetPackedB32(c1)) + SkScalarMul(cc[2], SkGetPackedB32(c2)) + SkScalarMul(cc[3], SkGetPackedB32(c3));
return SkPackARGB32(SkScalarRoundToInt(a),
SkScalarRoundToInt(SkScalarClampMax(r, a)),
SkScalarRoundToInt(SkScalarClampMax(g, a)),
SkScalarRoundToInt(SkScalarClampMax(b, a)));
}
bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* loc) {
SkBitmap src = this->getInputResult(0, proxy, source, matrix, loc);
if (src.config() != SkBitmap::kARGB_8888_Config) {
return false;
}
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
SkRect dstRect = SkRect::MakeWH(SkScalarMul(SkIntToScalar(src.width()), fScale.fWidth),
SkScalarMul(SkIntToScalar(src.height()), fScale.fHeight));
SkIRect dstIRect;
dstRect.roundOut(&dstIRect);
result->setConfig(src.config(), dstIRect.width(), dstIRect.height());
result->allocPixels();
if (!result->getPixels()) {
return false;
}
SkRect srcRect;
src.getBounds(&srcRect);
SkMatrix inverse;
inverse.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
inverse.postTranslate(SkFloatToScalar(-0.5f), SkFloatToScalar(-0.5f));
for (int y = dstIRect.fTop; y < dstIRect.fBottom; ++y) {
SkPMColor* dptr = result->getAddr32(dstIRect.fLeft, y);
for (int x = dstIRect.fLeft; x < dstIRect.fRight; ++x) {
SkPoint srcPt, dstPt = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
inverse.mapPoints(&srcPt, &dstPt, 1);
SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX);
SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY);
int sx = SkScalarFloorToInt(srcPt.fX);
int sy = SkScalarFloorToInt(srcPt.fY);
int x0 = SkClampMax(sx - 1, src.width() - 1);
int x1 = SkClampMax(sx , src.width() - 1);
int x2 = SkClampMax(sx + 1, src.width() - 1);
int x3 = SkClampMax(sx + 2, src.width() - 1);
int y0 = SkClampMax(sy - 1, src.height() - 1);
int y1 = SkClampMax(sy , src.height() - 1);
int y2 = SkClampMax(sy + 1, src.height() - 1);
int y3 = SkClampMax(sy + 2, src.height() - 1);
SkPMColor s00 = *src.getAddr32(x0, y0);
SkPMColor s10 = *src.getAddr32(x1, y0);
SkPMColor s20 = *src.getAddr32(x2, y0);
SkPMColor s30 = *src.getAddr32(x3, y0);
SkPMColor s0 = cubicBlend(fCoefficients, fractx, s00, s10, s20, s30);
SkPMColor s01 = *src.getAddr32(x0, y1);
SkPMColor s11 = *src.getAddr32(x1, y1);
SkPMColor s21 = *src.getAddr32(x2, y1);
SkPMColor s31 = *src.getAddr32(x3, y1);
SkPMColor s1 = cubicBlend(fCoefficients, fractx, s01, s11, s21, s31);
SkPMColor s02 = *src.getAddr32(x0, y2);
SkPMColor s12 = *src.getAddr32(x1, y2);
SkPMColor s22 = *src.getAddr32(x2, y2);
SkPMColor s32 = *src.getAddr32(x3, y2);
SkPMColor s2 = cubicBlend(fCoefficients, fractx, s02, s12, s22, s32);
SkPMColor s03 = *src.getAddr32(x0, y3);
SkPMColor s13 = *src.getAddr32(x1, y3);
SkPMColor s23 = *src.getAddr32(x2, y3);
SkPMColor s33 = *src.getAddr32(x3, y3);
SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33);
*dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3);
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
class GrGLBicubicEffect;
class GrBicubicEffect : public GrSingleTextureEffect {
public:
virtual ~GrBicubicEffect();
static const char* Name() { return "Bicubic"; }
const float* coefficients() const { return fCoefficients; }
typedef GrGLBicubicEffect GLEffect;
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16]) {
AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients)));
return CreateEffectRef(effect);
}
private:
GrBicubicEffect(GrTexture*, const SkScalar coefficients[16]);
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
float fCoefficients[16];
GR_DECLARE_EFFECT_TEST;
typedef GrSingleTextureEffect INHERITED;
};
class GrGLBicubicEffect : public GrGLEffect {
public:
GrGLBicubicEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect&);
virtual void emitCode(GrGLShaderBuilder*,
const GrDrawEffect&,
EffectKey,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray&) SK_OVERRIDE;
static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
private:
typedef GrGLUniformManager::UniformHandle UniformHandle;
UniformHandle fCoefficientsUni;
UniformHandle fImageIncrementUni;
GrGLEffectMatrix fEffectMatrix;
typedef GrGLEffect INHERITED;
};
GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
: INHERITED(factory)
, fCoefficientsUni(GrGLUniformManager::kInvalidUniformHandle)
, fImageIncrementUni(GrGLUniformManager::kInvalidUniformHandle)
, fEffectMatrix(drawEffect.castEffect<GrBicubicEffect>().coordsType()) {
}
void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect&,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) {
const char* coords;
fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kMat44f_GrSLType, "Coefficients");
fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec2f_GrSLType, "ImageIncrement");
const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
const char* coeff = builder->getUniformCStr(fCoefficientsUni);
SkString cubicBlendName;
static const GrGLShaderVar gCubicBlendArgs[] = {
GrGLShaderVar("coefficients", kMat44f_GrSLType),
GrGLShaderVar("t", kFloat_GrSLType),
GrGLShaderVar("c0", kVec4f_GrSLType),
GrGLShaderVar("c1", kVec4f_GrSLType),
GrGLShaderVar("c2", kVec4f_GrSLType),
GrGLShaderVar("c3", kVec4f_GrSLType),
};
builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType,
"cubicBlend",
SK_ARRAY_COUNT(gCubicBlendArgs),
gCubicBlendArgs,
"\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n"
"\tvec4 c = coefficients * ts;\n"
"\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n",
&cubicBlendName);
builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5, 0.5);\n", coords, imgInc);
builder->fsCodeAppendf("\tvec2 f = fract(coord / %s);\n", imgInc);
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
SkString coord;
coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
builder->fsCodeAppendf("\tvec4 s%d%d = ", x, y);
builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
samplers[0],
coord.c_str());
builder->fsCodeAppend(";\n");
}
builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, s0%d, s1%d, s2%d, s3%d);\n", y, cubicBlendName.c_str(), coeff, y, y, y, y);
}
builder->fsCodeAppendf("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor, cubicBlendName.c_str(), coeff);
}
GrGLEffect::EffectKey GrGLBicubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const GrBicubicEffect& bicubic = drawEffect.castEffect<GrBicubicEffect>();
EffectKey matrixKey = GrGLEffectMatrix::GenKey(bicubic.getMatrix(),
drawEffect,
bicubic.coordsType(),
bicubic.texture(0));
return matrixKey;
}
void GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
const GrDrawEffect& drawEffect) {
const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>();
GrTexture& texture = *effect.texture(0);
float imageIncrement[2];
imageIncrement[0] = 1.0f / texture.width();
imageIncrement[1] = 1.0f / texture.height();
uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
uman.setMatrix4f(fCoefficientsUni, effect.coefficients());
fEffectMatrix.setData(uman,
effect.getMatrix(),
drawEffect,
effect.texture(0));
}
GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
const SkScalar coefficients[16])
: INHERITED(texture, MakeDivByTextureWHMatrix(texture)) {
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
// Convert from row-major scalars to column-major floats.
fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
}
}
}
GrBicubicEffect::~GrBicubicEffect() {
}
const GrBackendEffectFactory& GrBicubicEffect::getFactory() const {
return GrTBackendEffectFactory<GrBicubicEffect>::getInstance();
}
bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase);
return this->texture(0) == s.texture(0) &&
!memcmp(fCoefficients, s.coefficients(), 16);
}
void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
// FIXME: Perhaps we can do better.
*validFlags = 0;
return;
}
GR_DEFINE_EFFECT_TEST(GrBicubicEffect);
GrEffectRef* GrBicubicEffect::TestCreate(SkMWCRandom* random,
GrContext* context,
const GrDrawTargetCaps&,
GrTexture* textures[]) {
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
GrEffectUnitTest::kAlphaTextureIdx;
SkScalar coefficients[16];
for (int i = 0; i < 16; i++) {
coefficients[i] = random->nextSScalar1();
}
return GrBicubicEffect::Create(textures[texIdx], coefficients);
}
bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
SkBitmap srcBM;
if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &srcBM)) {
return false;
}
GrTexture* srcTexture = (GrTexture*) srcBM.getTexture();
GrContext* context = srcTexture->getContext();
SkRect dstRect = SkRect::MakeWH(srcBM.width() * fScale.fWidth,
srcBM.height() * fScale.fHeight);
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fWidth = SkScalarCeilToInt(dstRect.width());
desc.fHeight = SkScalarCeilToInt(dstRect.height());
desc.fConfig = kSkia8888_GrPixelConfig;
GrAutoScratchTexture ast(context, desc);
SkAutoTUnref<GrTexture> dst(ast.detach());
if (!dst) {
return false;
}
GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
GrPaint paint;
paint.colorStage(0)->setEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->unref();
SkRect srcRect;
srcBM.getBounds(&srcRect);
context->drawRectToRect(paint, dstRect, srcRect);
return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, result);
}
#endif
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -1,29 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmapSource.h"
SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap)
: INHERITED(0),
fBitmap(bitmap) {
}
SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
fBitmap.unflatten(buffer);
}
void SkBitmapSource::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
fBitmap.flatten(buffer);
}
bool SkBitmapSource::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
SkBitmap* result, SkIPoint* offset) {
*result = fBitmap;
return true;
}

Просмотреть файл

@ -1,321 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBlendImageFilter.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLEffectMatrix.h"
#include "GrTBackendEffectFactory.h"
#include "SkImageFilterUtils.h"
#endif
namespace {
SkXfermode::Mode modeToXfermode(SkBlendImageFilter::Mode mode) {
switch (mode) {
case SkBlendImageFilter::kNormal_Mode:
return SkXfermode::kSrcOver_Mode;
case SkBlendImageFilter::kMultiply_Mode:
return SkXfermode::kMultiply_Mode;
case SkBlendImageFilter::kScreen_Mode:
return SkXfermode::kScreen_Mode;
case SkBlendImageFilter::kDarken_Mode:
return SkXfermode::kDarken_Mode;
case SkBlendImageFilter::kLighten_Mode:
return SkXfermode::kLighten_Mode;
}
SkASSERT(0);
return SkXfermode::kSrcOver_Mode;
}
};
///////////////////////////////////////////////////////////////////////////////
SkBlendImageFilter::SkBlendImageFilter(SkBlendImageFilter::Mode mode, SkImageFilter* background, SkImageFilter* foreground)
: INHERITED(background, foreground), fMode(mode)
{
}
SkBlendImageFilter::~SkBlendImageFilter() {
}
SkBlendImageFilter::SkBlendImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer)
{
fMode = (SkBlendImageFilter::Mode) buffer.readInt();
}
void SkBlendImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeInt((int) fMode);
}
bool SkBlendImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* dst,
SkIPoint* offset) {
SkBitmap background, foreground = src;
SkImageFilter* backgroundInput = getBackgroundInput();
SkImageFilter* foregroundInput = getForegroundInput();
SkASSERT(NULL != backgroundInput);
if (!backgroundInput->filterImage(proxy, src, ctm, &background, offset)) {
return false;
}
if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreground, offset)) {
return false;
}
SkAutoLockPixels alp_foreground(foreground), alp_background(background);
if (!foreground.getPixels() || !background.getPixels()) {
return false;
}
dst->setConfig(background.config(), background.width(), background.height());
dst->allocPixels();
SkCanvas canvas(*dst);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
canvas.drawBitmap(background, 0, 0, &paint);
paint.setXfermodeMode(modeToXfermode(fMode));
canvas.drawBitmap(foreground, 0, 0, &paint);
return true;
}
///////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
class GrGLBlendEffect : public GrGLEffect {
public:
GrGLBlendEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
virtual ~GrGLBlendEffect();
virtual void emitCode(GrGLShaderBuilder*,
const GrDrawEffect&,
EffectKey,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray&) SK_OVERRIDE;
static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
private:
static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
SkBlendImageFilter::Mode fMode;
GrGLEffectMatrix fForegroundEffectMatrix;
GrGLEffectMatrix fBackgroundEffectMatrix;
typedef GrGLEffect INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
class GrBlendEffect : public GrEffect {
public:
static GrEffectRef* Create(SkBlendImageFilter::Mode mode,
GrTexture* foreground,
GrTexture* background) {
AutoEffectUnref effect(SkNEW_ARGS(GrBlendEffect, (mode, foreground, background)));
return CreateEffectRef(effect);
}
virtual ~GrBlendEffect();
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
SkBlendImageFilter::Mode mode() const { return fMode; }
typedef GrGLBlendEffect GLEffect;
static const char* Name() { return "Blend"; }
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
private:
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
GrBlendEffect(SkBlendImageFilter::Mode mode, GrTexture* foreground, GrTexture* background);
GrTextureAccess fForegroundAccess;
GrTextureAccess fBackgroundAccess;
SkBlendImageFilter::Mode fMode;
typedef GrEffect INHERITED;
};
bool SkBlendImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
SkBitmap backgroundBM;
if (!SkImageFilterUtils::GetInputResultGPU(getBackgroundInput(), proxy, src, &backgroundBM)) {
return false;
}
GrTexture* background = (GrTexture*) backgroundBM.getTexture();
SkBitmap foregroundBM;
if (!SkImageFilterUtils::GetInputResultGPU(getForegroundInput(), proxy, src, &foregroundBM)) {
return false;
}
GrTexture* foreground = (GrTexture*) foregroundBM.getTexture();
GrContext* context = foreground->getContext();
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fWidth = src.width();
desc.fHeight = src.height();
desc.fConfig = kSkia8888_GrPixelConfig;
GrAutoScratchTexture ast(context, desc);
SkAutoTUnref<GrTexture> dst(ast.detach());
GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
GrPaint paint;
paint.colorStage(0)->setEffect(
GrBlendEffect::Create(fMode, foreground, background))->unref();
SkRect srcRect;
src.getBounds(&srcRect);
context->drawRect(paint, srcRect);
return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
}
///////////////////////////////////////////////////////////////////////////////
GrBlendEffect::GrBlendEffect(SkBlendImageFilter::Mode mode,
GrTexture* foreground,
GrTexture* background)
: fForegroundAccess(foreground)
, fBackgroundAccess(background)
, fMode(mode) {
this->addTextureAccess(&fForegroundAccess);
this->addTextureAccess(&fBackgroundAccess);
}
GrBlendEffect::~GrBlendEffect() {
}
bool GrBlendEffect::onIsEqual(const GrEffect& sBase) const {
const GrBlendEffect& s = CastEffect<GrBlendEffect>(sBase);
return fForegroundAccess.getTexture() == s.fForegroundAccess.getTexture() &&
fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture() &&
fMode == s.fMode;
}
const GrBackendEffectFactory& GrBlendEffect::getFactory() const {
return GrTBackendEffectFactory<GrBlendEffect>::getInstance();
}
void GrBlendEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
// The output alpha is always 1 - (1 - FGa) * (1 - BGa). So if either FGa or BGa is known to
// be one then the output alpha is one. (This effect ignores its input. We should have a way to
// communicate this.)
if (GrPixelConfigIsOpaque(fForegroundAccess.getTexture()->config()) ||
GrPixelConfigIsOpaque(fBackgroundAccess.getTexture()->config())) {
*validFlags = kA_GrColorComponentFlag;
*color = GrColorPackRGBA(0, 0, 0, 0xff);
} else {
*validFlags = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
GrGLBlendEffect::GrGLBlendEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
: INHERITED(factory)
, fMode(drawEffect.castEffect<GrBlendEffect>().mode())
, fForegroundEffectMatrix(kCoordsType)
, fBackgroundEffectMatrix(kCoordsType) {
}
GrGLBlendEffect::~GrGLBlendEffect() {
}
void GrGLBlendEffect::emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect&,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) {
const char* fgCoords;
const char* bgCoords;
GrSLType fgCoordsType = fForegroundEffectMatrix.emitCode(builder, key, &fgCoords, NULL, "FG");
GrSLType bgCoordsType = fBackgroundEffectMatrix.emitCode(builder, key, &bgCoords, NULL, "BG");
const char* bgColor = "bgColor";
const char* fgColor = "fgColor";
builder->fsCodeAppendf("\t\tvec4 %s = ", fgColor);
builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
samplers[0],
fgCoords,
fgCoordsType);
builder->fsCodeAppend(";\n");
builder->fsCodeAppendf("\t\tvec4 %s = ", bgColor);
builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
samplers[1],
bgCoords,
bgCoordsType);
builder->fsCodeAppendf(";\n");
builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.b);\n", outputColor, bgColor, fgColor);
switch (fMode) {
case SkBlendImageFilter::kNormal_Mode:
builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + %s.rgb;\n", outputColor, fgColor, bgColor, fgColor);
break;
case SkBlendImageFilter::kMultiply_Mode:
builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb + %s.rgb * %s.rgb;\n", outputColor, fgColor, bgColor, bgColor, fgColor, fgColor, bgColor);
break;
case SkBlendImageFilter::kScreen_Mode:
builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - %s.rgb * %s.rgb;\n", outputColor, bgColor, fgColor, fgColor, bgColor);
break;
case SkBlendImageFilter::kDarken_Mode:
builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, (1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, fgColor, bgColor, fgColor, bgColor, fgColor, bgColor);
break;
case SkBlendImageFilter::kLighten_Mode:
builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, (1.0 - %s.a) * %s.rgb + %s.rgb);\n", outputColor, fgColor, bgColor, fgColor, bgColor, fgColor, bgColor);
break;
}
}
void GrGLBlendEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
const GrBlendEffect& blend = drawEffect.castEffect<GrBlendEffect>();
GrTexture* fgTex = blend.texture(0);
GrTexture* bgTex = blend.texture(1);
fForegroundEffectMatrix.setData(uman,
GrEffect::MakeDivByTextureWHMatrix(fgTex),
drawEffect,
fgTex);
fBackgroundEffectMatrix.setData(uman,
GrEffect::MakeDivByTextureWHMatrix(bgTex),
drawEffect,
bgTex);
}
GrGLEffect::EffectKey GrGLBlendEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const GrBlendEffect& blend = drawEffect.castEffect<GrBlendEffect>();
GrTexture* fgTex = blend.texture(0);
GrTexture* bgTex = blend.texture(1);
EffectKey fgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(fgTex),
drawEffect,
kCoordsType,
fgTex);
EffectKey bgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(bgTex),
drawEffect,
kCoordsType,
bgTex);
bgKey <<= GrGLEffectMatrix::kKeyBits;
EffectKey modeKey = blend.mode() << (2 * GrGLEffectMatrix::kKeyBits);
return modeKey | bgKey | fgKey;
}
#endif

Просмотреть файл

@ -1,207 +0,0 @@
/*
* Copyright 2011 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkBlurImageFilter.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "SkImageFilterUtils.h"
#endif
SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
fSigma.fWidth = buffer.readScalar();
fSigma.fHeight = buffer.readScalar();
}
SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input)
: INHERITED(input), fSigma(SkSize::Make(sigmaX, sigmaY)) {
SkASSERT(sigmaX >= 0 && sigmaY >= 0);
}
void SkBlurImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSigma.fWidth);
buffer.writeScalar(fSigma.fHeight);
}
static void boxBlurX(const SkBitmap& src, SkBitmap* dst, int kernelSize,
int leftOffset, int rightOffset)
{
int width = src.width(), height = src.height();
int rightBorder = SkMin32(rightOffset + 1, width);
for (int y = 0; y < height; ++y) {
int sumA = 0, sumR = 0, sumG = 0, sumB = 0;
SkPMColor* p = src.getAddr32(0, y);
for (int i = 0; i < rightBorder; ++i) {
sumA += SkGetPackedA32(*p);
sumR += SkGetPackedR32(*p);
sumG += SkGetPackedG32(*p);
sumB += SkGetPackedB32(*p);
p++;
}
const SkColor* sptr = src.getAddr32(0, y);
SkColor* dptr = dst->getAddr32(0, y);
for (int x = 0; x < width; ++x) {
*dptr = SkPackARGB32(sumA / kernelSize,
sumR / kernelSize,
sumG / kernelSize,
sumB / kernelSize);
if (x >= leftOffset) {
SkColor l = *(sptr - leftOffset);
sumA -= SkGetPackedA32(l);
sumR -= SkGetPackedR32(l);
sumG -= SkGetPackedG32(l);
sumB -= SkGetPackedB32(l);
}
if (x + rightOffset + 1 < width) {
SkColor r = *(sptr + rightOffset + 1);
sumA += SkGetPackedA32(r);
sumR += SkGetPackedR32(r);
sumG += SkGetPackedG32(r);
sumB += SkGetPackedB32(r);
}
sptr++;
dptr++;
}
}
}
static void boxBlurY(const SkBitmap& src, SkBitmap* dst, int kernelSize,
int topOffset, int bottomOffset)
{
int width = src.width(), height = src.height();
int bottomBorder = SkMin32(bottomOffset + 1, height);
int srcStride = src.rowBytesAsPixels();
int dstStride = dst->rowBytesAsPixels();
for (int x = 0; x < width; ++x) {
int sumA = 0, sumR = 0, sumG = 0, sumB = 0;
SkColor* p = src.getAddr32(x, 0);
for (int i = 0; i < bottomBorder; ++i) {
sumA += SkGetPackedA32(*p);
sumR += SkGetPackedR32(*p);
sumG += SkGetPackedG32(*p);
sumB += SkGetPackedB32(*p);
p += srcStride;
}
const SkColor* sptr = src.getAddr32(x, 0);
SkColor* dptr = dst->getAddr32(x, 0);
for (int y = 0; y < height; ++y) {
*dptr = SkPackARGB32(sumA / kernelSize,
sumR / kernelSize,
sumG / kernelSize,
sumB / kernelSize);
if (y >= topOffset) {
SkColor l = *(sptr - topOffset * srcStride);
sumA -= SkGetPackedA32(l);
sumR -= SkGetPackedR32(l);
sumG -= SkGetPackedG32(l);
sumB -= SkGetPackedB32(l);
}
if (y + bottomOffset + 1 < height) {
SkColor r = *(sptr + (bottomOffset + 1) * srcStride);
sumA += SkGetPackedA32(r);
sumR += SkGetPackedR32(r);
sumG += SkGetPackedG32(r);
sumB += SkGetPackedB32(r);
}
sptr += srcStride;
dptr += dstStride;
}
}
}
static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lowOffset, int *highOffset)
{
float pi = SkScalarToFloat(SK_ScalarPI);
int d = static_cast<int>(floorf(SkScalarToFloat(s) * 3.0f * sqrtf(2.0f * pi) / 4.0f + 0.5f));
*kernelSize = d;
if (d % 2 == 1) {
*lowOffset = *highOffset = (d - 1) / 2;
*kernelSize3 = d;
} else {
*highOffset = d / 2;
*lowOffset = *highOffset - 1;
*kernelSize3 = d + 1;
}
}
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source, const SkMatrix& ctm,
SkBitmap* dst, SkIPoint* offset) {
SkBitmap src = this->getInputResult(0, proxy, source, ctm, offset);
if (src.config() != SkBitmap::kARGB_8888_Config) {
return false;
}
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
dst->setConfig(src.config(), src.width(), src.height());
dst->allocPixels();
int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);
if (kernelSizeX < 0 || kernelSizeY < 0) {
return false;
}
if (kernelSizeX == 0 && kernelSizeY == 0) {
src.copyTo(dst, dst->config());
return true;
}
SkBitmap temp;
temp.setConfig(dst->config(), dst->width(), dst->height());
if (!temp.allocPixels()) {
return false;
}
if (kernelSizeX > 0 && kernelSizeY > 0) {
boxBlurX(src, &temp, kernelSizeX, lowOffsetX, highOffsetX);
boxBlurY(temp, dst, kernelSizeY, lowOffsetY, highOffsetY);
boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX);
boxBlurY(temp, dst, kernelSizeY, highOffsetY, lowOffsetY);
boxBlurX(*dst, &temp, kernelSizeX3, highOffsetX, highOffsetX);
boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY);
} else if (kernelSizeX > 0) {
boxBlurX(src, dst, kernelSizeX, lowOffsetX, highOffsetX);
boxBlurX(*dst, &temp, kernelSizeX, highOffsetX, lowOffsetX);
boxBlurX(temp, dst, kernelSizeX3, highOffsetX, highOffsetX);
} else if (kernelSizeY > 0) {
boxBlurY(src, dst, kernelSizeY, lowOffsetY, highOffsetY);
boxBlurY(*dst, &temp, kernelSizeY, highOffsetY, lowOffsetY);
boxBlurY(temp, dst, kernelSizeY3, highOffsetY, highOffsetY);
}
return true;
}
bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
#if SK_SUPPORT_GPU
SkBitmap input;
if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &input)) {
return false;
}
GrTexture* source = (GrTexture*) input.getTexture();
SkRect rect;
src.getBounds(&rect);
SkAutoTUnref<GrTexture> tex(source->getContext()->gaussianBlur(source, false, rect,
fSigma.width(), fSigma.height()));
return SkImageFilterUtils::WrapTexture(tex, src.width(), src.height(), result);
#else
SkDEBUGFAIL("Should not call in GPU-less build");
return false;
#endif
}

Просмотреть файл

@ -1,57 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBlurMask_DEFINED
#define SkBlurMask_DEFINED
#include "SkShader.h"
#include "SkMask.h"
class SkBlurMask {
public:
enum Style {
kNormal_Style, //!< fuzzy inside and outside
kSolid_Style, //!< solid inside, fuzzy outside
kOuter_Style, //!< nothing inside, fuzzy outside
kInner_Style, //!< fuzzy inside, nothing outside
kStyleCount
};
enum Quality {
kLow_Quality, //!< box blur
kHigh_Quality //!< three pass box blur (similar to gaussian)
};
static bool BlurRect(SkMask *dst, const SkRect &src,
SkScalar radius, Style style,
SkIPoint *margin = NULL,
SkMask::CreateMode createMode=SkMask::kComputeBoundsAndRenderImage_CreateMode);
static bool Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin = NULL);
static bool BlurSeparable(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin = NULL);
// the "ground truth" blur does a gaussian convolution; it's slow
// but useful for comparison purposes.
static bool BlurGroundTruth(SkMask* dst, const SkMask& src,
SkScalar provided_radius, Style style,
SkIPoint* margin = NULL);
private:
static bool Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin, bool separable);
};
#endif

Просмотреть файл

@ -1,375 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkFlattenableBuffers.h"
#include "SkMaskFilter.h"
#include "SkBounder.h"
#include "SkRasterClip.h"
#include "SkRTConf.h"
#include "SkStringUtils.h"
class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
SkBlurMaskFilterImpl(SkScalar radius, SkBlurMaskFilter::BlurStyle,
uint32_t flags);
// overrides from SkMaskFilter
virtual SkMask::Format getFormat() const SK_OVERRIDE;
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
SkIPoint* margin) const SK_OVERRIDE;
virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
protected:
virtual FilterReturn filterRectsToNine(const SkRect[], int count, const SkMatrix&,
const SkIRect& clipBounds,
NinePatch*) const SK_OVERRIDE;
bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix,
SkIPoint* margin, SkMask::CreateMode createMode) const;
private:
SkScalar fRadius;
SkBlurMaskFilter::BlurStyle fBlurStyle;
uint32_t fBlurFlags;
SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
typedef SkMaskFilter INHERITED;
};
SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
SkBlurMaskFilter::BlurStyle style,
uint32_t flags) {
// use !(radius > 0) instead of radius <= 0 to reject NaN values
if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
|| flags > SkBlurMaskFilter::kAll_BlurFlag) {
return NULL;
}
return SkNEW_ARGS(SkBlurMaskFilterImpl, (radius, style, flags));
}
///////////////////////////////////////////////////////////////////////////////
SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar radius,
SkBlurMaskFilter::BlurStyle style,
uint32_t flags)
: fRadius(radius), fBlurStyle(style), fBlurFlags(flags) {
#if 0
fGamma = NULL;
if (gammaScale) {
fGamma = new U8[256];
if (gammaScale > 0)
SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
else
SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
}
#endif
SkASSERT(radius >= 0);
SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}
SkMask::Format SkBlurMaskFilterImpl::getFormat() const {
return SkMask::kA8_Format;
}
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix,
SkIPoint* margin) const{
SkScalar radius;
if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
radius = fRadius;
} else {
radius = matrix.mapRadius(fRadius);
}
// To avoid unseemly allocation requests (esp. for finite platforms like
// handset) we limit the radius so something manageable. (as opposed to
// a request like 10,000)
static const SkScalar MAX_RADIUS = SkIntToScalar(128);
radius = SkMinScalar(radius, MAX_RADIUS);
SkBlurMask::Quality blurQuality =
(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
#ifndef SK_DISABLE_SEPARABLE_MASK_BLUR
return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
blurQuality, margin);
#else
return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
blurQuality, margin);
#endif
}
bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
const SkMatrix& matrix,
SkIPoint* margin, SkMask::CreateMode createMode) const{
SkScalar radius;
if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
radius = fRadius;
} else {
radius = matrix.mapRadius(fRadius);
}
// To avoid unseemly allocation requests (esp. for finite platforms like
// handset) we limit the radius so something manageable. (as opposed to
// a request like 10,000)
static const SkScalar MAX_RADIUS = SkIntToScalar(128);
radius = SkMinScalar(radius, MAX_RADIUS);
return SkBlurMask::BlurRect(dst, r, radius, (SkBlurMask::Style)fBlurStyle,
margin, createMode);
}
#include "SkCanvas.h"
static bool drawRectsIntoMask(const SkRect rects[], int count, SkMask* mask) {
rects[0].roundOut(&mask->fBounds);
mask->fRowBytes = SkAlign4(mask->fBounds.width());
mask->fFormat = SkMask::kA8_Format;
size_t size = mask->computeImageSize();
mask->fImage = SkMask::AllocImage(size);
if (NULL == mask->fImage) {
return false;
}
sk_bzero(mask->fImage, size);
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kA8_Config,
mask->fBounds.width(), mask->fBounds.height(),
mask->fRowBytes);
bitmap.setPixels(mask->fImage);
SkCanvas canvas(bitmap);
canvas.translate(-SkIntToScalar(mask->fBounds.left()),
-SkIntToScalar(mask->fBounds.top()));
SkPaint paint;
paint.setAntiAlias(true);
if (1 == count) {
canvas.drawRect(rects[0], paint);
} else {
// todo: do I need a fast way to do this?
SkPath path;
path.addRect(rects[0]);
path.addRect(rects[1]);
path.setFillType(SkPath::kEvenOdd_FillType);
canvas.drawPath(path, paint);
}
return true;
}
static bool rect_exceeds(const SkRect& r, SkScalar v) {
return r.fLeft < -v || r.fTop < -v || r.fRight > v || r.fBottom > v ||
r.width() > v || r.height() > v;
}
#ifdef SK_IGNORE_FAST_RECT_BLUR
SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", false, "Use the faster analytic blur approach for ninepatch rects" );
#else
SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
#endif
SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
const SkMatrix& matrix,
const SkIRect& clipBounds,
NinePatch* patch) const {
if (count < 1 || count > 2) {
return kUnimplemented_FilterReturn;
}
// TODO: report correct metrics for innerstyle, where we do not grow the
// total bounds, but we do need an inset the size of our blur-radius
if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) {
return kUnimplemented_FilterReturn;
}
// TODO: take clipBounds into account to limit our coordinates up front
// for now, just skip too-large src rects (to take the old code path).
if (rect_exceeds(rects[0], SkIntToScalar(32767))) {
return kUnimplemented_FilterReturn;
}
SkIPoint margin;
SkMask srcM, dstM;
rects[0].roundOut(&srcM.fBounds);
srcM.fImage = NULL;
srcM.fFormat = SkMask::kA8_Format;
srcM.fRowBytes = 0;
bool filterResult = false;
if (count == 1 && c_analyticBlurNinepatch) {
// special case for fast rect blur
// don't actually do the blur the first time, just compute the correct size
filterResult = this->filterRectMask(&dstM, rects[0], matrix, &margin,
SkMask::kJustComputeBounds_CreateMode);
} else {
filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
}
if (!filterResult) {
return kFalse_FilterReturn;
}
/*
* smallR is the smallest version of 'rect' that will still guarantee that
* we get the same blur results on all edges, plus 1 center row/col that is
* representative of the extendible/stretchable edges of the ninepatch.
* Since our actual edge may be fractional we inset 1 more to be sure we
* don't miss any interior blur.
* x is an added pixel of blur, and { and } are the (fractional) edge
* pixels from the original rect.
*
* x x { x x .... x x } x x
*
* Thus, in this case, we inset by a total of 5 (on each side) beginning
* with our outer-rect (dstM.fBounds)
*/
SkRect smallR[2];
SkIPoint center;
// +2 is from +1 for each edge (to account for possible fractional edges
int smallW = dstM.fBounds.width() - srcM.fBounds.width() + 2;
int smallH = dstM.fBounds.height() - srcM.fBounds.height() + 2;
SkIRect innerIR;
if (1 == count) {
innerIR = srcM.fBounds;
center.set(smallW, smallH);
} else {
SkASSERT(2 == count);
rects[1].roundIn(&innerIR);
center.set(smallW + (innerIR.left() - srcM.fBounds.left()),
smallH + (innerIR.top() - srcM.fBounds.top()));
}
// +1 so we get a clean, stretchable, center row/col
smallW += 1;
smallH += 1;
// we want the inset amounts to be integral, so we don't change any
// fractional phase on the fRight or fBottom of our smallR.
const SkScalar dx = SkIntToScalar(innerIR.width() - smallW);
const SkScalar dy = SkIntToScalar(innerIR.height() - smallH);
if (dx < 0 || dy < 0) {
// we're too small, relative to our blur, to break into nine-patch,
// so we ask to have our normal filterMask() be called.
return kUnimplemented_FilterReturn;
}
smallR[0].set(rects[0].left(), rects[0].top(), rects[0].right() - dx, rects[0].bottom() - dy);
SkASSERT(!smallR[0].isEmpty());
if (2 == count) {
smallR[1].set(rects[1].left(), rects[1].top(),
rects[1].right() - dx, rects[1].bottom() - dy);
SkASSERT(!smallR[1].isEmpty());
}
if (count > 1 || !c_analyticBlurNinepatch) {
if (!drawRectsIntoMask(smallR, count, &srcM)) {
return kFalse_FilterReturn;
}
SkAutoMaskFreeImage amf(srcM.fImage);
if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
return kFalse_FilterReturn;
}
} else {
if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin,
SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
return kFalse_FilterReturn;
}
}
patch->fMask.fBounds.offsetTo(0, 0);
patch->fOuterRect = dstM.fBounds;
patch->fCenter = center;
return kTrue_FilterReturn;
}
void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
SkRect* dst) const {
dst->set(src.fLeft - fRadius, src.fTop - fRadius,
src.fRight + fRadius, src.fBottom + fRadius);
}
SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
: SkMaskFilter(buffer) {
fRadius = buffer.readScalar();
fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
SkASSERT(fRadius >= 0);
SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
}
void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fRadius);
buffer.writeInt(fBlurStyle);
buffer.writeUInt(fBlurFlags);
}
static const SkMaskFilter::BlurType gBlurStyle2BlurType[] = {
SkMaskFilter::kNormal_BlurType,
SkMaskFilter::kSolid_BlurType,
SkMaskFilter::kOuter_BlurType,
SkMaskFilter::kInner_BlurType,
};
SkMaskFilter::BlurType SkBlurMaskFilterImpl::asABlur(BlurInfo* info) const {
if (info) {
info->fRadius = fRadius;
info->fIgnoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
info->fHighQuality = SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag);
}
return gBlurStyle2BlurType[fBlurStyle];
}
#ifdef SK_DEVELOPER
void SkBlurMaskFilterImpl::toString(SkString* str) const {
str->append("SkBlurMaskFilterImpl: (");
str->append("radius: ");
str->appendScalar(fRadius);
str->append(" ");
static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = {
"normal", "solid", "outer", "inner"
};
str->appendf("style: %s ", gStyleName[fBlurStyle]);
str->append("flags: (");
if (fBlurFlags) {
bool needSeparator = false;
SkAddFlagToString(str,
SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag),
"IgnoreXform", &needSeparator);
SkAddFlagToString(str,
SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag),
"HighQuality", &needSeparator);
} else {
str->append("None");
}
str->append("))");
}
#endif
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkBlurMaskFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurMaskFilterImpl)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

Просмотреть файл

@ -1,492 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBlitRow.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkUtils.h"
#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1)
// baseclass for filters that store a color and mode
class SkModeColorFilter : public SkColorFilter {
public:
SkModeColorFilter(SkColor color) {
fColor = color;
fMode = ILLEGAL_XFERMODE_MODE;
this->updateCache();
}
SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
fColor = color;
fMode = mode;
this->updateCache();
};
SkColor getColor() const { return fColor; }
SkXfermode::Mode getMode() const { return fMode; }
bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
SkPMColor getPMColor() const { return fPMColor; }
virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
if (ILLEGAL_XFERMODE_MODE == fMode) {
return false;
}
if (color) {
*color = fColor;
}
if (mode) {
*mode = fMode;
}
return true;
}
virtual uint32_t getFlags() const SK_OVERRIDE {
return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
SkPMColor color = fPMColor;
SkXfermodeProc proc = fProc;
for (int i = 0; i < count; i++) {
result[i] = proc(color, shader[i]);
}
}
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const SK_OVERRIDE {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
SkPMColor color = fPMColor;
SkXfermodeProc16 proc16 = fProc16;
for (int i = 0; i < count; i++) {
result[i] = proc16(color, shader[i]);
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
this->INHERITED::flatten(buffer);
buffer.writeColor(fColor);
buffer.writeUInt(fMode);
}
SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
fColor = buffer.readColor();
fMode = (SkXfermode::Mode)buffer.readUInt();
this->updateCache();
}
private:
SkColor fColor;
SkXfermode::Mode fMode;
// cache
SkPMColor fPMColor;
SkXfermodeProc fProc;
SkXfermodeProc16 fProc16;
void updateCache() {
fPMColor = SkPreMultiplyColor(fColor);
fProc = SkXfermode::GetProc(fMode);
fProc16 = SkXfermode::GetProc16(fMode, fColor);
}
typedef SkColorFilter INHERITED;
};
class Src_SkModeColorFilter : public SkModeColorFilter {
public:
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
virtual uint32_t getFlags() const SK_OVERRIDE {
if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
return kAlphaUnchanged_Flag | kHasFilter16_Flag;
} else {
return 0;
}
}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
sk_memset32(result, this->getPMColor(), count);
}
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const SK_OVERRIDE {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
protected:
Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
typedef SkModeColorFilter INHERITED;
};
class SrcOver_SkModeColorFilter : public SkModeColorFilter {
public:
SrcOver_SkModeColorFilter(SkColor color)
: INHERITED(color, SkXfermode::kSrcOver_Mode) {
fColor32Proc = SkBlitRow::ColorProcFactory();
}
virtual uint32_t getFlags() const SK_OVERRIDE {
if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
return kAlphaUnchanged_Flag | kHasFilter16_Flag;
} else {
return 0;
}
}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
fColor32Proc(result, shader, count, this->getPMColor());
}
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const SK_OVERRIDE {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
protected:
SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
fColor32Proc = SkBlitRow::ColorProcFactory();
}
private:
SkBlitRow::ColorProc fColor32Proc;
typedef SkModeColorFilter INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
SkXfermode::Mode mode) {
unsigned alpha = SkColorGetA(color);
// first collaps some modes if possible
if (SkXfermode::kClear_Mode == mode) {
color = 0;
mode = SkXfermode::kSrc_Mode;
} else if (SkXfermode::kSrcOver_Mode == mode) {
if (0 == alpha) {
mode = SkXfermode::kDst_Mode;
} else if (255 == alpha) {
mode = SkXfermode::kSrc_Mode;
}
// else just stay srcover
}
// weed out combinations that are noops, and just return null
if (SkXfermode::kDst_Mode == mode ||
(0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
SkXfermode::kDstOver_Mode == mode ||
SkXfermode::kDstOut_Mode == mode ||
SkXfermode::kSrcATop_Mode == mode ||
SkXfermode::kXor_Mode == mode ||
SkXfermode::kDarken_Mode == mode)) ||
(0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
return NULL;
}
switch (mode) {
case SkXfermode::kSrc_Mode:
return SkNEW_ARGS(Src_SkModeColorFilter, (color));
case SkXfermode::kSrcOver_Mode:
return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
default:
return SkNEW_ARGS(SkModeColorFilter, (color, mode));
}
}
///////////////////////////////////////////////////////////////////////////////
static inline unsigned pin(unsigned value, unsigned max) {
if (value > max) {
value = max;
}
return value;
}
class SkLightingColorFilter : public SkColorFilter {
public:
SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
unsigned addR = SkColorGetR(fAdd);
unsigned addG = SkColorGetG(fAdd);
unsigned addB = SkColorGetB(fAdd);
for (int i = 0; i < count; i++) {
SkPMColor c = shader[i];
if (c) {
unsigned a = SkGetPackedA32(c);
unsigned scaleA = SkAlpha255To256(a);
unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
c = SkPackARGB32(a, r, g, b);
}
result[i] = c;
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter)
protected:
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
this->INHERITED::flatten(buffer);
buffer.writeColor(fMul);
buffer.writeColor(fAdd);
}
SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
fMul = buffer.readColor();
fAdd = buffer.readColor();
}
SkColor fMul, fAdd;
private:
typedef SkColorFilter INHERITED;
};
class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
public:
SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
: INHERITED(mul, add) {}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
unsigned addR = SkColorGetR(fAdd);
unsigned addG = SkColorGetG(fAdd);
unsigned addB = SkColorGetB(fAdd);
for (int i = 0; i < count; i++) {
SkPMColor c = shader[i];
if (c) {
unsigned a = SkGetPackedA32(c);
unsigned scaleA = SkAlpha255To256(a);
unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
c = SkPackARGB32(a, r, g, b);
}
result[i] = c;
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustAdd)
protected:
SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
typedef SkLightingColorFilter INHERITED;
};
class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
public:
SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
: INHERITED(mul, add) {}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
for (int i = 0; i < count; i++) {
SkPMColor c = shader[i];
if (c) {
unsigned a = SkGetPackedA32(c);
unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
c = SkPackARGB32(a, r, g, b);
}
result[i] = c;
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustMul)
protected:
SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
typedef SkLightingColorFilter INHERITED;
};
class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
public:
SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
: INHERITED(mul, add) {
SkASSERT(SkColorGetR(add) == 0);
SkASSERT(SkColorGetG(add) == 0);
SkASSERT(SkColorGetB(add) == 0);
SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
}
virtual uint32_t getFlags() const SK_OVERRIDE {
return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
}
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const SK_OVERRIDE {
// all mul components are the same
unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
if (count > 0) {
do {
*result++ = SkAlphaMulRGB16(*shader++, scale);
} while (--count > 0);
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_SingleMul)
protected:
SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
typedef SkLightingColorFilter INHERITED;
};
class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
public:
SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
: INHERITED(mul, add) {}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
unsigned addR = SkColorGetR(fAdd);
unsigned addG = SkColorGetG(fAdd);
unsigned addB = SkColorGetB(fAdd);
for (int i = 0; i < count; i++) {
SkPMColor c = shader[i];
if (c) {
unsigned a = SkGetPackedA32(c);
unsigned scaleA = SkAlpha255To256(a);
unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
c = SkPackARGB32(a, r, g, b);
}
result[i] = c;
}
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_NoPin)
protected:
SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
typedef SkLightingColorFilter INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
class SkSimpleColorFilter : public SkColorFilter {
public:
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW(SkSimpleColorFilter);
}
protected:
void filterSpan(const SkPMColor src[], int count, SkPMColor
result[]) const SK_OVERRIDE {
if (result != src) {
memcpy(result, src, count * sizeof(SkPMColor));
}
}
virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {}
virtual Factory getFactory() {
return CreateProc;
}
};
SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
mul &= 0x00FFFFFF;
add &= 0x00FFFFFF;
if (0xFFFFFF == mul) {
if (0 == add) {
return SkNEW(SkSimpleColorFilter); // no change to the colors
} else {
return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
}
}
if (0 == add) {
if (SkColorGetR(mul) == SkColorGetG(mul) &&
SkColorGetR(mul) == SkColorGetB(mul)) {
return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
} else {
return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
}
}
if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
SkColorGetB(mul) + SkColorGetB(add) <= 255) {
return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
}
return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustAdd)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustMul)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_SingleMul)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_NoPin)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSimpleColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

Просмотреть файл

@ -1,46 +0,0 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkMatrix.h"
#if SK_SUPPORT_GPU
#include "GrTexture.h"
#include "SkImageFilterUtils.h"
#include "SkBitmap.h"
#include "SkGrPixelRef.h"
#include "SkGr.h"
bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
SkASSERT(texture->config() == kSkia8888_GrPixelConfig);
result->setConfig(SkBitmap::kARGB_8888_Config, width, height);
result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (texture)))->unref();
return true;
}
bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
if (!filter) {
*result = src;
return true;
} else if (filter->canFilterImageGPU()) {
return filter->filterImageGPU(proxy, src, result);
} else {
SkIPoint offset;
if (filter->filterImage(proxy, src, SkMatrix(), result, &offset)) {
if (!result->getTexture()) {
GrContext* context = ((GrTexture *) src.getTexture())->getContext();
GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context,
*result, NULL);
result->setPixelRef(new SkGrPixelRef(resultTex))->unref();
GrUnlockAndUnrefCachedBitmapTexture(resultTex);
}
return true;
} else {
return false;
}
}
}
#endif

Просмотреть файл

@ -1,49 +0,0 @@
/*
* Copyright 2012 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkOffsetImageFilter.h"
#include "SkBitmap.h"
#include "SkMatrix.h"
#include "SkFlattenableBuffers.h"
bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* loc) {
SkBitmap src = this->getInputResult(0, proxy, source, matrix, loc);
SkVector vec;
matrix.mapVectors(&vec, &fOffset, 1);
loc->fX += SkScalarRoundToInt(vec.fX);
loc->fY += SkScalarRoundToInt(vec.fY);
*result = src;
return true;
}
bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) {
SkVector vec;
ctm.mapVectors(&vec, &fOffset, 1);
*dst = src;
dst->offset(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY));
return true;
}
void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fOffset);
}
SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy,
SkImageFilter* input) : INHERITED(input) {
fOffset.set(dx, dy);
}
SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
buffer.readPoint(&fOffset);
}

Просмотреть файл

@ -1,58 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkRectShaderImageFilter.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkFlattenableBuffers.h"
#include "SkShader.h"
SkRectShaderImageFilter* SkRectShaderImageFilter::Create(SkShader* s, const SkRect& rect) {
SkASSERT(s);
return SkNEW_ARGS(SkRectShaderImageFilter, (s, rect));
}
SkRectShaderImageFilter::SkRectShaderImageFilter(SkShader* s, const SkRect& rect)
: INHERITED(NULL)
, fShader(s)
, fRect(rect) {
SkASSERT(s);
s->ref();
}
SkRectShaderImageFilter::SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
fShader = buffer.readFlattenableT<SkShader>();
buffer.readRect(&fRect);
}
void SkRectShaderImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShader);
buffer.writeRect(fRect);
}
SkRectShaderImageFilter::~SkRectShaderImageFilter() {
SkSafeUnref(fShader);
}
bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* loc) {
SkAutoTUnref<SkDevice> device(proxy->createDevice(SkScalarCeilToInt(fRect.width()),
SkScalarCeilToInt(fRect.height())));
SkCanvas canvas(device.get());
SkPaint paint;
paint.setShader(fShader);
canvas.drawRect(fRect, paint);
*result = device.get()->accessBitmap(false);
return true;
}

Просмотреть файл

@ -1,129 +0,0 @@
#include "SkTestImageFilters.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkFlattenableBuffers.h"
// Simple helper canvas that "takes ownership" of the provided device, so that
// when this canvas goes out of scope, so will its device. Could be replaced
// with the following:
//
// SkCanvas canvas(device);
// SkAutoTUnref<SkDevice> aur(device);
//
class OwnDeviceCanvas : public SkCanvas {
public:
OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) {
SkSafeUnref(device);
}
};
///////////////////////////////////////////////////////////////////////////////
SkComposeImageFilter::~SkComposeImageFilter() {
}
bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* result,
SkIPoint* loc) {
SkImageFilter* outer = getInput(0);
SkImageFilter* inner = getInput(1);
if (!outer && !inner) {
return false;
}
if (!outer || !inner) {
return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, loc);
}
SkBitmap tmp;
return inner->filterImage(proxy, src, ctm, &tmp, loc) &&
outer->filterImage(proxy, tmp, ctm, result, loc);
}
bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
const SkMatrix& ctm,
SkIRect* dst) {
SkImageFilter* outer = getInput(0);
SkImageFilter* inner = getInput(1);
if (!outer && !inner) {
return false;
}
if (!outer || !inner) {
return (outer ? outer : inner)->filterBounds(src, ctm, dst);
}
SkIRect tmp;
return inner->filterBounds(src, ctm, &tmp) &&
outer->filterBounds(tmp, ctm, dst);
}
SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
}
///////////////////////////////////////////////////////////////////////////////
bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix&,
SkBitmap* result, SkIPoint*) {
SkScalar scale = fScale;
if (scale > SK_Scalar1 || scale <= 0) {
return false;
}
int dstW = SkScalarRoundToInt(src.width() * scale);
int dstH = SkScalarRoundToInt(src.height() * scale);
if (dstW < 1) {
dstW = 1;
}
if (dstH < 1) {
dstH = 1;
}
SkBitmap tmp;
// downsample
{
SkDevice* dev = proxy->createDevice(dstW, dstH);
if (NULL == dev) {
return false;
}
OwnDeviceCanvas canvas(dev);
SkPaint paint;
paint.setFilterBitmap(true);
canvas.scale(scale, scale);
canvas.drawBitmap(src, 0, 0, &paint);
tmp = dev->accessBitmap(false);
}
// upscale
{
SkDevice* dev = proxy->createDevice(src.width(), src.height());
if (NULL == dev) {
return false;
}
OwnDeviceCanvas canvas(dev);
SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()),
SkIntToScalar(src.height()));
canvas.drawBitmapRect(tmp, NULL, r, NULL);
*result = dev->accessBitmap(false);
}
return true;
}
void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fScale);
}
SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
fScale = buffer.readScalar();
}

Просмотреть файл

@ -1,38 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkGradientShaderPriv.h"
// Clamp
SkFixed clamp_tileproc(SkFixed x) {
return SkClampMax(x, 0xFFFF);
}
// Repeat
SkFixed repeat_tileproc(SkFixed x) {
return x & 0xFFFF;
}
// Mirror
// Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
// See http://code.google.com/p/skia/issues/detail?id=472
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#pragma optimize("", off)
#endif
SkFixed mirror_tileproc(SkFixed x) {
int s = x << 15 >> 31;
return (x ^ s) & 0xFFFF;
}
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#pragma optimize("", on)
#endif

Просмотреть файл

@ -1,849 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrAAHairLinePathRenderer.h"
#include "GrContext.h"
#include "GrDrawState.h"
#include "GrDrawTargetCaps.h"
#include "GrEffect.h"
#include "GrGpu.h"
#include "GrIndexBuffer.h"
#include "GrPathUtils.h"
#include "GrTBackendEffectFactory.h"
#include "SkGeometry.h"
#include "SkStroke.h"
#include "SkTemplates.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
namespace {
// quadratics are rendered as 5-sided polys in order to bound the
// AA stroke around the center-curve. See comments in push_quad_index_buffer and
// bloat_quad.
static const int kVertsPerQuad = 5;
static const int kIdxsPerQuad = 9;
static const int kVertsPerLineSeg = 4;
static const int kIdxsPerLineSeg = 6;
static const int kNumQuadsInIdxBuffer = 256;
static const size_t kQuadIdxSBufize = kIdxsPerQuad *
sizeof(uint16_t) *
kNumQuadsInIdxBuffer;
bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
uint16_t* data = (uint16_t*) qIdxBuffer->lock();
bool tempData = NULL == data;
if (tempData) {
data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad);
}
for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) {
// Each quadratic is rendered as a five sided polygon. This poly bounds
// the quadratic's bounding triangle but has been expanded so that the
// 1-pixel wide area around the curve is inside the poly.
// If a,b,c are the original control points then the poly a0,b0,c0,c1,a1
// that is rendered would look like this:
// b0
// b
//
// a0 c0
// a c
// a1 c1
// Each is drawn as three triangles specified by these 9 indices:
int baseIdx = i * kIdxsPerQuad;
uint16_t baseVert = (uint16_t)(i * kVertsPerQuad);
data[0 + baseIdx] = baseVert + 0; // a0
data[1 + baseIdx] = baseVert + 1; // a1
data[2 + baseIdx] = baseVert + 2; // b0
data[3 + baseIdx] = baseVert + 2; // b0
data[4 + baseIdx] = baseVert + 4; // c1
data[5 + baseIdx] = baseVert + 3; // c0
data[6 + baseIdx] = baseVert + 1; // a1
data[7 + baseIdx] = baseVert + 4; // c1
data[8 + baseIdx] = baseVert + 2; // b0
}
if (tempData) {
bool ret = qIdxBuffer->updateData(data, kQuadIdxSBufize);
delete[] data;
return ret;
} else {
qIdxBuffer->unlock();
return true;
}
}
}
GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) {
const GrIndexBuffer* lIdxBuffer = context->getQuadIndexBuffer();
if (NULL == lIdxBuffer) {
return NULL;
}
GrGpu* gpu = context->getGpu();
GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false);
SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf);
if (NULL == qIdxBuf ||
!push_quad_index_data(qIdxBuf)) {
return NULL;
}
return SkNEW_ARGS(GrAAHairLinePathRenderer,
(context, lIdxBuffer, qIdxBuf));
}
GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
const GrContext* context,
const GrIndexBuffer* linesIndexBuffer,
const GrIndexBuffer* quadsIndexBuffer) {
fLinesIndexBuffer = linesIndexBuffer;
linesIndexBuffer->ref();
fQuadsIndexBuffer = quadsIndexBuffer;
quadsIndexBuffer->ref();
}
GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
fLinesIndexBuffer->unref();
fQuadsIndexBuffer->unref();
}
namespace {
typedef SkTArray<SkPoint, true> PtArray;
#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
typedef SkTArray<int, true> IntArray;
// Takes 178th time of logf on Z600 / VC2010
int get_float_exp(float x) {
GR_STATIC_ASSERT(sizeof(int) == sizeof(float));
#if GR_DEBUG
static bool tested;
if (!tested) {
tested = true;
GrAssert(get_float_exp(0.25f) == -2);
GrAssert(get_float_exp(0.3f) == -2);
GrAssert(get_float_exp(0.5f) == -1);
GrAssert(get_float_exp(1.f) == 0);
GrAssert(get_float_exp(2.f) == 1);
GrAssert(get_float_exp(2.5f) == 1);
GrAssert(get_float_exp(8.f) == 3);
GrAssert(get_float_exp(100.f) == 6);
GrAssert(get_float_exp(1000.f) == 9);
GrAssert(get_float_exp(1024.f) == 10);
GrAssert(get_float_exp(3000000.f) == 21);
}
#endif
const int* iptr = (const int*)&x;
return (((*iptr) & 0x7f800000) >> 23) - 127;
}
// we subdivide the quads to avoid huge overfill
// if it returns -1 then should be drawn as lines
int num_quad_subdivs(const SkPoint p[3]) {
static const SkScalar gDegenerateToLineTol = SK_Scalar1;
static const SkScalar gDegenerateToLineTolSqd =
SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
return -1;
}
SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]);
if (dsqd < gDegenerateToLineTolSqd) {
return -1;
}
if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) {
return -1;
}
// tolerance of triangle height in pixels
// tuned on windows Quadro FX 380 / Z600
// trade off of fill vs cpu time on verts
// maybe different when do this using gpu (geo or tess shaders)
static const SkScalar gSubdivTol = 175 * SK_Scalar1;
if (dsqd <= SkScalarMul(gSubdivTol, gSubdivTol)) {
return 0;
} else {
static const int kMaxSub = 4;
// subdividing the quad reduces d by 4. so we want x = log4(d/tol)
// = log4(d*d/tol*tol)/2
// = log2(d*d/tol*tol)
#ifdef SK_SCALAR_IS_FLOAT
// +1 since we're ignoring the mantissa contribution.
int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1;
log = GrMin(GrMax(0, log), kMaxSub);
return log;
#else
SkScalar log = SkScalarLog(
SkScalarDiv(dsqd,
SkScalarMul(gSubdivTol, gSubdivTol)));
static const SkScalar conv = SkScalarInvert(SkScalarLog(2));
log = SkScalarMul(log, conv);
return GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub);
#endif
}
}
/**
* Generates the lines and quads to be rendered. Lines are always recorded in
* device space. We will do a device space bloat to account for the 1pixel
* thickness.
* Quads are recorded in device space unless m contains
* perspective, then in they are in src space. We do this because we will
* subdivide large quads to reduce over-fill. This subdivision has to be
* performed before applying the perspective matrix.
*/
int generate_lines_and_quads(const SkPath& path,
const SkMatrix& m,
const GrIRect& devClipBounds,
PtArray* lines,
PtArray* quads,
IntArray* quadSubdivCnts) {
SkPath::Iter iter(path, false);
int totalQuadCount = 0;
GrRect bounds;
GrIRect ibounds;
bool persp = m.hasPerspective();
for (;;) {
GrPoint pts[4];
GrPoint devPts[4];
GrPathCmd cmd = (GrPathCmd)iter.next(pts);
switch (cmd) {
case kMove_PathCmd:
break;
case kLine_PathCmd:
m.mapPoints(devPts, pts, 2);
bounds.setBounds(devPts, 2);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
if (SkIRect::Intersects(devClipBounds, ibounds)) {
SkPoint* pts = lines->push_back_n(2);
pts[0] = devPts[0];
pts[1] = devPts[1];
}
break;
case kQuadratic_PathCmd:
m.mapPoints(devPts, pts, 3);
bounds.setBounds(devPts, 3);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
if (SkIRect::Intersects(devClipBounds, ibounds)) {
int subdiv = num_quad_subdivs(devPts);
GrAssert(subdiv >= -1);
if (-1 == subdiv) {
SkPoint* pts = lines->push_back_n(4);
pts[0] = devPts[0];
pts[1] = devPts[1];
pts[2] = devPts[1];
pts[3] = devPts[2];
} else {
// when in perspective keep quads in src space
SkPoint* qPts = persp ? pts : devPts;
SkPoint* pts = quads->push_back_n(3);
pts[0] = qPts[0];
pts[1] = qPts[1];
pts[2] = qPts[2];
quadSubdivCnts->push_back() = subdiv;
totalQuadCount += 1 << subdiv;
}
}
break;
case kCubic_PathCmd:
m.mapPoints(devPts, pts, 4);
bounds.setBounds(devPts, 4);
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
if (SkIRect::Intersects(devClipBounds, ibounds)) {
PREALLOC_PTARRAY(32) q;
// we don't need a direction if we aren't constraining the subdivision
static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction;
// We convert cubics to quadratics (for now).
// In perspective have to do conversion in src space.
if (persp) {
SkScalar tolScale =
GrPathUtils::scaleToleranceToSrc(SK_Scalar1, m,
path.getBounds());
GrPathUtils::convertCubicToQuads(pts, tolScale, false, kDummyDir, &q);
} else {
GrPathUtils::convertCubicToQuads(devPts, SK_Scalar1, false, kDummyDir, &q);
}
for (int i = 0; i < q.count(); i += 3) {
SkPoint* qInDevSpace;
// bounds has to be calculated in device space, but q is
// in src space when there is perspective.
if (persp) {
m.mapPoints(devPts, &q[i], 3);
bounds.setBounds(devPts, 3);
qInDevSpace = devPts;
} else {
bounds.setBounds(&q[i], 3);
qInDevSpace = &q[i];
}
bounds.outset(SK_Scalar1, SK_Scalar1);
bounds.roundOut(&ibounds);
if (SkIRect::Intersects(devClipBounds, ibounds)) {
int subdiv = num_quad_subdivs(qInDevSpace);
GrAssert(subdiv >= -1);
if (-1 == subdiv) {
SkPoint* pts = lines->push_back_n(4);
// lines should always be in device coords
pts[0] = qInDevSpace[0];
pts[1] = qInDevSpace[1];
pts[2] = qInDevSpace[1];
pts[3] = qInDevSpace[2];
} else {
SkPoint* pts = quads->push_back_n(3);
// q is already in src space when there is no
// perspective and dev coords otherwise.
pts[0] = q[0 + i];
pts[1] = q[1 + i];
pts[2] = q[2 + i];
quadSubdivCnts->push_back() = subdiv;
totalQuadCount += 1 << subdiv;
}
}
}
}
break;
case kClose_PathCmd:
break;
case kEnd_PathCmd:
return totalQuadCount;
}
}
}
struct Vertex {
GrPoint fPos;
union {
struct {
SkScalar fA;
SkScalar fB;
SkScalar fC;
} fLine;
GrVec fQuadCoord;
struct {
SkScalar fBogus[4];
};
};
};
GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint));
void intersect_lines(const SkPoint& ptA, const SkVector& normA,
const SkPoint& ptB, const SkVector& normB,
SkPoint* result) {
SkScalar lineAW = -normA.dot(ptA);
SkScalar lineBW = -normB.dot(ptB);
SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
SkScalarMul(normA.fY, normB.fX);
wInv = SkScalarInvert(wInv);
result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY);
result->fX = SkScalarMul(result->fX, wInv);
result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW);
result->fY = SkScalarMul(result->fY, wInv);
}
void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) {
GrAssert(!toDevice == !toSrc);
// original quad is specified by tri a,b,c
SkPoint a = qpts[0];
SkPoint b = qpts[1];
SkPoint c = qpts[2];
// this should be in the src space, not dev coords, when we have perspective
GrPathUtils::QuadUVMatrix DevToUV(qpts);
if (toDevice) {
toDevice->mapPoints(&a, 1);
toDevice->mapPoints(&b, 1);
toDevice->mapPoints(&c, 1);
}
// make a new poly where we replace a and c by a 1-pixel wide edges orthog
// to edges ab and bc:
//
// before | after
// | b0
// b |
// |
// | a0 c0
// a c | a1 c1
//
// edges a0->b0 and b0->c0 are parallel to original edges a->b and b->c,
// respectively.
Vertex& a0 = verts[0];
Vertex& a1 = verts[1];
Vertex& b0 = verts[2];
Vertex& c0 = verts[3];
Vertex& c1 = verts[4];
SkVector ab = b;
ab -= a;
SkVector ac = c;
ac -= a;
SkVector cb = b;
cb -= c;
// We should have already handled degenerates
GrAssert(ab.length() > 0 && cb.length() > 0);
ab.normalize();
SkVector abN;
abN.setOrthog(ab, SkVector::kLeft_Side);
if (abN.dot(ac) > 0) {
abN.negate();
}
cb.normalize();
SkVector cbN;
cbN.setOrthog(cb, SkVector::kLeft_Side);
if (cbN.dot(ac) < 0) {
cbN.negate();
}
a0.fPos = a;
a0.fPos += abN;
a1.fPos = a;
a1.fPos -= abN;
c0.fPos = c;
c0.fPos += cbN;
c1.fPos = c;
c1.fPos -= cbN;
intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
if (toSrc) {
toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad);
}
DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts);
}
void add_quads(const SkPoint p[3],
int subdiv,
const SkMatrix* toDevice,
const SkMatrix* toSrc,
Vertex** vert) {
GrAssert(subdiv >= 0);
if (subdiv) {
SkPoint newP[5];
SkChopQuadAtHalf(p, newP);
add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert);
add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert);
} else {
bloat_quad(p, toDevice, toSrc, *vert);
*vert += kVertsPerQuad;
}
}
void add_line(const SkPoint p[2],
int rtHeight,
const SkMatrix* toSrc,
Vertex** vert) {
const SkPoint& a = p[0];
const SkPoint& b = p[1];
SkVector orthVec = b;
orthVec -= a;
if (orthVec.setLength(SK_Scalar1)) {
orthVec.setOrthog(orthVec);
SkScalar lineC = -(a.dot(orthVec));
for (int i = 0; i < kVertsPerLineSeg; ++i) {
(*vert)[i].fPos = (i < 2) ? a : b;
if (0 == i || 3 == i) {
(*vert)[i].fPos -= orthVec;
} else {
(*vert)[i].fPos += orthVec;
}
(*vert)[i].fLine.fA = orthVec.fX;
(*vert)[i].fLine.fB = orthVec.fY;
(*vert)[i].fLine.fC = lineC;
}
if (NULL != toSrc) {
toSrc->mapPointsWithStride(&(*vert)->fPos,
sizeof(Vertex),
kVertsPerLineSeg);
}
} else {
// just make it degenerate and likely offscreen
(*vert)[0].fPos.set(SK_ScalarMax, SK_ScalarMax);
(*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax);
(*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax);
(*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax);
}
*vert += kVertsPerLineSeg;
}
}
///////////////////////////////////////////////////////////////////////////////
/**
* The output of this effect is a hairline edge for quadratics.
* Quadratic specified by 0=u^2-v canonical coords. u and v are the first
* two components of the vertex attribute. Uses unsigned distance.
* Coverage is min(0, 1-distance). 3rd & 4th component unused.
* Requires shader derivative instruction support.
*/
class HairQuadEdgeEffect : public GrEffect {
public:
static GrEffectRef* Create() {
// we go through this so we only have one copy of each effect
static GrEffectRef* gHairQuadEdgeEffectRef =
CreateEffectRef(AutoEffectUnref(SkNEW(HairQuadEdgeEffect)));
static SkAutoTUnref<GrEffectRef> gUnref(gHairQuadEdgeEffectRef);
gHairQuadEdgeEffectRef->ref();
return gHairQuadEdgeEffectRef;
}
virtual ~HairQuadEdgeEffect() {}
static const char* Name() { return "HairQuadEdge"; }
virtual void getConstantColorComponents(GrColor* color,
uint32_t* validFlags) const SK_OVERRIDE {
*validFlags = 0;
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
return GrTBackendEffectFactory<HairQuadEdgeEffect>::getInstance();
}
class GLEffect : public GrGLEffect {
public:
GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
: INHERITED (factory) {}
virtual void emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) SK_OVERRIDE {
const char *vsName, *fsName;
const SkString* attrName =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
"\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
fsName, fsName);
builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
fsName);
builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
SkString modulate;
GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
return 0x0;
}
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
typedef GrGLEffect INHERITED;
};
private:
HairQuadEdgeEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
}
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
return true;
}
GR_DECLARE_EFFECT_TEST;
typedef GrEffect INHERITED;
};
GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect);
GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
// Doesn't work without derivative instructions.
return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;}
///////////////////////////////////////////////////////////////////////////////
/**
* The output of this effect is a 1-pixel wide line.
* Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component unused.
*/
class HairLineEdgeEffect : public GrEffect {
public:
static GrEffectRef* Create() {
// we go through this so we only have one copy of each effect
static GrEffectRef* gHairLineEdgeEffectRef =
CreateEffectRef(AutoEffectUnref(SkNEW(HairLineEdgeEffect)));
static SkAutoTUnref<GrEffectRef> gUnref(gHairLineEdgeEffectRef);
gHairLineEdgeEffectRef->ref();
return gHairLineEdgeEffectRef;
}
virtual ~HairLineEdgeEffect() {}
static const char* Name() { return "HairLineEdge"; }
virtual void getConstantColorComponents(GrColor* color,
uint32_t* validFlags) const SK_OVERRIDE {
*validFlags = 0;
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
return GrTBackendEffectFactory<HairLineEdgeEffect>::getInstance();
}
class GLEffect : public GrGLEffect {
public:
GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
: INHERITED (factory) {}
virtual void emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) SK_OVERRIDE {
const char *vsName, *fsName;
const SkString* attrName =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
builder->addVarying(kVec4f_GrSLType, "HairLineEdge", &vsName, &fsName);
builder->fsCodeAppendf("\t\tedgeAlpha = abs(dot(vec3(%s.xy,1), %s.xyz));\n",
builder->fragmentPosition(), fsName);
builder->fsCodeAppendf("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
SkString modulate;
GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
return 0x0;
}
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
typedef GrGLEffect INHERITED;
};
private:
HairLineEdgeEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
}
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
return true;
}
GR_DECLARE_EFFECT_TEST;
typedef GrEffect INHERITED;
};
GR_DEFINE_EFFECT_TEST(HairLineEdgeEffect);
GrEffectRef* HairLineEdgeEffect::TestCreate(SkMWCRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
return HairLineEdgeEffect::Create();
}
///////////////////////////////////////////////////////////////////////////////
bool GrAAHairLinePathRenderer::createGeom(
const SkPath& path,
GrDrawTarget* target,
int* lineCnt,
int* quadCnt,
GrDrawTarget::AutoReleaseGeometry* arg) {
GrDrawState* drawState = target->drawState();
int rtHeight = drawState->getRenderTarget()->height();
GrIRect devClipBounds;
target->getClip()->getConservativeBounds(drawState->getRenderTarget(),
&devClipBounds);
// position + edge
static const GrVertexAttrib kAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
SkMatrix viewM = drawState->getViewMatrix();
PREALLOC_PTARRAY(128) lines;
PREALLOC_PTARRAY(128) quads;
IntArray qSubdivs;
*quadCnt = generate_lines_and_quads(path, viewM, devClipBounds,
&lines, &quads, &qSubdivs);
*lineCnt = lines.count() / 2;
int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt;
target->drawState()->setVertexAttribs(kAttribs, SK_ARRAY_COUNT(kAttribs));
GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
if (!arg->set(target, vertCnt, 0)) {
return false;
}
Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices());
const SkMatrix* toDevice = NULL;
const SkMatrix* toSrc = NULL;
SkMatrix ivm;
if (viewM.hasPerspective()) {
if (viewM.invert(&ivm)) {
toDevice = &viewM;
toSrc = &ivm;
}
}
for (int i = 0; i < *lineCnt; ++i) {
add_line(&lines[2*i], rtHeight, toSrc, &verts);
}
int unsubdivQuadCnt = quads.count() / 3;
for (int i = 0; i < unsubdivQuadCnt; ++i) {
GrAssert(qSubdivs[i] >= 0);
add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts);
}
return true;
}
bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
const SkStrokeRec& stroke,
const GrDrawTarget* target,
bool antiAlias) const {
if (!stroke.isHairlineStyle() || !antiAlias) {
return false;
}
static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
SkPath::kQuad_SegmentMask;
if (!target->caps()->shaderDerivativeSupport() &&
(gReqDerivMask & path.getSegmentMasks())) {
return false;
}
return true;
}
bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
const SkStrokeRec&,
GrDrawTarget* target,
bool antiAlias) {
int lineCnt;
int quadCnt;
GrDrawTarget::AutoReleaseGeometry arg;
if (!this->createGeom(path,
target,
&lineCnt,
&quadCnt,
&arg)) {
return false;
}
GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
GrDrawState* drawState = target->drawState();
GrDrawState::AutoDeviceCoordDraw adcd;
// createGeom transforms the geometry to device space when the matrix does not have
// perspective.
if (!drawState->getViewMatrix().hasPerspective()) {
adcd.set(drawState);
if (!adcd.succeeded()) {
return false;
}
}
// TODO: See whether rendering lines as degenerate quads improves perf
// when we have a mix
enum {
// the edge effects share this stage with glyph rendering
// (kGlyphMaskStage in GrTextContext) && SW path rendering
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
static const int kEdgeAttrIndex = 1;
GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create();
GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create();
target->setIndexSourceToBuffer(fLinesIndexBuffer);
int lines = 0;
int nBufLines = fLinesIndexBuffer->maxQuads();
drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref();
while (lines < lineCnt) {
int n = GrMin(lineCnt - lines, nBufLines);
target->drawIndexed(kTriangles_GrPrimitiveType,
kVertsPerLineSeg*lines, // startV
0, // startI
kVertsPerLineSeg*n, // vCount
kIdxsPerLineSeg*n); // iCount
lines += n;
}
target->setIndexSourceToBuffer(fQuadsIndexBuffer);
int quads = 0;
drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref();
while (quads < quadCnt) {
int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType,
4 * lineCnt + kVertsPerQuad*quads, // startV
0, // startI
kVertsPerQuad*n, // vCount
kIdxsPerQuad*n); // iCount
quads += n;
}
return true;
}

Просмотреть файл

@ -1,273 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrAARectRenderer.h"
#include "GrRefCnt.h"
#include "GrGpu.h"
SK_DEFINE_INST_COUNT(GrAARectRenderer)
namespace {
static void aa_rect_attributes(bool useCoverage, const GrVertexAttrib** attribs, int* count) {
static const GrVertexAttrib kCoverageAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
};
static const GrVertexAttrib kColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
};
*attribs = useCoverage ? kCoverageAttribs : kColorAttribs;
*count = 2;
}
static void set_inset_fan(GrPoint* pts, size_t stride,
const GrRect& r, SkScalar dx, SkScalar dy) {
pts->setRectFan(r.fLeft + dx, r.fTop + dy,
r.fRight - dx, r.fBottom - dy, stride);
}
};
void GrAARectRenderer::reset() {
GrSafeSetNull(fAAFillRectIndexBuffer);
GrSafeSetNull(fAAStrokeRectIndexBuffer);
}
static const uint16_t gFillAARectIdx[] = {
0, 1, 5, 5, 4, 0,
1, 2, 6, 6, 5, 1,
2, 3, 7, 7, 6, 2,
3, 0, 4, 4, 7, 3,
4, 5, 6, 6, 7, 4,
};
static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx);
static const int kVertsPerAAFillRect = 8;
static const int kNumAAFillRectsInIndexBuffer = 256;
GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect *
sizeof(uint16_t) *
kNumAAFillRectsInIndexBuffer;
if (NULL == fAAFillRectIndexBuffer) {
fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
if (NULL != fAAFillRectIndexBuffer) {
uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock();
bool useTempData = (NULL == data);
if (useTempData) {
data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect);
}
for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) {
// Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around
// the inner rect (for AA) and 2 for the inner rect.
int baseIdx = i * kIndicesPerAAFillRect;
uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect);
for (int j = 0; j < kIndicesPerAAFillRect; ++j) {
data[baseIdx+j] = baseVert + gFillAARectIdx[j];
}
}
if (useTempData) {
if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
GrCrash("Can't get AA Fill Rect indices into buffer!");
}
SkDELETE_ARRAY(data);
} else {
fAAFillRectIndexBuffer->unlock();
}
}
}
return fAAFillRectIndexBuffer;
}
static const uint16_t gStrokeAARectIdx[] = {
0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
};
int GrAARectRenderer::aaStrokeRectIndexCount() {
return GR_ARRAY_COUNT(gStrokeAARectIdx);
}
GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) {
if (NULL == fAAStrokeRectIndexBuffer) {
fAAStrokeRectIndexBuffer =
gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false);
if (NULL != fAAStrokeRectIndexBuffer) {
#if GR_DEBUG
bool updated =
#endif
fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
sizeof(gStrokeAARectIdx));
GR_DEBUGASSERT(updated);
}
}
return fAAStrokeRectIndexBuffer;
}
void GrAARectRenderer::fillAARect(GrGpu* gpu,
GrDrawTarget* target,
const GrRect& devRect,
bool useVertexCoverage) {
GrDrawState* drawState = target->drawState();
const GrVertexAttrib* attribs;
int attribCount;
aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
drawState->setVertexAttribs(attribs, attribCount);
GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
return;
}
GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
if (NULL == indexBuffer) {
GrPrintf("Failed to create index buffer!\n");
return;
}
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize);
GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
set_inset_fan(fan1Pos, vsize, devRect, SK_ScalarHalf, SK_ScalarHalf);
verts += sizeof(GrPoint);
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
}
GrColor innerColor;
if (useVertexCoverage) {
innerColor = 0xffffffff;
} else {
innerColor = target->getDrawState().getColor();
}
verts += 4 * vsize;
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
}
target->setIndexSourceToBuffer(indexBuffer);
target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
kVertsPerAAFillRect,
kIndicesPerAAFillRect);
}
void GrAARectRenderer::strokeAARect(GrGpu* gpu,
GrDrawTarget* target,
const GrRect& devRect,
const GrVec& devStrokeSize,
bool useVertexCoverage) {
GrDrawState* drawState = target->drawState();
const SkScalar& dx = devStrokeSize.fX;
const SkScalar& dy = devStrokeSize.fY;
const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
SkScalar spare;
{
SkScalar w = devRect.width() - dx;
SkScalar h = devRect.height() - dy;
spare = GrMin(w, h);
}
if (spare <= 0) {
GrRect r(devRect);
r.inset(-rx, -ry);
this->fillAARect(gpu, target, r, useVertexCoverage);
return;
}
const GrVertexAttrib* attribs;
int attribCount;
aa_rect_attributes(useVertexCoverage, &attribs, &attribCount);
drawState->setVertexAttribs(attribs, attribCount);
GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
return;
}
GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu);
if (NULL == indexBuffer) {
GrPrintf("Failed to create index buffer!\n");
return;
}
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize);
// We create vertices for four nested rectangles. There are two ramps from 0 to full
// coverage, one on the exterior of the stroke and the other on the interior.
// The following pointers refer to the four rects, from outermost to innermost.
GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
set_inset_fan(fan0Pos, vsize, devRect,
-rx - SK_ScalarHalf, -ry - SK_ScalarHalf);
set_inset_fan(fan1Pos, vsize, devRect,
-rx + SK_ScalarHalf, -ry + SK_ScalarHalf);
set_inset_fan(fan2Pos, vsize, devRect,
rx - SK_ScalarHalf, ry - SK_ScalarHalf);
set_inset_fan(fan3Pos, vsize, devRect,
rx + SK_ScalarHalf, ry + SK_ScalarHalf);
// The outermost rect has 0 coverage
verts += sizeof(GrPoint);
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
}
// The inner two rects have full coverage
GrColor innerColor;
if (useVertexCoverage) {
innerColor = 0xffffffff;
} else {
innerColor = target->getDrawState().getColor();
}
verts += 4 * vsize;
for (int i = 0; i < 8; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
}
// The innermost rect has full coverage
verts += 8 * vsize;
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
}
target->setIndexSourceToBuffer(indexBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType,
0, 0, 16, aaStrokeRectIndexCount());
}

Просмотреть файл

@ -1,206 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrAtlas.h"
#include "GrContext.h"
#include "GrGpu.h"
#include "GrRectanizer.h"
#include "GrPlotMgr.h"
#if 0
#define GR_PLOT_WIDTH 8
#define GR_PLOT_HEIGHT 4
#define GR_ATLAS_WIDTH 256
#define GR_ATLAS_HEIGHT 256
#define GR_ATLAS_TEXTURE_WIDTH (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
#define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
#else
#define GR_ATLAS_TEXTURE_WIDTH 1024
#define GR_ATLAS_TEXTURE_HEIGHT 2048
#define GR_ATLAS_WIDTH 341
#define GR_ATLAS_HEIGHT 341
#define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH)
#define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT)
#endif
///////////////////////////////////////////////////////////////////////////////
#define BORDER 1
#if GR_DEBUG
static int gCounter;
#endif
GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
fAtlasMgr = mgr; // just a pointer, not an owner
fNext = NULL;
fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
fPlot.set(plotX, plotY);
fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
GR_ATLAS_HEIGHT - BORDER);
fMaskFormat = format;
#if GR_DEBUG
// GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
gCounter += 1;
#endif
}
GrAtlas::~GrAtlas() {
fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
delete fRects;
#if GR_DEBUG
--gCounter;
// GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
#endif
}
static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
loc->fX += plot.fX * GR_ATLAS_WIDTH;
loc->fY += plot.fY * GR_ATLAS_HEIGHT;
}
static uint8_t* zerofill(uint8_t* ptr, int count) {
while (--count >= 0) {
*ptr++ = 0;
}
return ptr;
}
bool GrAtlas::addSubImage(int width, int height, const void* image,
GrIPoint16* loc) {
if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
return false;
}
SkAutoSMalloc<1024> storage;
int dstW = width + 2*BORDER;
int dstH = height + 2*BORDER;
if (BORDER) {
const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
const size_t dstRB = dstW * bpp;
uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB);
Gr_bzero(dst, dstRB); // zero top row
dst += dstRB;
for (int y = 0; y < height; y++) {
dst = zerofill(dst, bpp); // zero left edge
memcpy(dst, image, width * bpp);
dst += width * bpp;
dst = zerofill(dst, bpp); // zero right edge
image = (const void*)((const char*)image + width * bpp);
}
Gr_bzero(dst, dstRB); // zero bottom row
image = storage.get();
}
adjustForPlot(loc, fPlot);
GrContext* context = fTexture->getContext();
// We pass the flag that does not force a flush. We assume our caller is
// smart and hasn't referenced the part of the texture we're about to update
// since the last flush.
context->writeTexturePixels(fTexture,
loc->fX, loc->fY, dstW, dstH,
fTexture->config(), image, 0,
GrContext::kDontFlush_PixelOpsFlag);
// now tell the caller to skip the top/left BORDER
loc->fX += BORDER;
loc->fY += BORDER;
return true;
}
///////////////////////////////////////////////////////////////////////////////
GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) {
fGpu = gpu;
gpu->ref();
Gr_bzero(fTexture, sizeof(fTexture));
fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT));
}
GrAtlasMgr::~GrAtlasMgr() {
for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) {
GrSafeUnref(fTexture[i]);
}
delete fPlotMgr;
fGpu->unref();
}
static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
switch (format) {
case kA8_GrMaskFormat:
return kAlpha_8_GrPixelConfig;
case kA565_GrMaskFormat:
return kRGB_565_GrPixelConfig;
case kA888_GrMaskFormat:
return kSkia8888_GrPixelConfig;
default:
GrAssert(!"unknown maskformat");
}
return kUnknown_GrPixelConfig;
}
GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
int width, int height, const void* image,
GrMaskFormat format,
GrIPoint16* loc) {
GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
if (atlas && atlas->addSubImage(width, height, image, loc)) {
return atlas;
}
// If the above fails, then either we have no starting atlas, or the current
// one is full. Either way we need to allocate a new atlas
GrIPoint16 plot;
if (!fPlotMgr->newPlot(&plot)) {
return NULL;
}
GrAssert(0 == kA8_GrMaskFormat);
GrAssert(1 == kA565_GrMaskFormat);
if (NULL == fTexture[format]) {
// TODO: Update this to use the cache rather than directly creating a texture.
GrTextureDesc desc;
desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
desc.fWidth = GR_ATLAS_TEXTURE_WIDTH;
desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT;
desc.fConfig = maskformat2pixelconfig(format);
fTexture[format] = fGpu->createTexture(desc, NULL, 0);
if (NULL == fTexture[format]) {
return NULL;
}
}
GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, format));
if (!newAtlas->addSubImage(width, height, image, loc)) {
delete newAtlas;
return NULL;
}
newAtlas->fNext = atlas;
return newAtlas;
}
void GrAtlasMgr::freePlot(int x, int y) {
GrAssert(fPlotMgr->isBusy(x, y));
fPlotMgr->freePlot(x, y);
}

Просмотреть файл

@ -1,81 +0,0 @@
/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrAtlas_DEFINED
#define GrAtlas_DEFINED
#include "GrPoint.h"
#include "GrTexture.h"
class GrGpu;
class GrRectanizer;
class GrAtlasMgr;
class GrAtlas {
public:
GrAtlas(GrAtlasMgr*, int plotX, int plotY, GrMaskFormat);
int getPlotX() const { return fPlot.fX; }
int getPlotY() const { return fPlot.fY; }
GrMaskFormat getMaskFormat() const { return fMaskFormat; }
GrTexture* texture() const { return fTexture; }
bool addSubImage(int width, int height, const void*, GrIPoint16*);
static void FreeLList(GrAtlas* atlas) {
while (atlas) {
GrAtlas* next = atlas->fNext;
delete atlas;
atlas = next;
}
}
// testing
GrAtlas* nextAtlas() const { return fNext; }
private:
~GrAtlas(); // does not try to delete the fNext field
GrAtlas* fNext;
GrTexture* fTexture;
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
GrIPoint16 fPlot;
GrMaskFormat fMaskFormat;
friend class GrAtlasMgr;
};
class GrPlotMgr;
class GrAtlasMgr {
public:
GrAtlasMgr(GrGpu*);
~GrAtlasMgr();
GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*,
GrMaskFormat, GrIPoint16*);
GrTexture* getTexture(GrMaskFormat format) const {
GrAssert((unsigned)format < kCount_GrMaskFormats);
return fTexture[format];
}
// to be called by ~GrAtlas()
void freePlot(int x, int y);
private:
GrGpu* fGpu;
GrTexture* fTexture[kCount_GrMaskFormats];
GrPlotMgr* fPlotMgr;
};
#endif

Просмотреть файл

@ -1,110 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrBinHashKey_DEFINED
#define GrBinHashKey_DEFINED
#include "GrTypes.h"
/**
* Hash function class that can take a data chunk of any predetermined length. The hash function
* used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html).
*
* Keys are computed from ENTRY objects. ENTRY must be fully ordered by a member:
* int compare(const GrTBinHashKey<ENTRY, ..>& k);
* which returns negative if the ENTRY < k, 0 if it equals k, and positive if k < the ENTRY.
* Additionally, ENTRY must be flattenable into the key using setKeyData.
*
* This class satisfies the requirements to be a key for a GrTHashTable.
*/
template<typename ENTRY, size_t KEY_SIZE>
class GrTBinHashKey {
public:
enum { kKeySize = KEY_SIZE };
GrTBinHashKey() {
this->reset();
}
GrTBinHashKey(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) {
*this = other;
}
GrTBinHashKey<ENTRY, KEY_SIZE>& operator=(const GrTBinHashKey<ENTRY, KEY_SIZE>& other) {
memcpy(this, &other, sizeof(*this));
return *this;
}
~GrTBinHashKey() {
}
void reset() {
fHash = 0;
#if GR_DEBUG
fIsValid = false;
#endif
}
void setKeyData(const uint32_t* SK_RESTRICT data) {
GrAssert(GrIsALIGN4(KEY_SIZE));
memcpy(&fData, data, KEY_SIZE);
uint32_t hash = 0;
size_t len = KEY_SIZE;
while (len >= 4) {
hash += *data++;
hash += (fHash << 10);
hash ^= (hash >> 6);
len -= 4;
}
hash += (fHash << 3);
hash ^= (fHash >> 11);
hash += (fHash << 15);
#if GR_DEBUG
fIsValid = true;
#endif
fHash = hash;
}
int compare(const GrTBinHashKey<ENTRY, KEY_SIZE>& key) const {
GrAssert(fIsValid && key.fIsValid);
return memcmp(fData, key.fData, KEY_SIZE);
}
static bool EQ(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) {
GrAssert(key.fIsValid);
return 0 == entry.compare(key);
}
static bool LT(const ENTRY& entry, const GrTBinHashKey<ENTRY, KEY_SIZE>& key) {
GrAssert(key.fIsValid);
return entry.compare(key) < 0;
}
uint32_t getHash() const {
GrAssert(fIsValid);
return fHash;
}
const uint8_t* getData() const {
GrAssert(fIsValid);
return fData;
}
private:
uint32_t fHash;
uint8_t fData[KEY_SIZE]; // Buffer for key storage
#if GR_DEBUG
public:
bool fIsValid;
#endif
};
#endif

Просмотреть файл

@ -1,10 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGeometryBuffer.h"
SK_DEFINE_INST_COUNT(GrGeometryBuffer)

Просмотреть файл

@ -1,524 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrOvalRenderer.h"
#include "GrEffect.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
#include "GrTBackendEffectFactory.h"
#include "GrDrawState.h"
#include "GrDrawTarget.h"
#include "SkStrokeRec.h"
SK_DEFINE_INST_COUNT(GrOvalRenderer)
namespace {
struct CircleVertex {
GrPoint fPos;
GrPoint fCenter;
SkScalar fOuterRadius;
SkScalar fInnerRadius;
};
struct EllipseVertex {
GrPoint fPos;
GrPoint fCenter;
SkScalar fOuterXRadius;
SkScalar fOuterXYRatio;
SkScalar fInnerXRadius;
SkScalar fInnerXYRatio;
};
inline bool circle_stays_circle(const SkMatrix& m) {
return m.isSimilarity();
}
}
///////////////////////////////////////////////////////////////////////////////
/**
* The output of this effect is a modulation of the input color and coverage for a circle,
* specified as center_x, center_y, x_radius, inner radius and outer radius in window space
* (y-down).
*/
class CircleEdgeEffect : public GrEffect {
public:
static GrEffectRef* Create(bool stroke) {
// we go through this so we only have one copy of each effect (stroked/filled)
static SkAutoTUnref<GrEffectRef> gCircleStrokeEdgeEffectRef(
CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (true)))));
static SkAutoTUnref<GrEffectRef> gCircleFillEdgeEffectRef(
CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEffect, (false)))));
if (stroke) {
gCircleStrokeEdgeEffectRef.get()->ref();
return gCircleStrokeEdgeEffectRef;
} else {
gCircleFillEdgeEffectRef.get()->ref();
return gCircleFillEdgeEffectRef;
}
}
virtual void getConstantColorComponents(GrColor* color,
uint32_t* validFlags) const SK_OVERRIDE {
*validFlags = 0;
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance();
}
virtual ~CircleEdgeEffect() {}
static const char* Name() { return "CircleEdge"; }
inline bool isStroked() const { return fStroke; }
class GLEffect : public GrGLEffect {
public:
GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
: INHERITED (factory) {}
virtual void emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) SK_OVERRIDE {
const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>();
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
const SkString* attrName =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n",
builder->fragmentPosition(), fsName);
builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
if (circleEffect.isStroked()) {
builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName);
builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n");
}
SkString modulate;
GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>();
return circleEffect.isStroked() ? 0x1 : 0x0;
}
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
typedef GrGLEffect INHERITED;
};
private:
CircleEdgeEffect(bool stroke) : GrEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
fStroke = stroke;
}
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other);
return cee.fStroke == fStroke;
}
bool fStroke;
GR_DECLARE_EFFECT_TEST;
typedef GrEffect INHERITED;
};
GR_DEFINE_EFFECT_TEST(CircleEdgeEffect);
GrEffectRef* CircleEdgeEffect::TestCreate(SkMWCRandom* random,
GrContext* context,
const GrDrawTargetCaps&,
GrTexture* textures[]) {
return CircleEdgeEffect::Create(random->nextBool());
}
///////////////////////////////////////////////////////////////////////////////
/**
* The output of this effect is a modulation of the input color and coverage for an axis-aligned
* ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in window space (y-down).
*/
class EllipseEdgeEffect : public GrEffect {
public:
static GrEffectRef* Create(bool stroke) {
// we go through this so we only have one copy of each effect (stroked/filled)
static SkAutoTUnref<GrEffectRef> gEllipseStrokeEdgeEffectRef(
CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEffect, (true)))));
static SkAutoTUnref<GrEffectRef> gEllipseFillEdgeEffectRef(
CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEffect, (false)))));
if (stroke) {
gEllipseStrokeEdgeEffectRef.get()->ref();
return gEllipseStrokeEdgeEffectRef;
} else {
gEllipseFillEdgeEffectRef.get()->ref();
return gEllipseFillEdgeEffectRef;
}
}
virtual void getConstantColorComponents(GrColor* color,
uint32_t* validFlags) const SK_OVERRIDE {
*validFlags = 0;
}
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance();
}
virtual ~EllipseEdgeEffect() {}
static const char* Name() { return "EllipseEdge"; }
inline bool isStroked() const { return fStroke; }
class GLEffect : public GrGLEffect {
public:
GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
: INHERITED (factory) {}
virtual void emitCode(GrGLShaderBuilder* builder,
const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) SK_OVERRIDE {
const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>();
const char *vsCenterName, *fsCenterName;
const char *vsEdgeName, *fsEdgeName;
builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName);
const SkString* attr0Name =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_str());
builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fsEdgeName);
const SkString* attr1Name =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str());
// translate to origin
builder->fsCodeAppendf("\tvec2 outerOffset = (%s.xy - %s.xy);\n",
builder->fragmentPosition(), fsCenterName);
builder->fsCodeAppend("\tvec2 innerOffset = outerOffset;\n");
// scale y by xRadius/yRadius
builder->fsCodeAppendf("\touterOffset.y *= %s.y;\n", fsEdgeName);
builder->fsCodeAppend("\tfloat dOuter = length(outerOffset);\n");
// compare outer lengths against xOuterRadius
builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n",
fsEdgeName);
if (ellipseEffect.isStroked()) {
builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName);
builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n");
// compare inner lengths against xInnerRadius
builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.z, 0.0, 1.0);\n",
fsEdgeName);
builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n");
}
SkString modulate;
GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>();
return ellipseEffect.isStroked() ? 0x1 : 0x0;
}
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {
}
private:
typedef GrGLEffect INHERITED;
};
private:
EllipseEdgeEffect(bool stroke) : GrEffect() {
this->addVertexAttrib(kVec2f_GrSLType);
this->addVertexAttrib(kVec4f_GrSLType);
fStroke = stroke;
}
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other);
return eee.fStroke == fStroke;
}
bool fStroke;
GR_DECLARE_EFFECT_TEST;
typedef GrEffect INHERITED;
};
GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect);
GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random,
GrContext* context,
const GrDrawTargetCaps&,
GrTexture* textures[]) {
return EllipseEdgeEffect::Create(random->nextBool());
}
///////////////////////////////////////////////////////////////////////////////
bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, const GrPaint& paint,
const GrRect& oval, const SkStrokeRec& stroke)
{
if (!paint.isAntiAlias()) {
return false;
}
const SkMatrix& vm = context->getMatrix();
// we can draw circles
if (SkScalarNearlyEqual(oval.width(), oval.height())
&& circle_stays_circle(vm)) {
drawCircle(target, paint, oval, stroke);
// and axis-aligned ellipses only
} else if (vm.rectStaysRect()) {
drawEllipse(target, paint, oval, stroke);
} else {
return false;
}
return true;
}
void GrOvalRenderer::drawCircle(GrDrawTarget* target,
const GrPaint& paint,
const GrRect& circle,
const SkStrokeRec& stroke)
{
GrDrawState* drawState = target->drawState();
const SkMatrix& vm = drawState->getViewMatrix();
GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY());
vm.mapPoints(&center, 1);
SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width()));
SkScalar strokeWidth = vm.mapRadius(stroke.getWidth());
GrDrawState::AutoDeviceCoordDraw adcd(drawState);
if (!adcd.succeeded()) {
return;
}
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
return;
}
CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
SkStrokeRec::Style style = stroke.getStyle();
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
enum {
// the edge effects share this stage with glyph rendering
// (kGlyphMaskStage in GrTextContext) && SW path rendering
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
static const int kCircleEdgeAttrIndex = 1;
drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref();
SkScalar innerRadius = 0.0f;
SkScalar outerRadius = radius;
SkScalar halfWidth = 0;
if (style != SkStrokeRec::kFill_Style) {
if (SkScalarNearlyZero(strokeWidth)) {
halfWidth = SK_ScalarHalf;
} else {
halfWidth = SkScalarHalf(strokeWidth);
}
outerRadius += halfWidth;
if (isStroked) {
innerRadius = SkMaxScalar(0, radius - halfWidth);
}
}
// The radii are outset for two reasons. First, it allows the shader to simply perform
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
// verts of the bounding box that is rendered and the outset ensures the box will cover all
// pixels partially covered by the circle.
outerRadius += SK_ScalarHalf;
innerRadius -= SK_ScalarHalf;
for (int i = 0; i < 4; ++i) {
verts[i].fCenter = center;
verts[i].fOuterRadius = outerRadius;
verts[i].fInnerRadius = innerRadius;
}
SkRect bounds = SkRect::MakeLTRB(
center.fX - outerRadius,
center.fY - outerRadius,
center.fX + outerRadius,
center.fY + outerRadius
);
verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom);
verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
}
void GrOvalRenderer::drawEllipse(GrDrawTarget* target,
const GrPaint& paint,
const GrRect& ellipse,
const SkStrokeRec& stroke)
{
GrDrawState* drawState = target->drawState();
#ifdef SK_DEBUG
{
// we should have checked for this previously
bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
SkASSERT(paint.isAntiAlias() && isAxisAlignedEllipse);
}
#endif
const SkMatrix& vm = drawState->getViewMatrix();
GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
vm.mapPoints(&center, 1);
SkRect xformedRect;
vm.mapRect(&xformedRect, ellipse);
GrDrawState::AutoDeviceCoordDraw adcd(drawState);
if (!adcd.succeeded()) {
return;
}
// position + edge
static const GrVertexAttrib kVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
{kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding}
};
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
if (!geo.succeeded()) {
GrPrintf("Failed to get space for vertices!\n");
return;
}
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
SkStrokeRec::Style style = stroke.getStyle();
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
enum {
// the edge effects share this stage with glyph rendering
// (kGlyphMaskStage in GrTextContext) && SW path rendering
// (kPathMaskStage in GrSWMaskHelper)
kEdgeEffectStage = GrPaint::kTotalStages,
};
GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
static const int kEllipseCenterAttrIndex = 1;
static const int kEllipseEdgeAttrIndex = 2;
drawState->setEffect(kEdgeEffectStage, effect,
kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
SkScalar xRadius = SkScalarHalf(xformedRect.width());
SkScalar yRadius = SkScalarHalf(xformedRect.height());
SkScalar innerXRadius = 0.0f;
SkScalar innerRatio = 1.0f;
if (SkStrokeRec::kFill_Style != style) {
SkScalar strokeWidth = stroke.getWidth();
// do (potentially) anisotropic mapping
SkVector scaledStroke;
scaledStroke.set(strokeWidth, strokeWidth);
vm.mapVectors(&scaledStroke, 1);
if (SkScalarNearlyZero(scaledStroke.length())) {
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
} else {
scaledStroke.scale(0.5f);
}
// this is legit only if scale & translation (which should be the case at the moment)
if (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style) {
SkScalar innerYRadius = SkMaxScalar(0, yRadius - scaledStroke.fY);
if (innerYRadius > SK_ScalarNearlyZero) {
innerXRadius = SkMaxScalar(0, xRadius - scaledStroke.fX);
innerRatio = innerXRadius/innerYRadius;
}
}
xRadius += scaledStroke.fX;
yRadius += scaledStroke.fY;
}
SkScalar outerRatio = SkScalarDiv(xRadius, yRadius);
for (int i = 0; i < 4; ++i) {
verts[i].fCenter = center;
verts[i].fOuterXRadius = xRadius + 0.5f;
verts[i].fOuterXYRatio = outerRatio;
verts[i].fInnerXRadius = innerXRadius - 0.5f;
verts[i].fInnerXYRatio = innerRatio;
}
SkScalar L = -xRadius;
SkScalar R = +xRadius;
SkScalar T = -yRadius;
SkScalar B = +yRadius;
// We've extended the outer x radius out half a pixel to antialias.
// Expand the drawn rect here so all the pixels will be captured.
L += center.fX - SK_ScalarHalf;
R += center.fX + SK_ScalarHalf;
T += center.fY - SK_ScalarHalf;
B += center.fY + SK_ScalarHalf;
verts[0].fPos = SkPoint::Make(L, T);
verts[1].fPos = SkPoint::Make(R, T);
verts[2].fPos = SkPoint::Make(L, B);
verts[3].fPos = SkPoint::Make(R, B);
target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
}

Просмотреть файл

@ -1,10 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrPath.h"
SK_DEFINE_INST_COUNT(GrPath)

Просмотреть файл

@ -1,30 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrPath_DEFINED
#define GrPath_DEFINED
#include "GrResource.h"
#include "GrRect.h"
class GrPath : public GrResource {
public:
SK_DECLARE_INST_COUNT(GrPath);
GrPath(GrGpu* gpu, bool isWrapped) : INHERITED(gpu, isWrapped) {}
const GrRect& getBounds() const { return fBounds; }
protected:
GrRect fBounds;
private:
typedef GrResource INHERITED;
};
#endif

Просмотреть файл

@ -1,14 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrPathRenderer.h"
SK_DEFINE_INST_COUNT(GrPathRenderer)
GrPathRenderer::GrPathRenderer() {
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше