Browse Source

Merge branch 'PixelArray2'

v1.x
Tj Holowaychuk 15 years ago
parent
commit
2f85eb7c5c
  1. 8
      lib/canvas.js
  2. 34
      lib/context2d.js
  3. 29
      lib/pixelarray.js
  4. 3
      src/Canvas.cc
  5. 1
      src/Canvas.h
  6. 2
      src/CanvasGradient.cc
  7. 2
      src/CanvasGradient.h
  8. 3
      src/CanvasRenderingContext2d.cc
  9. 2
      src/Image.h
  10. 61
      src/ImageData.cc
  11. 27
      src/ImageData.h
  12. 130
      src/PixelArray.cc
  13. 32
      src/PixelArray.h
  14. 4
      src/init.cc

8
lib/canvas.js

@ -13,6 +13,7 @@ var canvas = require('../build/default/canvas')
, Canvas = canvas.Canvas
, Image = canvas.Image
, cairoVersion = canvas.cairoVersion
, PixelArray = Canvas.PixelArray
, Context2d = require('./context2d')
, PNGStream = require('./pngstream')
, fs = require('fs');
@ -41,6 +42,7 @@ exports.cairoVersion = cairoVersion;
exports.Context2d = Context2d;
exports.PNGStream = PNGStream;
exports.PixelArray = PixelArray;
exports.Image = Image;
/**
@ -55,6 +57,12 @@ require('./context2d');
require('./image');
/**
* PixelArray implementation.
*/
require('./pixelarray');
/**
* Inspect canvas.
*

34
lib/context2d.js

@ -12,6 +12,8 @@
var canvas = require('../build/default/canvas')
, Context2d = canvas.CanvasRenderingContext2d
, CanvasGradient = canvas.CanvasGradient
, ImageData = canvas.ImageData
, PixelArray = canvas.CanvasPixelArray
, colors = require('./colors');
/**
@ -448,4 +450,34 @@ Context2d.prototype.__defineSetter__('textAlign', function(val){
Context2d.prototype.__defineGetter__('textAlign', function(){
return this.lastTextAlignment || 'start';
});
});
/**
* Get `ImageData` with the given rect.
*
* @param {Number} x
* @param {Number} y
* @param {Number} width
* @param {Number} height
* @return {ImageData}
* @api public
*/
Context2d.prototype.getImageData = function(x, y, width, height){
var arr = new PixelArray(this.canvas, x, y, width, height);
return new ImageData(arr);
};
/**
* Create `ImageData` with the given dimensions.
*
* @param {Number} width
* @param {Number} height
* @return {ImageData}
* @api public
*/
Context2d.prototype.createImageData = function(width, height){
var arr = new PixelArray(width, height);
return new ImageData(arr);
};

29
lib/pixelarray.js

@ -0,0 +1,29 @@
/*!
* Canvas - PixelArray
* Copyright (c) 2010 LearnBoost <tj@learnboost.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Canvas = require('../build/default/canvas')
, PixelArray = Canvas.CanvasPixelArray;
/**
* Custom inspect.
*/
PixelArray.prototype.inspect = function(){
var buf = '[PixelArray ';
for (var i = 0, len = this.length; i < len; i += 4) {
buf += '\n ' + i + ': rgba('
+ this[i + 0] + ','
+ this[i + 1] + ','
+ this[i + 2] + ','
+ this[i + 3] + ')';
}
return buf + '\n]';
};

3
src/Canvas.cc

@ -12,9 +12,6 @@
#include <node_buffer.h>
#include <node_version.h>
using namespace v8;
using namespace node;
/*
* Buffer data pointer access.
*/

1
src/Canvas.h

@ -14,6 +14,7 @@
#include <cairo.h>
using namespace v8;
using namespace node;
/*
* Maxmimum states per context.

2
src/CanvasGradient.cc

@ -9,7 +9,7 @@
#include "CanvasGradient.h"
/*
* Initialie CanvasGradient.
* Initialize CanvasGradient.
*/
void

2
src/CanvasGradient.h

@ -10,8 +10,6 @@
#include "Canvas.h"
using namespace v8;
class Gradient: public node::ObjectWrap {
public:
static void Initialize(Handle<Object> target);

3
src/CanvasRenderingContext2d.cc

@ -13,9 +13,6 @@
#include "CanvasRenderingContext2d.h"
#include "CanvasGradient.h"
using namespace v8;
using namespace node;
/*
* Set RGBA.
*/

2
src/Image.h

@ -10,8 +10,6 @@
#include "Canvas.h"
using namespace v8;
class Image: public node::ObjectWrap {
public:
char *filename;

61
src/ImageData.cc

@ -0,0 +1,61 @@
//
// ImageData.cc
//
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
//
#include "ImageData.h"
/*
* Initialize ImageData.
*/
void
ImageData::Initialize(Handle<Object> target) {
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(ImageData::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(String::NewSymbol("ImageData"));
// Prototype
Local<ObjectTemplate> proto = t->PrototypeTemplate();
proto->SetAccessor(String::NewSymbol("width"), GetWidth);
proto->SetAccessor(String::NewSymbol("height"), GetHeight);
target->Set(String::NewSymbol("ImageData"), t->GetFunction());
}
/*
* Initialize a new ImageData object.
*/
Handle<Value>
ImageData::New(const Arguments &args) {
HandleScope scope;
// TODO: arg assertions
PixelArray *arr = ObjectWrap::Unwrap<PixelArray>(args[0]->ToObject());
ImageData *imageData = new ImageData(arr);
args.This()->Set(String::NewSymbol("data"), args[0]);
imageData->Wrap(args.This());
return args.This();
}
/*
* Get width.
*/
Handle<Value>
ImageData::GetWidth(Local<String> prop, const AccessorInfo &info) {
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This());
return Number::New(imageData->pixelArray()->width());
}
/*
* Get height.
*/
Handle<Value>
ImageData::GetHeight(Local<String> prop, const AccessorInfo &info) {
ImageData *imageData = ObjectWrap::Unwrap<ImageData>(info.This());
return Number::New(imageData->pixelArray()->height());
}

27
src/ImageData.h

@ -0,0 +1,27 @@
//
// ImageData.h
//
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
//
#ifndef __NODE_IMAGE_DATA_H__
#define __NODE_IMAGE_DATA_H__
#include "Canvas.h"
#include "PixelArray.h"
#include <stdlib.h>
class ImageData: public node::ObjectWrap {
public:
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> GetWidth(Local<String> prop, const AccessorInfo &info);
static Handle<Value> GetHeight(Local<String> prop, const AccessorInfo &info);
inline PixelArray *pixelArray(){ return _arr; }
ImageData(PixelArray *arr): _arr(arr) {}
private:
PixelArray *_arr;
};
#endif

130
src/PixelArray.cc

@ -0,0 +1,130 @@
//
// PixelArray.cc
//
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
//
#include "PixelArray.h"
#include <stdlib.h>
#include <string.h>
/*
* Initialize PixelArray.
*/
void
PixelArray::Initialize(Handle<Object> target) {
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(PixelArray::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(String::NewSymbol("CanvasPixelArray"));
Local<ObjectTemplate> proto = t->InstanceTemplate();
proto->SetAccessor(String::NewSymbol("length"), GetLength);
target->Set(String::NewSymbol("CanvasPixelArray"), t->GetFunction());
}
/*
* Initialize a new PixelArray.
*/
Handle<Value>
PixelArray::New(const Arguments &args) {
HandleScope scope;
PixelArray *arr;
// TODO: arg handling
switch (args.Length()) {
// width, height
case 2:
arr = new PixelArray(
args[0]->Int32Value()
, args[1]->Int32Value());
break;
// canvas, x, y, width, height
case 5: {
Canvas *canvas = ObjectWrap::Unwrap<Canvas>(args[0]->ToObject());
arr = new PixelArray(
canvas
, args[1]->Int32Value()
, args[2]->Int32Value()
, args[3]->Int32Value()
, args[4]->Int32Value());
}
break;
default:
return ThrowException(Exception::TypeError(String::New("invalid arguments")));
}
// Let v8 handle accessors (and clamping)
args.This()->SetIndexedPropertiesToPixelData(
arr->data()
, arr->length());
arr->Wrap(args.This());
return args.This();
}
/*
* Get length.
*/
Handle<Value>
PixelArray::GetLength(Local<String> prop, const AccessorInfo &info) {
return Number::New(info.This()->GetIndexedPropertiesPixelDataLength());
}
/*
* Initialize a new PixelArray copying data
* from the canvas surface using the given rect.
*/
PixelArray::PixelArray(Canvas *canvas, int sx, int sy, int width, int height):
_width(width), _height(height) {
// Alloc space for our new data
uint8_t *dst = alloc();
uint8_t *src = canvas->data();
int s = stride();
// Normalize data (argb -> rgba)
for (int y = 0; y < height; ++y) {
uint32_t *row = (uint32_t *)(src + s * y);
for (int x = 0; x < width; ++x) {
int bx = x * 4;
uint32_t *pixel = row + x;
// premultiplied
uint8_t a = *pixel >> 24;
dst[bx + 3] = a;
dst[bx + 0] = (*pixel >> 16) * 255 / a;
dst[bx + 1] = (*pixel >> 8) * 255 / a;
dst[bx + 2] = *pixel * 255 / a;
}
dst += s;
}
}
/*
* Initialize an empty PixelArray with the given dimensions.
*/
PixelArray::PixelArray(int width, int height):
_width(width), _height(height) {
alloc();
}
/*
* Allocate / zero data buffer.
*/
uint8_t *
PixelArray::alloc() {
_data = (uint8_t *) malloc(length());
memset(_data, 0, length());
return _data;
}
PixelArray::~PixelArray() {
free(_data);
}

32
src/PixelArray.h

@ -0,0 +1,32 @@
//
// PixelArray.h
//
// Copyright (c) 2010 LearnBoost <tj@learnboost.com>
//
#ifndef __NODE_PIXEL_ARRAY_H__
#define __NODE_PIXEL_ARRAY_H__
#include "Canvas.h"
class PixelArray: public node::ObjectWrap {
public:
static void Initialize(Handle<Object> target);
static Handle<Value> New(const Arguments &args);
static Handle<Value> GetLength(Local<String> prop, const AccessorInfo &info);
inline int length(){ return _width * _height * 4; }
inline int width(){ return _width; }
inline int height(){ return _height; }
inline int stride(){ return _width * 4; }
inline uint8_t *data(){ return _data; }
PixelArray(Canvas *canvas, int x, int y, int width, int height);
PixelArray(int width, int height);
~PixelArray();
private:
uint8_t *alloc();
uint8_t *_data;
int _width, _height;
};
#endif

4
src/init.cc

@ -7,6 +7,8 @@
#include "Canvas.h"
#include "Image.h"
#include "ImageData.h"
#include "PixelArray.h"
#include "CanvasGradient.h"
#include "CanvasRenderingContext2d.h"
@ -15,6 +17,8 @@ init (Handle<Object> target) {
HandleScope scope;
Canvas::Initialize(target);
Image::Initialize(target);
ImageData::Initialize(target);
PixelArray::Initialize(target);
Context2d::Initialize(target);
Gradient::Initialize(target);
target->Set(String::New("cairoVersion"), String::New(cairo_version_string()));

Loading…
Cancel
Save