# HG changeset patch # User Thinker K.F. Li # Date 1276075809 -28800 # Node ID dcd7adb2c0fc0b35c3c7e6fb9f8195f48c71d078 # Parent aa2b388fba4eaee78b77254e4157aff5fb386cf8# Parent 13b15b7a463bbf70591aba2206fc14819494aafc Merge from Android_Skia diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/native_test/Android.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/native_test/Android.mk Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := native_test +LOCAL_STATIC_LIBRARIES := libmbfly +LOCAL_SHARED_LIBRARIES := libsgl +LOCAL_C_INCLUDES += $(call include-path-for,corecg) \ + $(TARGET_OUT_HEADERS)/libmbfly +LOCAL_SRC_FILES := native_test.cpp + +include $(BUILD_EXECUTABLE) + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/native_test/native_test.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/native_test/native_test.cpp Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,44 @@ +#include +#include + +extern "C" { +#include +}; + +void native_test(void) { + mbe_t *mbe1, *mbe2; + SkBitmap *bmap1, *bmap2; + redraw_man_t _rdman; + redraw_man_t *rdman = &_rdman; + coord_t *root; + shape_t *shape; + paint_t *paint; + + bmap1 = new SkBitmap(); + bmap1->setConfig(SkBitmap::kARGB_8888_Config, 300, 300); + mbe1 = mbe_create((mbe_surface_t *)bmap1); + bmap2 = new SkBitmap(); + bmap2->setConfig(SkBitmap::kARGB_8888_Config, 300, 300); + mbe2 = mbe_create((mbe_surface_t *)bmap2); + + redraw_man_init(rdman, mbe1, mbe2); + root = rdman_get_root(rdman); + shape = rdman_shape_path_new(rdman, "M 100 100 L 100 150 L 150 150 z"); + paint = rdman_paint_color_new(rdman, 1, 0, 0, 1); + rdman_paint_stroke(rdman, paint, shape); + rdman_add_shape(rdman, shape, root); + + rdman_shape_changed(rdman, shape); + rdman_paint_changed(rdman, paint); + + rdman_redraw_all(rdman); + + rdman_paint_free(rdman, paint); + rdman_shape_free(rdman, shape); + redraw_man_destroy(rdman); +} + +int main(int argc, const char *argv[]) { + native_test(); + return 0; +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/AndroidManifest.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/AndroidManifest.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/build.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/build.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,20 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked in Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source-folder' for the location of your java source folder and +# 'out-folder' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + +# The name of your application package as defined in the manifest. +# Used by the 'uninstall' rule. +application-package=org.madbutterfly.android.examples.testpath diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/build.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/default.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/default.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-4 diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/local.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/local.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk-location=/home/thinker/progm/Android/out/host/freebsd-x86/sdk/android-sdk_eng.thinker_freebsd-x86 diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/res/layout/main.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/res/layout/main.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,13 @@ + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/res/values/strings.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/res/values/strings.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,4 @@ + + + testpath + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/src/org/madbutterfly/android/examples/testpath/testpath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/src/org/madbutterfly/android/examples/testpath/testpath.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,59 @@ +package org.madbutterfly.android.examples.testpath; + +import android.app.Activity; +import android.view.SurfaceHolder; +import android.content.Context; +import android.os.Bundle; +import android.graphics.Canvas; +import android.util.Log; +import org.madbutterfly.MBView; +import org.madbutterfly.redraw_man; +import org.madbutterfly.coord; +import org.madbutterfly.shape; +import org.madbutterfly.paint; + +public class testpath extends Activity implements SurfaceHolder.Callback +{ + MBView main_view; + String TAG = "testpath"; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + SurfaceHolder holder; + + // setContentView(R.layout.main); + main_view = new MBView(this); + holder = main_view.getHolder(); + holder.addCallback(this); + setContentView(main_view); + } + + public void surfaceChanged(SurfaceHolder holder, int format, + int w, int h) { + } + + public void surfaceCreated(SurfaceHolder holder) { + redraw_man rdman; + shape path; + coord _coord; + paint pnt; + + Log.v(TAG, "surfaceCreated enter"); + rdman = main_view.get_rdman(); + path = rdman.shape_path_new("M 100 100 L 150 100 L 150 150 z"); + path.set_stroke_width(2); + _coord = rdman.get_root(); + _coord.add_shape(path); + pnt = rdman.paint_color_new(1, 0, 1, 1); + pnt.stroke(path); + Log.v(TAG, "surfaceCreated before redraw"); + rdman.redraw(); + Log.v(TAG, "surfaceCreated leave"); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/AndroidManifest.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/AndroidManifest.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,21 @@ + + + + + + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/build.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/build.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,20 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked in Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source-folder' for the location of your java source folder and +# 'out-folder' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + +# The name of your application package as defined in the manifest. +# Used by the 'uninstall' rule. +application-package=org.madbutterfly.android.examples.testpath diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/build.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/default.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/default.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-4 diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/local.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/local.properties Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked in Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk-location=/home/thinker/progm/Android/out/host/freebsd-x86/sdk/android-sdk_eng.thinker_freebsd-x86 diff -r aa2b388fba4e -r dcd7adb2c0fc Android/examples/testpath/tests/src/org/madbutterfly/android/examples/testpath/testpathTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/examples/testpath/tests/src/org/madbutterfly/android/examples/testpath/testpathTest.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,21 @@ +package org.madbutterfly.android.examples.testpath; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * This is a simple framework for a test of an Application. See + * {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on + * how to write and extend Application tests. + *

+ * To run this test, you can type: + * adb shell am instrument -w \ + * -e class org.madbutterfly.android.examples.testpath.testpathTest \ + * org.madbutterfly.android.examples.testpath.tests/android.test.InstrumentationTestRunner + */ +public class testpathTest extends ActivityInstrumentationTestCase2 { + + public testpathTest() { + super("org.madbutterfly.android.examples.testpath", testpath.class); + } + +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/Android.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/Android.mk Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,33 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := mbfly-java +LOCAL_MODULE_CLASS := JAVA_LIBRARIES + +LOCAL_SRC_FILES := \ + org/madbutterfly/_jni.java \ + org/madbutterfly/MBView.java \ + org/madbutterfly/redraw_man.java \ + org/madbutterfly/coord.java \ + org/madbutterfly/shape.java \ + org/madbutterfly/paint.java \ + org/madbutterfly/InvalidStateException.java + +include $(BUILD_JAVA_LIBRARY) + +######################## +include $(CLEAR_VARS) + +LOCAL_MODULE := mbfly-permissions.xml + +LOCAL_MODULE_TAGS := user + +LOCAL_MODULE_CLASS := ETC + +# This will install the file in /system/etc/permissions +# +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/mbfly-permissions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/mbfly-permissions.xml Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,6 @@ + + + + + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/InvalidStateException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/InvalidStateException.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,12 @@ +package org.madbutterfly; + +import java.lang.Exception; + +public class InvalidStateException extends Exception { + public InvalidStateException() { + super(); + } + public InvalidStateException(String msg) { + super(msg); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/MBView.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/MBView.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,77 @@ +package org.madbutterfly; + +import android.view.SurfaceView; +import android.view.SurfaceHolder; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.Xfermode; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; + +public class MBView extends SurfaceView { + redraw_man rdman; + Canvas cr, backend; + Bitmap cr_bmap, backend_bmap; + Paint copy_pnt; + int w, h; + + public MBView(Context context) { + super(context); + Paint paint; + Xfermode mode; + + rdman = null; + cr = null; + backend = null; + + mode = new PorterDuffXfermode(PorterDuff.Mode.SRC); + copy_pnt = new Paint(); + copy_pnt.setXfermode(mode); + w = 100; + h = 100; + } + + public redraw_man get_rdman() { + if(rdman != null) + return rdman; + + w = getWidth(); + h = getHeight(); + + cr_bmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + cr = new Canvas(cr_bmap); + backend_bmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + backend = new Canvas(backend_bmap); + + rdman = new redraw_man(cr, backend, this); + + return rdman; + } + + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + this.w = w; + this.h = h; + + if(rdman == null) { + get_rdman(); + return; + } + + cr_bmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + cr.setBitmap(cr_bmap); + backend_bmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + backend.setBitmap(backend_bmap); + } + + public void redraw() { + SurfaceHolder holder; + Canvas canvas; + + holder = getHolder(); + canvas = holder.lockCanvas(); + canvas.drawBitmap(backend_bmap, 0, 0, copy_pnt); + holder.unlockCanvasAndPost(canvas); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/_jni.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/_jni.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,48 @@ +package org.madbutterfly; +import android.graphics.Canvas; + +class _jni { + native static int redraw_man_new(Canvas cr, Canvas backend); + native static void redraw_man_free(int rdman); + native static int rdman_add_shape(int rdman, int shape, int coord); + native static int rdman_get_root(int rdman); + native static int rdman_redraw_all(int rdman); + native static int rdman_redraw_changed(int rdman); + native static int rdman_redraw_area(int rdman, float x, float y, + float w, float h); + native static void rdman_paint_fill(int rdman, int paint, int shape); + native static void rdman_paint_stroke(int rdman, int paint, int shape); + + /* coord_t */ + native static int rdman_coord_new(int rdman, int parent); + native static void rdman_coord_free(int rdman, int coord); + native static void rdman_coord_subtree_free(int rdman, int coord); + native static void rdman_coord_changed(int rdman, int coord); + + /* shape_t */ + native static void rdman_shape_changed(int rdman, int shape); + native static void rdman_shape_free(int rdman, int shape); + native static int rdman_shape_path_new(int rdman, String data); + native static void sh_set_stroke_width(int shape, float w); + + /* paint_t */ + native static int rdman_paint_color_new(int rdman, float r, float g, + float b, float a); + native static int rdman_paint_free(int rdman, int paint); + native static void paint_color_set(int paint, float r, float g, + float b, float a); + native static float[] paint_color_get(int paint); + native static int rdman_paint_linear_new(int rdman, + float x1, float y1, + float x2, float y2); + native static int paint_linear_stops(int paint, int n_stops, int stops); + native static int rdman_paint_radial_new(int rdman, float cx, float cy, + float r); + native static int paint_radial_stops(int paint, int n_stops, int stops); + native static int paint_create_stops(float stops[][]); + native static int paint_free_stops(int stops); + + static { + System.loadLibrary("mbfly-jni"); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/coord.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/coord.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,34 @@ +package org.madbutterfly; + +import java.util.ArrayList; + +public class coord { + protected int addr; + redraw_man rdman; + public ArrayList children; + public ArrayList members; + + public coord(redraw_man rdman, int addr) { + this.addr = addr; + this.rdman = rdman; + children = new ArrayList(); + members = new ArrayList(); + } + + protected void invalid() { + addr = 0; + } + + protected void finalize() { + if(addr != 0) + _jni.rdman_coord_free(rdman._rdman_addr, addr); + } + + public void add_shape(shape member) { + _jni.rdman_add_shape(rdman._rdman_addr, member.addr, addr); + members.add(member); + member.parent = this; + _jni.rdman_coord_changed(rdman._rdman_addr, addr); + _jni.rdman_shape_changed(rdman._rdman_addr, member.addr); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/paint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/paint.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,70 @@ +package org.madbutterfly; + +import java.util.ArrayList; + +public class paint { + protected int addr; + redraw_man rdman; + ArrayList members; + + public paint(redraw_man rdman, int addr) { + this.addr = addr; + this.rdman = rdman; + members = new ArrayList(); + } + + protected void invalid() { + addr = 0; + } + + protected void finalize() { + if(addr != 0) + _jni.rdman_paint_free(rdman._rdman_addr, addr); + } + + public void stroke(shape sh) { + no_stroke(sh); + + if(sh.fill != this) + members.add(sh); + + sh.stroke = this; + + _jni.rdman_paint_stroke(rdman._rdman_addr, addr, sh.addr); + } + + public void fill(shape sh) { + no_fill(sh); + + if(sh.stroke != this) + members.add(sh); + + sh.fill = this; + + _jni.rdman_paint_fill(rdman._rdman_addr, addr, sh.addr); + } + + public boolean is_empty() { + return members.size() == 0; + } + + public static void no_stroke(shape sh) { + int i; + + if(sh.stroke != null && sh.stroke != sh.fill) { + i = sh.stroke.members.indexOf(sh); + sh.stroke.members.remove(i); + } + sh.stroke = null; + } + + public static void no_fill(shape sh) { + int i; + + if(sh.fill != null && sh.stroke != sh.fill) { + i = sh.stroke.members.indexOf(sh); + sh.stroke.members.remove(i); + } + sh.fill = null; + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/redraw_man.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/redraw_man.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,108 @@ +package org.madbutterfly; + +import android.graphics.Canvas; +import android.view.SurfaceHolder; +import java.util.ArrayList; + +public class redraw_man { + Canvas _cr, _backend; + int _rdman_addr; // address of redraw_man_t + coord root; + ArrayList paints; + MBView _view; + + public redraw_man(Canvas cr, Canvas backend, MBView view) { + int addr; + + _view = view; + _cr = cr; + _backend = backend; + + _rdman_addr = _jni.redraw_man_new(cr, backend); + addr = _jni.rdman_get_root(_rdman_addr); + root = new coord(this, addr); + + paints = new ArrayList(); + } + + static void _invalid_subtree(coord subtree) { + int i, sz; + coord child; + shape member; + + subtree.invalid(); + + sz = subtree.members.size(); + for(i = 0; i < sz; i ++) { + member = (shape)subtree.members.get(i); + member.invalid(); + } + + sz = subtree.children.size(); + for(i = 0; i < sz; i++) { + child = (coord)subtree.children.get(i); + _invalid_subtree(child); + } + } + + protected void finalize() { + int i, sz; + paint pnt; + + _invalid_subtree(root); + + /* invalid paints */ + sz = paints.size(); + for(i = 0; i < sz; i++) { + pnt = (paint)paints.get(i); + pnt.invalid(); + } + + _jni.redraw_man_free(_rdman_addr); + } + + public coord get_root() { + return root; + } + + public coord coord_new(coord parent) { + int addr; + coord child; + + addr = _jni.rdman_coord_new(_rdman_addr, parent.addr); + child = new coord(this, addr); + parent.children.add(child); + + return child; + } + + public void coord_free(coord obj) { + obj.finalize(); + obj.invalid(); + } + + public shape shape_path_new(String pathdata) { + int addr; + shape new_shape; + + addr = _jni.rdman_shape_path_new(_rdman_addr, pathdata); + new_shape = new shape(this, addr); + + return new_shape; + } + + public paint paint_color_new(float r, float g, float b, float a) { + int addr; + paint pnt; + + addr = _jni.rdman_paint_color_new(_rdman_addr, r, g, b, a); + pnt = new paint(this, addr); + + return pnt; + } + + public void redraw() { + _jni.rdman_redraw_all(_rdman_addr); + _view.redraw(); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/java/org/madbutterfly/shape.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/java/org/madbutterfly/shape.java Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,28 @@ +package org.madbutterfly; + +public class shape { + protected int addr; + redraw_man rdman; + protected coord parent; + protected paint stroke, fill; + + public shape(redraw_man rdman, int addr) { + this.addr = addr; + this.rdman = rdman; + this.parent = null; + stroke = fill = null; + } + + protected void invalid() { + addr = 0; + } + + protected void finalize() { + if(addr != 0) + _jni.rdman_shape_free(rdman._rdman_addr, addr); + } + + public void set_stroke_width(float w) { + _jni.sh_set_stroke_width(addr, w); + } +} diff -r aa2b388fba4e -r dcd7adb2c0fc Android/jni/Android.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/jni/Android.mk Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,15 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libmbfly-jni +LOCAL_SRC_FILES := mbfly.cpp +LOCAL_SHARED_LIBRARIES := libcorecg libsgl libnativehelper libcutils +LOCAL_STATIC_LIBRARIES := libmbfly +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libmbfly \ + $(call include-path-for,corecg) \ + $(call include-path-for,libnativehelper)/nativehelper + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) diff -r aa2b388fba4e -r dcd7adb2c0fc Android/jni/mbfly.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/jni/mbfly.cpp Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,226 @@ +#include + +#define DECL_C extern "C" { +#define END_C } + +DECL_C + +#include +#include +#include + +#define ASSERT(x) + + +extern mbe_t *skia_mbe_create_by_canvas(SkCanvas *canvas); + +jint Java_org_madbutterfly__1jni_redraw_1man_1new(JNIEnv *env, + jobject cls, + jobject cr, + jobject backend) { + jclass canvas_cls; + jfieldID fid; + SkCanvas *_cr, *_backend; + redraw_man_t *rdman; + mbe_t *mbe1, *mbe2; + + canvas_cls = env->GetObjectClass(cr); + fid = env->GetFieldID(canvas_cls, "mNativeCanvas", "I"); + _cr = (SkCanvas *)env->GetIntField(cr, fid); + canvas_cls = env->GetObjectClass(backend); + fid = env->GetFieldID(canvas_cls, "mNativeCanvas", "I"); + _backend = (SkCanvas *)env->GetIntField(backend, fid); + + mbe1 = skia_mbe_create_by_canvas(_cr); + mbe2 = skia_mbe_create_by_canvas(_backend); + ASSERT(mbe1 != NULL && mbe2 != NULL); + + rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); + ASSERT(rdman != NULL); + redraw_man_init(rdman, mbe1, mbe2); + + return (jint)rdman; +} + +void Java_org_madbutterfly__1jni_redraw_1man_1free(JNIEnv *env, + jobject cls, + jint rdman) { + redraw_man_destroy((redraw_man_t *)rdman); + free((redraw_man_t *)rdman); +} + +jint Java_org_madbutterfly__1jni_rdman_1add_1shape(JNIEnv *env, + jobject cls, + jint rdman, + jint shape, + jint coord) { + jint r; + + r = rdman_add_shape((redraw_man_t *)rdman, + (shape_t *)shape, + (coord_t *)coord); + return r; +} + +jint Java_org_madbutterfly__1jni_rdman_1get_1root(JNIEnv *env, + jobject cls, + jint rdman) { + jint root; + + root = (jint)rdman_get_root((redraw_man_t *)rdman); + return root; +} + +jint Java_org_madbutterfly__1jni_rdman_1redraw_1all(JNIEnv *env, + jobject cls, + jint rdman) { + jint r; + + r = rdman_redraw_all((redraw_man_t *)rdman); + return r; +} + +void Java_org_madbutterfly__1jni_rdman_1paint_1fill(JNIEnv *env, + jobject cls, + jint rdman, + jint paint, + jint shape) { + rdman_paint_fill((redraw_man_t *)rdman, + (paint_t *)paint, + (shape_t *)shape); +} + +void Java_org_madbutterfly__1jni_rdman_1paint_1stroke(JNIEnv *env, + jobject cls, + jint rdman, + jint paint, + jint shape) { + rdman_paint_stroke((redraw_man_t *)rdman, + (paint_t *)paint, + (shape_t *)shape); +} + +jint Java_org_madbutterfly__1jni_rdman_1coord_1new(JNIEnv *env, + jobject cls, + jint rdman, + jint parent) { + jint coord; + + coord = (jint)rdman_coord_new((redraw_man_t *)rdman, + (coord_t *)parent); + return coord; +} + +void Java_org_madbutterfly__1jni_rdman_1coord_1free(JNIEnv *env, + jobject cls, + jint rdman, + jint coord) { + rdman_coord_free((redraw_man_t *)rdman, + (coord_t *)coord); +} + +void Java_org_madbutterfly__1jni_rdman_1coord_1subtree_1free(JNIEnv *env, + jobject cls, + jint rdman, + jint coord) { + rdman_coord_subtree_free((redraw_man_t *)rdman, + (coord_t *)coord); +} + +void Java_org_madbutterfly__1jni_rdman_1coord_1changed(JNIEnv *env, + jobject cls, + jint rdman, + jint coord) { + rdman_coord_changed((redraw_man_t *)rdman, + (coord_t *)coord); +} + +void Java_org_madbutterfly__1jni_rdman_1shape_1changed(JNIEnv *env, + jobject cls, + jint rdman, + jint shape) { + rdman_shape_changed((redraw_man_t *)rdman, + (shape_t *)shape); +} + +void Java_org_madbutterfly__1jni_rdman_1shape_1free(JNIEnv *env, + jobject cls, + jint rdman, + jint shape) { + rdman_shape_free((redraw_man_t *)rdman, + (shape_t *)shape); +} + +jint Java_org_madbutterfly__1jni_rdman_1shape_1path_1new(JNIEnv *env, + jobject cls, + jint rdman, + jstring data) { + const char *str; + jint shape; + + str = env->GetStringUTFChars(data, NULL); + shape = (jint)rdman_shape_path_new((redraw_man_t *)rdman, (char *)str); + env->ReleaseStringUTFChars(data, str); + + return shape; +} + +void Java_org_madbutterfly__1jni_sh_1set_1stroke_1width(JNIEnv *env, + jobject cls, + jint shape, + jfloat w) { + sh_set_stroke_width((shape_t *)shape, w); +} + +jint Java_org_madbutterfly__1jni_rdman_1paint_1color_1new(JNIEnv *env, + jobject cls, + jint rdman, + jfloat r, jfloat g, + jfloat b, jfloat a) { + jint paint; + + paint = (jint)rdman_paint_color_new((redraw_man_t *)rdman, + r, g, b, a); + return paint; +} + +jint Java_org_madbutterfly__1jni_rdman_1paint_1free(JNIEnv *env, + jobject cls, + jint rdman, + jint paint) { + jint r; + + r = rdman_paint_free((redraw_man_t *)rdman, + (paint_t *)paint); + return r; +} + +void Java_org_madbutterfly__1jni_paint_1color_1set(JNIEnv *env, + jobject cls, + jint paint, + jfloat r, jfloat g, + jfloat b, jfloat a) { + paint_color_set((paint_t *)paint, r, g, b, a); +} + +jfloatArray Java_org_madbutterfly__1jni_paint_1color_1get(JNIEnv *env, + jobject cls, + jint paint) { + co_comp_t r, g, b, a; + jfloat color[4]; + jfloatArray result; + + paint_color_get((paint_t *)paint, &r, &g, &b, &a); + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + + result = env->NewFloatArray(4); + env->SetFloatArrayRegion(result, 0, 4, color); + + return result; +} + +END_C + diff -r aa2b388fba4e -r dcd7adb2c0fc Android/mb/Android.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/mb/Android.mk Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,63 @@ +LOCAL_PATH:= $(call my-dir) +MB_LOCAL_PATH := $(LOCAL_PATH) +include $(CLEAR_VARS) + +LOCAL_MODULE := MadButterfly +LOCAL_CONFIGURE := $(LOCAL_PATH)/../../configure +LOCAL_CONFIGURE_ARGS := --enable-skia --config-cache +LOCAL_CFLAGS := -I$(shell pwd)/$(call include-path-for,corecg) \ + -I$(shell pwd)/$(call include-path-for,corecg)/../effects/ \ + -I$(shell pwd)/$(call include-path-for,frameworks-base) \ + -I$(shell pwd)/$(call include-path-for,system-core) +# LOCAL_CFLAGS += -O0 -g +LOCAL_CONFIGURE_CACHE := config.cache + +include $(BUILD_AUTOCONF) + +MB_INTERMEDIATES:=$(strip $(intermediates)) + +$(LOCAL_BUILT_MODULE): $(MB_INTERMEDIATES)/build/config.cache + +$(MB_INTERMEDIATES)/build/config.cache: + $(hide) mkdir -p $(MB_INTERMEDIATES)/build/; + cp $(strip $(MB_LOCAL_PATH))/config.cache $(MB_INTERMEDIATES)/build/ + +include $(CLEAR_VARS) + +LOCAL_MODULE:= libmbfly +LOCAL_MODULE_SUFFIX:= .a +LOCAL_SRC_FILES:= $(MB_INTERMEDIATES)/build/src/.libs/libmbfly.a +LOCAL_MODULE_CLASS:= STATIC_LIBRARIES +LOCAL_REQUIRED_MODULES:= MadButterfly +LOCAL_COPY_HEADERS:= \ + ../../include/mb_prop.h \ + ../../include/mb_graph_engine.h \ + ../../include/mb_redraw_man.h \ + ../../include/mb.h \ + ../../include/mb_graph_engine_cairo.h \ + ../../include/mb_shapes.h \ + ../../include/mb_X_supp.h \ + ../../include/mb_graph_engine_skia.h \ + ../../include/mb_so.h \ + ../../include/mb_af.h \ + ../../include/mb_img_ldr.h \ + ../../include/mb_timer.h \ + ../../include/mb_ani_menu.h \ + ../../include/mb_obj.h \ + ../../include/mb_tools.h \ + ../../include/mb_animate.h \ + ../../include/mb_observer.h \ + ../../include/mb_types.h \ + ../../include/mb_basic_types.h \ + ../../include/mb_paint.h \ + ../../include/mbbutton.h +LOCAL_COPY_HEADERS_TO:= libmbfly + +include $(BUILD_DUMMY) + +MB_LOCAL_COPY_HEADERS_TO:= $(LOCAL_COPY_HEADERS_TO) +$(eval $(call copy-one-header,$(MB_INTERMEDIATES)/build/include/mb_config.h,$(TARGET_OUT_HEADERS)/$(MB_LOCAL_COPY_HEADERS_TO)/mb_config.h)) +all_copied_headers: $(TARGET_OUT_HEADERS)/$(MB_LOCAL_COPY_HEADERS_TO)/mb_config.h + +$(MB_INTERMEDIATES)/build/src/.libs/libmbfly.a: MadButterfly +$(MB_INTERMEDIATES)/build/include/mb_config.h: MadButterfly diff -r aa2b388fba4e -r dcd7adb2c0fc Android/mb/config.cache --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Android/mb/config.cache Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,121 @@ +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +ac_cv_build=${ac_cv_build=i386-unknown-freebsd9.0} +ac_cv_c_compiler_gnu=${ac_cv_c_compiler_gnu=yes} +ac_cv_c_const=${ac_cv_c_const=yes} +ac_cv_c_uint32_t=${ac_cv_c_uint32_t=yes} +ac_cv_c_uint64_t=${ac_cv_c_uint64_t=yes} +ac_cv_cxx_compiler_gnu=${ac_cv_cxx_compiler_gnu=yes} +ac_cv_env_CCC_set='' +ac_cv_env_CCC_value='' +ac_cv_env_CPPFLAGS_set='' +ac_cv_env_CPPFLAGS_value='' +ac_cv_env_CPP_set='' +ac_cv_env_CPP_value='' +ac_cv_env_CXXCPP_set='' +ac_cv_env_CXXCPP_value='' +ac_cv_env_LDFLAGS_set=set +ac_cv_env_LDFLAGS_value='' +ac_cv_env_LIBS_set='' +ac_cv_env_LIBS_value='' +ac_cv_env_PKG_CONFIG_set='' +ac_cv_env_PKG_CONFIG_value='' +ac_cv_env_XMKMF_set='' +ac_cv_env_XMKMF_value='' +ac_cv_env_build_alias_set='' +ac_cv_env_build_alias_value='' +ac_cv_env_cairo_CFLAGS_set='' +ac_cv_env_cairo_CFLAGS_value='' +ac_cv_env_cairo_LIBS_set='' +ac_cv_env_cairo_LIBS_value='' +ac_cv_env_host_alias_set=set +ac_cv_env_host_alias_value=i386-unknown-freebsd +ac_cv_env_pangocairo_CFLAGS_set='' +ac_cv_env_pangocairo_CFLAGS_value='' +ac_cv_env_pangocairo_LIBS_set='' +ac_cv_env_pangocairo_LIBS_value='' +ac_cv_env_target_alias_set=set +ac_cv_env_target_alias_value=arm-unknown-linux +ac_cv_func_gettimeofday=${ac_cv_func_gettimeofday=yes} +ac_cv_func_malloc_0_nonnull=${ac_cv_func_malloc_0_nonnull=yes} +ac_cv_func_memset=${ac_cv_func_memset=yes} +ac_cv_func_realloc_0_nonnull=${ac_cv_func_realloc_0_nonnull=yes} +ac_cv_func_select=${ac_cv_func_select=yes} +ac_cv_func_select_args=${ac_cv_func_select_args='int,fd_set *,struct timeval *'} +ac_cv_func_sqrt=${ac_cv_func_sqrt=no} +ac_cv_func_strdup=${ac_cv_func_strdup=yes} +ac_cv_have_x=${ac_cv_have_x='have_x=yes ac_x_includes='\''/usr/local/include'\'' ac_x_libraries='\''/usr/local/lib'\'} +ac_cv_header_dlfcn_h=${ac_cv_header_dlfcn_h=yes} +ac_cv_header_inttypes_h=${ac_cv_header_inttypes_h=yes} +ac_cv_header_memory_h=${ac_cv_header_memory_h=yes} +ac_cv_header_stdc=${ac_cv_header_stdc=no} +ac_cv_header_stdint_h=${ac_cv_header_stdint_h=yes} +ac_cv_header_stdlib_h=${ac_cv_header_stdlib_h=yes} +ac_cv_header_string_h=${ac_cv_header_string_h=yes} +ac_cv_header_strings_h=${ac_cv_header_strings_h=yes} +ac_cv_header_sys_select_h=${ac_cv_header_sys_select_h=yes} +ac_cv_header_sys_socket_h=${ac_cv_header_sys_socket_h=yes} +ac_cv_header_sys_stat_h=${ac_cv_header_sys_stat_h=yes} +ac_cv_header_sys_time_h=${ac_cv_header_sys_time_h=yes} +ac_cv_header_sys_types_h=${ac_cv_header_sys_types_h=yes} +ac_cv_header_time=${ac_cv_header_time=yes} +ac_cv_header_unistd_h=${ac_cv_header_unistd_h=yes} +ac_cv_host=${ac_cv_host=i386-unknown-freebsd} +ac_cv_objext=${ac_cv_objext=o} +ac_cv_path_EGREP=${ac_cv_path_EGREP='/usr/bin/grep -E'} +ac_cv_path_FGREP=${ac_cv_path_FGREP='/usr/bin/grep -F'} +ac_cv_path_GREP=${ac_cv_path_GREP=/usr/bin/grep} +ac_cv_path_SED=${ac_cv_path_SED=/usr/bin/sed} +ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'} +ac_cv_prog_AWK=${ac_cv_prog_AWK=gawk} +ac_cv_prog_CC=${ac_cv_prog_CC=/home/thinker/progm/Android/prebuilt/freebsd-x86/toolchain/arm-eabi-4.4.0/bin/arm-unknown-eabi-gcc} +ac_cv_prog_CPP=${ac_cv_prog_CPP='/home/thinker/progm/Android/prebuilt/freebsd-x86/toolchain/arm-eabi-4.4.0/bin/arm-unknown-eabi-gcc -E'} +ac_cv_prog_CXXCPP=${ac_cv_prog_CXXCPP='/home/thinker/progm/Android/prebuilt/freebsd-x86/toolchain/arm-eabi-4.4.0/bin/arm-unknown-eabi-g++ -E'} +ac_cv_prog_STRIP=${ac_cv_prog_STRIP=strip} +ac_cv_prog_ac_ct_AR=${ac_cv_prog_ac_ct_AR=ar} +ac_cv_prog_ac_ct_DUMPBIN=${ac_cv_prog_ac_ct_DUMPBIN='link -dump -symbols'} +ac_cv_prog_ac_ct_OBJDUMP=${ac_cv_prog_ac_ct_OBJDUMP=objdump} +ac_cv_prog_ac_ct_RANLIB=${ac_cv_prog_ac_ct_RANLIB=ranlib} +ac_cv_prog_ac_ct_STRIP=${ac_cv_prog_ac_ct_STRIP=strip} +ac_cv_prog_cc_c89=${ac_cv_prog_cc_c89=''} +ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes} +ac_cv_prog_cxx_g=${ac_cv_prog_cxx_g=yes} +ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set=yes} +ac_cv_struct_tm=${ac_cv_struct_tm=time.h} +ac_cv_type_size_t=${ac_cv_type_size_t=yes} +am_cv_CC_dependencies_compiler_type=${am_cv_CC_dependencies_compiler_type=gcc3} +am_cv_CXX_dependencies_compiler_type=${am_cv_CXX_dependencies_compiler_type=gcc3} +lt_cv_deplibs_check_method=${lt_cv_deplibs_check_method=pass_all} +lt_cv_file_magic_cmd=${lt_cv_file_magic_cmd='$MAGIC_CMD'} +lt_cv_file_magic_test_file=${lt_cv_file_magic_test_file=''} +lt_cv_ld_reload_flag=${lt_cv_ld_reload_flag=-r} +lt_cv_nm_interface=${lt_cv_nm_interface='BSD nm'} +lt_cv_objdir=${lt_cv_objdir=.libs} +lt_cv_path_LD=${lt_cv_path_LD=/usr/home/thinker/progm/Android/prebuilt/freebsd-x86/toolchain/arm-eabi-4.4.0/arm-unknown-eabi/bin/ld} +lt_cv_path_LDCXX=${lt_cv_path_LDCXX=/usr/home/thinker/progm/Android/prebuilt/freebsd-x86/toolchain/arm-eabi-4.4.0/arm-unknown-eabi/bin/ld} +lt_cv_path_NM=${lt_cv_path_NM=no} +lt_cv_prog_compiler_c_o=${lt_cv_prog_compiler_c_o=yes} +lt_cv_prog_compiler_c_o_CXX=${lt_cv_prog_compiler_c_o_CXX=yes} +lt_cv_prog_compiler_pic_works=${lt_cv_prog_compiler_pic_works=yes} +lt_cv_prog_compiler_pic_works_CXX=${lt_cv_prog_compiler_pic_works_CXX=yes} +lt_cv_prog_compiler_rtti_exceptions=${lt_cv_prog_compiler_rtti_exceptions=no} +lt_cv_prog_compiler_static_works=${lt_cv_prog_compiler_static_works=no} +lt_cv_prog_compiler_static_works_CXX=${lt_cv_prog_compiler_static_works_CXX=no} +lt_cv_prog_gnu_ld=${lt_cv_prog_gnu_ld=yes} +lt_cv_prog_gnu_ldcxx=${lt_cv_prog_gnu_ldcxx=yes} +lt_cv_sys_global_symbol_pipe=${lt_cv_sys_global_symbol_pipe=''} +test "${lt_cv_sys_global_symbol_to_c_name_address+set}" = set || lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\) $/ {\"\1\", (void *) 0},/p'\'' -e '\''s/^[BCDEGRST]* \([^ ]*\) \([^ ]*\)$/ {"\2", (void *) \&\2},/p'\' +test "${lt_cv_sys_global_symbol_to_c_name_address_lib_prefix+set}" = set || lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \([^ ]*\) $/ {\"\1\", (void *) 0},/p'\'' -e '\''s/^[BCDEGRST]* \([^ ]*\) \(lib[^ ]*\)$/ {"\2", (void *) \&\2},/p'\'' -e '\''s/^[BCDEGRST]* \([^ ]*\) \([^ ]*\)$/ {"lib\2", (void *) \&\2},/p'\' +lt_cv_sys_global_symbol_to_cdecl=${lt_cv_sys_global_symbol_to_cdecl=''} +lt_cv_sys_max_cmd_len=${lt_cv_sys_max_cmd_len=196608} diff -r aa2b388fba4e -r dcd7adb2c0fc Makefile.am --- a/Makefile.am Sun Nov 08 00:37:29 2009 +0800 +++ b/Makefile.am Wed Jun 09 17:30:09 2010 +0800 @@ -2,3 +2,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libmbfly.pc EXTRA_DIST = libmbfly.pc.in Doxyfile README.h + +if NODEJS + SUBDIRS += nodejs +endif diff -r aa2b388fba4e -r dcd7adb2c0fc configure.ac --- a/configure.ac Sun Nov 08 00:37:29 2009 +0800 +++ b/configure.ac Wed Jun 09 17:30:09 2010 +0800 @@ -4,18 +4,15 @@ AC_PREREQ(2.61) AC_INIT([MadButterfly],[0.0],[http://www.assembla.com/spaces/MadButterfly]) AC_CONFIG_SRCDIR([README.h]) -AC_CONFIG_HEADER([config.h]) +AC_CONFIG_HEADER([config.h include/mb_config.h]) AM_INIT_AUTOMAKE([foreign]) # Checks for programs. AC_PROG_CC +AC_PROG_CXX LT_INIT AC_PROG_LIBTOOL -# Checks for libraries. -PKG_CHECK_MODULES([cairo], [cairo >= 1.6], , AC_MSG_ERROR([cairo >= 1.6 not found])) -PKG_CHECK_MODULES([pangocairo], [pangocairo >= 1.0], , AC_MSG_ERROR([pangocairo >= 1.0 not found])) - # Checks for header files. AC_PATH_X AC_HEADER_STDC @@ -36,7 +33,7 @@ AC_CHECK_FUNCS([gettimeofday memset select sqrt strdup]) AC_ARG_ENABLE([testcase], - [--enable-testcase Enable testcase], + [ --enable-testcase Enable testcase], [case "${enableval}" in yes) testcase=true ;; no) testcase=false ;; @@ -45,19 +42,15 @@ AM_CONDITIONAL([TESTCASE], [test x$testcase = xtrue]) AC_ARG_ENABLE([sh_text], - [--disable-sh_text Turn off sh_text], + [ --disable-sh_text Turn off sh_text], [case "${enableval}" in yes) sh_text=true ;; no) sh_text=false ;; *) AC_MSG_ERROR([bad value ${enableval} for --disable-sh_text]) ;; esac],[sh_text=true]) -AM_CONDITIONAL([SH_TEXT], [test x$sh_text = xtrue]) -[if [ x"${sh_text}" = xtrue ]; then] -AC_DEFINE([SH_TEXT]) -[fi] AC_ARG_ENABLE([sh_stext], - [--disable-sh_stext Turn off sh_stext], + [ --disable-sh_stext Turn off sh_stext], [case "${enableval}" in yes) sh_stext=true ;; no) sh_stext=false ;; @@ -68,6 +61,63 @@ AC_DEFINE([SH_STEXT]) [fi] +AC_ARG_ENABLE([X_supp], + [ --disable-X_supp Turn off X backend], +[case "${enableval}" in + yes) X_supp=true ;; + no) X_supp=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --disable-X_supp]) ;; +esac],[X_supp=true]) + +AC_ARG_ENABLE([skia], + [ --enable-skia Turn on Skia instead of Cairo], +[case "${enableval}" in + yes) skia=true ;; + no) skia=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-skia]) ;; +esac],[skia=false]) +AM_CONDITIONAL([SKIA_GRAPH_ENGINE], [test x$skia = xtrue]) +AM_CONDITIONAL([CAIRO_GRAPH_ENGINE], [test x$skia != xtrue]) +[if [ x"${skia}" = xtrue ]; then ] +AC_DEFINE([SKIA_GRAPH_ENGINE]) +cairo=false +[else] +AC_DEFINE([CAIRO_GRAPH_ENGINE]) +cairo=true +[fi] + +AC_ARG_ENABLE([nodejs], + [ --enable-nodejs Turn on nodejs support], +[case "${enableval}" in + yes) nodejs=true ;; + no) nodejs=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-nodejs]) ;; +esac],[nodejs=false]) +[if [ x"${nodejs}" = xtrue ]; then ] + AC_PATH_PROG([NODE_WAF], [node-waf]) + AC_CHECK_PROG([has_node], [node], [true], [false]) +[fi] +AM_CONDITIONAL([NODEJS], [test x"${nodejs}-${has_node}" = xtrue-true]) + +# Define AM and AC variable for sh_text +AM_CONDITIONAL([SH_TEXT], [test x$sh_text = xtrue -a x$cairo = xtrue]) +[if [ x"${sh_text}" = xtrue -a x$cairo = xtrue ]; then] +AC_DEFINE([SH_TEXT]) +[fi] + +# Define AM and AC variable for X_supp +AM_CONDITIONAL([X_SUPP], + [test x$X_supp = xtrue -a x$cairo = xtrue]) +[if [ x"${X_supp}" = xtrue -a x"${cairo}" = xtrue ]; then] +AC_DEFINE([X_SUPP]) +[fi] + +# Checks for libraries. +[if [ x"${cairo}" = xtrue ]; then] +PKG_CHECK_MODULES([cairo], [cairo >= 1.6], , AC_MSG_ERROR([cairo >= 1.6 not found])) +PKG_CHECK_MODULES([pangocairo], [pangocairo >= 1.0], , AC_MSG_ERROR([pangocairo >= 1.0 not found])) +[fi] + AC_CONFIG_FILES([Makefile libmbfly.pc libmbfly-uninstalled.pc @@ -81,9 +131,13 @@ src/Makefile include/Makefile inkscape/Makefile + nodejs/Makefile tools/Makefile]) AH_TEMPLATE([SH_TEXT],[Enable sh_text object]) AH_TEMPLATE([SH_STEXT],[Enable sh_stext object]) +AH_TEMPLATE([SKIA_GRAPH_ENGINE], [Enable Skia Graphic Engine]) +AH_TEMPLATE([CAIRO_GRAPH_ENGINE], [Enable Cairo Graphic Engine]) +AH_TEMPLATE([X_SUPP], [Enable X backend]) AC_OUTPUT diff -r aa2b388fba4e -r dcd7adb2c0fc dox/Android.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dox/Android.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,124 @@ +/*! \page android Integrate MadButterfly with Android + * + * I think almost all technical guys know Android, the mobile OS + * project from Google. Once I know Android, my first idea is it is + * cool if Android programmers can be powered by MadButterfly. + * MadButterfly is very feasible for a lot of programs running on + * devices that Android be targeted for. This document is about how + * the MadButterfly is integrated with Android and power Android + * applications. + * + * \section android_jni Android Native Code + * + * Android applications are actually Java code running on Dalvik VM. + * Although, Java bytecode was translated into Dalvik bytecode. JNI + * is the bridge of bytecode and native code. Bytecode and native + * code can access each other through JNI interface. So, we must + * implement a set of JNI native function as the channel for + * communication between Android applications and MadButterfly. + * Following image is how the MadButterfly integrated with the + * Android. + * + * \image html Android-int.png + * + * MB JNI is a set of JNI native static methods that expose + * MadButterfly functions to Java code. Java application can call + * native static methods of MB JNI to access functions provided by + * MadButterfly. + * + * Android applications draw everything on Canvas obects (backed by a + * surface). A canvas is actually a wrapper for a SkCanvas of Skia. + * Drawing on a Canvas object means drawing on a SkCanvas object. To + * draw on the screen, MadButterfly draws on the SkCanvas. + * + * The idea is to make MadButterfly as a View of Android UI. + * SurfaceView is extended as MBView; the sub-type of View for showing + * graphics generated by MadButterfly. The SurfaceView own a surface. + * The surface is passed to MadButterfly as a SurfaceHolder. MB JNI + * can get Canvas objects from the SurfaceHolder, and get associated + * SkCanvas in turn. With SkCanvas objects, MadButterfly can draw for + * the MBView object. + * + * \section android_mem Memory Management for Android JNI Interface + * + * Some memory allocated and returned by MadButterfly should be + * managed by the application. These memory blocks should not be + * freed until they are no more used by MadButterfly engine. It means + * Android applications reponsible for managing memory blocks. To + * simplify implmentation of MB JNI, MB JNI always return the address + * of an allocated objects as a Java integer. Java code should + * take care about these addresses, and call proper functions for + * freeing objects specified by addresses at right time. + * + * A Java side framework should be designed to easy the work of + * Android application programmers. The framework should take care of + * tracking life-cycle of MadButterfly objects. The namespace of the + * framework is 'org.madbutterfly'. + * + * \section android_jni _jni + * + * org.madbutterfly._jni class is the placeholder to collect JNI + * native methods for all MadButterfly functions. All methods of _jni + * are static. A method usually maps to a MadButterfly function. For + * example, rdman_coord_new() mapes to the MadButterfly function with + * the same name. + * + * The object returned by a MadButterfly function, for ex. returned + * value of rdman_coord_new(), is casted to a int, the address of the + * object. So, type of an argument or return value of an object is + * declared as a int. For example, + * \code + * class _jni { + * native static int rdman_coord_new(void); + * } + * \endcode + * Java code should keep these integers carefully for maintaining + * life-cycle of objects. + * + * MadButterfly provides only initial function for some objects, + * application should allocate memory for these function by them-self. + * For these function, a new JNI native method are used instead of + * initial function. The new JNI method is responsible for allocating + * memory and calling initial function. For example, redraw_man_new() + * is defined as a JNI method instead of redraw_man_init(). + * \code + * native static int redraw_man_new(Canvas cr, Canvas backend); + * \endcode + * First argument, rdman, of redraw_man_init() is replaced by a int + * returned value of redraw_man_new(). cr and backend, mbe_t type by + * MadButterfly, are, now, Canvas type by the JNI native method. The + * implementation of the JNI native mothod would retrieves the + * SkCanvas object, and casts it to mbe_t type. + * + * \section android_java_mb Java Likes MadButterfly + * + * Managing life-cycle for MadButterfly objects is not Java likes. + * To provie a Java style interface for MadButterfly, a framework to + * hide underlying life-cycle management is requried. Life-cycle is + * one major responsibility of the framework, it should keep integers + * of addresses of objects and free the associated resources with + * correct JNI methods and at right time. + * + * For example, org.madbutterfly.redraw_man is the respective Java + * class of redraw_man_t of MadButterfly engine. redraw_man has a + * private member variable redraw_man._rdman_addr. It is the address + * of the respective redraw_man_t object of MadButterfly. redraw_man + * would call _jni.redraw_man_destroy() to release associated + * resources and free the memory before it being recycled. So, + * redraw_man.finalize() is defined for releasing resources. It would + * be called before a redraw_man object being recycled. + * + * \section android_MBView MBView for Android MBView extends + * + * SurfaceView is a sub-class of View provided by Android. MBView + * inherits SurfaceView to implement a View controlled by + * MadButterfly. A MBView object owns a redraw_man, a.k.a + * redraw_man_t of MadButterfly. Android application programmers + * works on redraw_man to manipulate MadButterfly and changes content + * showed by the MBView object. Android applications call + * MBView.get_rdman() to retrieve the redraw_man object assocaited + * with a MBView object. MadButterfly would draw the content of a + * redraw_man object on the surface, inherited from the SurfaceView + * class, associated with the MBView object. + * + */ diff -r aa2b388fba4e -r dcd7adb2c0fc examples/Makefile.am --- a/examples/Makefile.am Sun Nov 08 00:37:29 2009 +0800 +++ b/examples/Makefile.am Wed Jun 09 17:30:09 2010 +0800 @@ -1,1 +1,3 @@ +if X_SUPP SUBDIRS = calculator svg2code_ex tank dynamic drag menu +endif diff -r aa2b388fba4e -r dcd7adb2c0fc examples/menu/filebrowser.c --- a/examples/menu/filebrowser.c Sun Nov 08 00:37:29 2009 +0800 +++ b/examples/menu/filebrowser.c Wed Jun 09 17:30:09 2010 +0800 @@ -69,21 +69,20 @@ { redraw_man_t *rdman = MBAF_RDMAN(app); paint_t *paint, *old_paint; - paint_t *previewimg_paint; shape_t *obj = (shape_t *) MB_SPRITE_GET_OBJ(app->rootsprite, "previewimg"); int w, h; - previewimg_paint = - (paint_t *)MB_SPRITE_GET_OBJ(app->rootsprite, - "previewimg_paint_img"); printf("Preview %s\n",path); - paint = rdman_img_ldr_load_paint(rdman, path); + paint = rdman_img_ldr_load_paint(rdman, path); /* return a cached + * paint if the + * path was loaded + * before */ if (paint) { paint_image_get_size(paint, &w, &h); printf("image %d %d\n",w, h); old_paint = sh_get_fill(obj); rdman_paint_fill(rdman, paint, obj); - if(old_paint != previewimg_paint) + if(old_paint != paint) rdman_paint_free(rdman, old_paint); rdman_shape_changed(MBAF_RDMAN(app),obj); diff -r aa2b388fba4e -r dcd7adb2c0fc img/Android-int.png Binary file img/Android-int.png has changed diff -r aa2b388fba4e -r dcd7adb2c0fc include/Makefile.am --- a/include/Makefile.am Sun Nov 08 00:37:29 2009 +0800 +++ b/include/Makefile.am Wed Jun 09 17:30:09 2010 +0800 @@ -1,4 +1,5 @@ include_HEADERS = \ + mb_config.h \ mb_animate.h \ mb.h \ mb_timer.h \ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb.h --- a/include/mb.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb.h Wed Jun 09 17:30:09 2010 +0800 @@ -1,9 +1,13 @@ #ifndef __MB_H_ #define __MB_H_ +#include "mb_config.h" + #include "mb_types.h" #include "mb_redraw_man.h" +#ifdef X_SUPP #include "mb_X_supp.h" +#endif #include "mb_animate.h" #include "mb_shapes.h" diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_basic_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_basic_types.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,11 @@ +#ifndef __MB_BASIC_TYPES_H_ +#define __MB_BASIC_TYPES_H_ + +typedef float co_aix; +typedef float co_comp_t; +typedef struct _grad_stop { + co_aix offset; + co_comp_t r, g, b, a; +} grad_stop_t; + +#endif /* __MB_BASIC_TYPES_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_config.h.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_config.h.in Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,19 @@ +#ifndef __MB_CONFIG_H_ +#define __MB_CONFIG_H_ + +/* Enable Cairo Graphic Engine */ +#undef CAIRO_GRAPH_ENGINE + +/* Enable Skia Graphic Engine */ +#undef SKIA_GRAPH_ENGINE + +/* Enable sh_text */ +#undef SH_TEXT + +/* Enable sh_stext */ +#undef SH_STEXT + +/* Enable X backend */ +#undef X_SUPP + +#endif /* __MB_CONFIG_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_graph_engine.h --- a/include/mb_graph_engine.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb_graph_engine.h Wed Jun 09 17:30:09 2010 +0800 @@ -1,187 +1,13 @@ #ifndef __MBE_H_ #define __MBE_H_ - -#include -#include -#include -#include "mb_img_ldr.h" - -/*! \defgroup mb_graph_engine MadButterfly Graphic Engine - * @{ - */ -#define MBE_OPERATOR_CLEAR CAIRO_OPERATOR_CLEAR -#define MBE_OPERATOR_SOURCE CAIRO_OPERATOR_SOURCE -#define MBE_STATUS_SUCCESS CAIRO_STATUS_SUCCESS - -#define mbe_ft_font_face_create_for_pattern cairo_ft_font_face_create_for_pattern -#define mbe_image_surface_create_from_png cairo_image_surface_create_from_png -#define mbe_pattern_add_color_stop_rgba cairo_pattern_add_color_stop_rgba -#define mbe_pattern_create_for_surface cairo_pattern_create_for_surface -#define mbe_scaled_font_text_extents cairo_scaled_font_text_extents -#define mbe_image_surface_get_stride cairo_image_surface_get_stride -#define mbe_image_surface_get_height cairo_image_surface_get_height -#define mbe_image_surface_get_width cairo_image_surface_get_width -#define mbe_image_surface_get_data cairo_image_surface_get_data -#define mbe_scaled_font_reference cairo_scaled_font_reference -#define mbe_pattern_create_radial cairo_pattern_create_radial -#define mbe_pattern_create_linear cairo_pattern_create_linear -#define mbe_xlib_surface_create cairo_xlib_surface_create -#define mbe_scaled_font_destroy cairo_scaled_font_destroy -#define mbe_font_options_create cairo_font_options_create -#define mbe_font_face_reference cairo_font_face_reference -#define mbe_set_source_surface cairo_set_source_surface -#define mbe_scaled_font_status cairo_scaled_font_status -#define mbe_scaled_font_create cairo_scaled_font_create -#define mbe_pattern_set_matrix cairo_pattern_set_matrix -#define mbe_font_face_destroy cairo_font_face_destroy -#define mbe_paint_with_alpha cairo_paint_with_alpha -#define mbe_font_face_status cairo_font_face_status -#define mbe_surface_destroy cairo_surface_destroy -#define mbe_set_source_rgba cairo_set_source_rgba -#define mbe_set_scaled_font cairo_set_scaled_font -#define mbe_pattern_destroy cairo_pattern_destroy -#define mbe_get_scaled_font cairo_get_scaled_font -#define mbe_set_source_rgb cairo_set_source_rgb -#define mbe_set_line_width cairo_set_line_width -#define mbe_get_font_face cairo_get_font_face -#define mbe_fill_preserve cairo_fill_preserve -#define mbe_set_operator cairo_set_operator -#define mbe_get_operator cairo_get_operator -#define mbe_set_source cairo_set_source -#define mbe_reset_clip cairo_reset_clip -#define mbe_get_target cairo_get_target -#define mbe_close_path cairo_close_path -#define mbe_text_path cairo_text_path -#define mbe_show_text cairo_show_text -#define mbe_rectangle cairo_rectangle -#define mbe_in_stroke cairo_in_stroke -#define mbe_new_path cairo_new_path -#define mbe_curve_to cairo_curve_to -#define mbe_restore cairo_restore -#define mbe_move_to cairo_move_to -#define mbe_line_to cairo_line_to -#define mbe_in_fill cairo_in_fill -#define mbe_destroy cairo_destroy -#define mbe_stroke cairo_stroke -#define mbe_create cairo_create -#define mbe_paint cairo_paint -#define mbe_save cairo_save -#define mbe_fill cairo_fill -#define mbe_clip cairo_clip - -typedef cairo_text_extents_t mbe_text_extents_t; -typedef cairo_font_options_t mbe_font_options_t; -typedef cairo_scaled_font_t mbe_scaled_font_t; -typedef cairo_font_face_t mbe_font_face_t; -typedef cairo_operator_t mbe_operator_t; -typedef cairo_surface_t mbe_surface_t; -typedef cairo_pattern_t mbe_pattern_t; -typedef cairo_status_t mbe_status_t; -typedef cairo_matrix_t mbe_matrix_t; -typedef cairo_t mbe_t; -typedef float co_aix; +#include -static mbe_surface_t * -mbe_image_surface_create_for_data(unsigned char *data, - mb_img_fmt_t fmt, - int width, int height, - int stride) { - cairo_format_t _fmt; - - switch(fmt) { - case MB_IFMT_ARGB32: - _fmt = CAIRO_FORMAT_ARGB32; - break; - case MB_IFMT_RGB24: - _fmt = CAIRO_FORMAT_RGB24; - break; - case MB_IFMT_A8: - _fmt = CAIRO_FORMAT_A8; - break; - case MB_IFMT_A1: - _fmt = CAIRO_FORMAT_A1; - break; - default: - return NULL; - } - return cairo_image_surface_create_for_data(data, _fmt, - width, height, stride); -} - -static mb_img_fmt_t -mbe_image_surface_get_format(mbe_surface_t *surface) { - cairo_format_t _fmt; - mb_img_fmt_t fmt; - - _fmt = cairo_image_surface_get_format(surface); - switch(_fmt) { - case CAIRO_FORMAT_ARGB32: - fmt = MB_IFMT_ARGB32; - break; - case CAIRO_FORMAT_RGB24: - fmt = MB_IFMT_RGB24; - break; - case CAIRO_FORMAT_A8: - fmt = MB_IFMT_A8; - break; - case CAIRO_FORMAT_A1: - fmt = MB_IFMT_A1; - break; - default: - fmt = MB_IFMT_DUMMY; - break; - } +#ifdef CAIRO_GRAPH_ENGINE +#include +#endif - return fmt; -} - -static mbe_surface_t * -mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) { - cairo_format_t _fmt; - - switch(fmt) { - case MB_IFMT_ARGB32: - _fmt = CAIRO_FORMAT_ARGB32; - break; - case MB_IFMT_RGB24: - _fmt = CAIRO_FORMAT_RGB24; - break; - case MB_IFMT_A8: - _fmt = CAIRO_FORMAT_A8; - break; - case MB_IFMT_A1: - _fmt = CAIRO_FORMAT_A1; - break; - default: - return NULL; - } - - return cairo_image_surface_create(_fmt, width, height); -} - -static void -mbe_transform(mbe_t *mbe, const co_aix matrix[6]) { - cairo_matrix_t cmtx; - - cmtx.xx = matrix[0]; - cmtx.xy = matrix[1]; - cmtx.x0 = matrix[2]; - cmtx.yx = matrix[3]; - cmtx.yy = matrix[4]; - cmtx.y0 = matrix[5]; - - cairo_transform(mbe, &cmtx); -} - -static void -mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, - co_aix angle_start, co_aix angle_stop) { - if(angle_start <= angle_stop) - cairo_arc(mbe, x, y, radius, angle_start, angle_stop); - else - cairo_arc_negative(mbe, x, y, radius, angle_start, angle_stop); -} - -/* @} */ +#ifdef SKIA_GRAPH_ENGINE +#include +#endif #endif /* __MBE_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_graph_engine_cairo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_graph_engine_cairo.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,246 @@ +#ifndef __MB_GE_CAIRO_H_ +#define __MB_GE_CAIRO_H_ + +#include +#include +#include +#include "mb_basic_types.h" +#include "mb_img_ldr.h" + +/*! \defgroup mb_ge_cairo MadButterfly Graphic Engine with Cairo + * @{ + */ +#define MBE_OPERATOR_CLEAR CAIRO_OPERATOR_CLEAR +#define MBE_OPERATOR_SOURCE CAIRO_OPERATOR_SOURCE +#define MBE_STATUS_SUCCESS CAIRO_STATUS_SUCCESS + +#define mbe_image_surface_create_from_png cairo_image_surface_create_from_png +#define mbe_pattern_create_for_surface cairo_pattern_create_for_surface +#define mbe_scaled_font_text_extents cairo_scaled_font_text_extents +#define mbe_image_surface_get_stride cairo_image_surface_get_stride +#define mbe_image_surface_get_height cairo_image_surface_get_height +#define mbe_image_surface_get_width cairo_image_surface_get_width +#define mbe_image_surface_get_data cairo_image_surface_get_data +#define mbe_scaled_font_reference cairo_scaled_font_reference +#define mbe_xlib_surface_create cairo_xlib_surface_create +#define mbe_scaled_font_destroy cairo_scaled_font_destroy +#define mbe_font_face_reference cairo_font_face_reference +#define mbe_font_face_destroy cairo_font_face_destroy +#define mbe_paint_with_alpha cairo_paint_with_alpha +#define mbe_surface_destroy cairo_surface_destroy +#define mbe_set_source_rgba cairo_set_source_rgba +#define mbe_set_scaled_font cairo_set_scaled_font +#define mbe_pattern_destroy cairo_pattern_destroy +#define mbe_get_scaled_font cairo_get_scaled_font +#define mbe_set_source_rgb cairo_set_source_rgb +#define mbe_set_line_width cairo_set_line_width +#define mbe_get_font_face cairo_get_font_face +#define mbe_fill_preserve cairo_fill_preserve +#define mbe_set_source cairo_set_source +#define mbe_reset_clip cairo_reset_clip +#define mbe_get_target cairo_get_target +#define mbe_close_path cairo_close_path +#define mbe_text_path cairo_text_path +#define mbe_rectangle cairo_rectangle +#define mbe_in_stroke cairo_in_stroke +#define mbe_new_path cairo_new_path +#define mbe_curve_to cairo_curve_to +#define mbe_restore cairo_restore +#define mbe_move_to cairo_move_to +#define mbe_line_to cairo_line_to +#define mbe_in_fill cairo_in_fill +#define mbe_destroy cairo_destroy +#define mbe_stroke cairo_stroke +#define mbe_create cairo_create +#define mbe_paint cairo_paint +#define mbe_save cairo_save +#define mbe_fill cairo_fill +#define mbe_clip cairo_clip + +typedef cairo_text_extents_t mbe_text_extents_t; +typedef cairo_scaled_font_t mbe_scaled_font_t; +typedef cairo_font_face_t mbe_font_face_t; +typedef cairo_surface_t mbe_surface_t; +typedef cairo_pattern_t mbe_pattern_t; +typedef cairo_t mbe_t; + +#define MB_MATRIX_2_CAIRO(cmtx, mtx) { \ + (cmtx).xx = (mtx)[0]; \ + (cmtx).xy = (mtx)[1]; \ + (cmtx).x0 = (mtx)[2]; \ + (cmtx).yx = (mtx)[3]; \ + (cmtx).yy = (mtx)[4]; \ + (cmtx).y0 = (mtx)[5]; \ +} + + +extern mbe_font_face_t * mbe_query_font_face(const char *family, + int slant, int weight); +extern void mbe_free_font_face(mbe_font_face_t *face); +extern mbe_pattern_t *mbe_pattern_create_radial(co_aix cx0, co_aix cy0, + co_aix radius0, + co_aix cx1, co_aix cy1, + co_aix radius1, + grad_stop_t *stops, + int stop_cnt); +extern mbe_pattern_t *mbe_pattern_create_linear(co_aix x0, co_aix y0, + co_aix x1, co_aix y1, + grad_stop_t *stops, + int stop_cnt); + + +static void mbe_pattern_set_matrix(mbe_pattern_t *ptn, + const co_aix matrix[6]) { + cairo_matrix_t cmtx; + + MB_MATRIX_2_CAIRO(cmtx, matrix); + cairo_pattern_set_matrix(ptn, &cmtx); +} + +static void mbe_clear(mbe_t *canvas) { + cairo_operator_t old_op; + + old_op = cairo_get_operator(canvas); + cairo_set_operator(canvas, CAIRO_OPERATOR_CLEAR); + cairo_paint(canvas); + cairo_set_operator(canvas, old_op); +} + +static void mbe_copy_source(mbe_t *src, mbe_t *dst) { + cairo_operator_t saved_op; + cairo_surface_t *surf; + cairo_pattern_t *ptn; + + surf = cairo_get_target(src); + ptn = cairo_pattern_create_for_surface(surf); + cairo_set_source(src, ptn); + cairo_pattern_destroy(ptn); + saved_op = cairo_get_operator(dst); + cairo_set_operator(dst, CAIRO_OPERATOR_SOURCE); + cairo_paint(dst); + cairo_set_operator(dst, saved_op); +} + +static mbe_scaled_font_t * +mbe_scaled_font_create(mbe_font_face_t *face, co_aix fnt_mtx[6], + co_aix ctm[6]) { + cairo_font_options_t *options; + mbe_scaled_font_t *scaled; + cairo_matrix_t cfnt_mtx, cctm; + + options = cairo_font_options_create(); + if(options == NULL) + return NULL; + + MB_MATRIX_2_CAIRO(cfnt_mtx, fnt_mtx); + MB_MATRIX_2_CAIRO(cctm, ctm); + scaled = cairo_scaled_font_create(face, &cfnt_mtx, &cctm, options); + + cairo_font_options_destroy(options); + + return scaled; +} + +static mbe_surface_t * +mbe_image_surface_create_for_data(unsigned char *data, + mb_img_fmt_t fmt, + int width, int height, + int stride) { + cairo_format_t _fmt; + + switch(fmt) { + case MB_IFMT_ARGB32: + _fmt = CAIRO_FORMAT_ARGB32; + break; + case MB_IFMT_RGB24: + _fmt = CAIRO_FORMAT_RGB24; + break; + case MB_IFMT_A8: + _fmt = CAIRO_FORMAT_A8; + break; + case MB_IFMT_A1: + _fmt = CAIRO_FORMAT_A1; + break; + default: + return NULL; + } + return cairo_image_surface_create_for_data(data, _fmt, + width, height, stride); +} + +static mb_img_fmt_t +mbe_image_surface_get_format(mbe_surface_t *surface) { + cairo_format_t _fmt; + mb_img_fmt_t fmt; + + _fmt = cairo_image_surface_get_format(surface); + switch(_fmt) { + case CAIRO_FORMAT_ARGB32: + fmt = MB_IFMT_ARGB32; + break; + case CAIRO_FORMAT_RGB24: + fmt = MB_IFMT_RGB24; + break; + case CAIRO_FORMAT_A8: + fmt = MB_IFMT_A8; + break; + case CAIRO_FORMAT_A1: + fmt = MB_IFMT_A1; + break; + default: + fmt = MB_IFMT_DUMMY; + break; + } + + return fmt; +} + +static mbe_surface_t * +mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) { + cairo_format_t _fmt; + + switch(fmt) { + case MB_IFMT_ARGB32: + _fmt = CAIRO_FORMAT_ARGB32; + break; + case MB_IFMT_RGB24: + _fmt = CAIRO_FORMAT_RGB24; + break; + case MB_IFMT_A8: + _fmt = CAIRO_FORMAT_A8; + break; + case MB_IFMT_A1: + _fmt = CAIRO_FORMAT_A1; + break; + default: + return NULL; + } + + return cairo_image_surface_create(_fmt, width, height); +} + +static void +mbe_transform(mbe_t *mbe, const co_aix matrix[6]) { + cairo_matrix_t cmtx; + + cmtx.xx = matrix[0]; + cmtx.xy = matrix[1]; + cmtx.x0 = matrix[2]; + cmtx.yx = matrix[3]; + cmtx.yy = matrix[4]; + cmtx.y0 = matrix[5]; + + cairo_transform(mbe, &cmtx); +} + +static void +mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, + co_aix angle_start, co_aix angle_stop) { + if(angle_start <= angle_stop) + cairo_arc(mbe, x, y, radius, angle_start, angle_stop); + else + cairo_arc_negative(mbe, x, y, radius, angle_start, angle_stop); +} +/* @} */ + +#endif /* __MB_GE_CAIRO_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_graph_engine_skia.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/mb_graph_engine_skia.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,122 @@ +#ifndef __MB_GE_SKIA_H_ +#define __MB_GE_SKIA_H_ + +#include +#include "mb_basic_types.h" +#include "mb_img_ldr.h" + +/*! \defgroup mb_ge_skia MadButterfly Graphic Engine with Skia + * @{ + */ +#define MBE_OPERATOR_CLEAR 2 +#define MBE_OPERATOR_SOURCE 1 +#define MBE_STATUS_SUCCESS 0 + +struct _mbe_text_extents_t { + co_aix x_bearing; + co_aix y_bearing; + co_aix width; + co_aix height; + co_aix x_advance; + co_aix y_advance; +}; +struct _mbe_scaled_font_t; +struct _mbe_font_face_t; +struct _mbe_surface_t; +struct _mbe_pattern_t; +struct _mbe_t; + +typedef struct _mbe_text_extents_t mbe_text_extents_t; +typedef struct _mbe_scaled_font_t mbe_scaled_font_t; +typedef struct _mbe_font_face_t mbe_font_face_t; +typedef struct _mbe_surface_t mbe_surface_t; +typedef struct _mbe_pattern_t mbe_pattern_t; +typedef struct _mbe_t mbe_t; + +extern mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface); +extern mbe_pattern_t *mbe_pattern_create_radial(co_aix cx0, co_aix cy0, + co_aix radius0, + co_aix cx1, co_aix cy1, + co_aix radius1, + grad_stop_t *stops, + int stop_cnt); +extern mbe_pattern_t *mbe_pattern_create_linear(co_aix x0, co_aix y0, + co_aix x1, co_aix y1, + grad_stop_t *stops, + int stop_cnt); +extern void mbe_pattern_set_matrix(mbe_pattern_t *ptn, + const co_aix matrix[6]); +extern void mbe_pattern_destroy(mbe_pattern_t *ptn); + +extern int mbe_image_surface_get_stride(mbe_surface_t *surface); +extern int mbe_image_surface_get_height(mbe_surface_t *surface); +extern int mbe_image_surface_get_width(mbe_surface_t *surface); +extern unsigned char *mbe_image_surface_get_data(mbe_surface_t *surface); +extern mbe_surface_t *mbe_image_surface_create_from_png(const char *filename); +extern mbe_surface_t * +mbe_image_surface_create_for_data(unsigned char *data, + mb_img_fmt_t fmt, + int width, int height, + int stride); +extern mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface); +extern mbe_surface_t * +mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height); + +extern mbe_scaled_font_t *mbe_scaled_font_reference(mbe_scaled_font_t *scaled); +extern void mbe_scaled_font_destroy(mbe_scaled_font_t *scaled); +extern mbe_font_face_t *mbe_font_face_reference(mbe_font_face_t *face); +extern mbe_scaled_font_t * +mbe_scaled_font_create(mbe_font_face_t *face, co_aix fnt_mtx[6], + co_aix ctm[6]); +extern mbe_scaled_font_t *mbe_get_scaled_font(mbe_t *canvas); +extern void mbe_scaled_font_text_extents(mbe_scaled_font_t *scaled, + const char *txt, + mbe_text_extents_t *extents); + +extern void mbe_font_face_destroy(mbe_font_face_t *face); +extern void mbe_paint_with_alpha(mbe_t *canvas, co_aix alpha); +extern void mbe_surface_destroy(mbe_surface_t *surface); +extern void mbe_set_source_rgba(mbe_t *canvas, + co_aix r, co_aix g, co_aix b, co_aix a); +extern void mbe_set_scaled_font(mbe_t *canvas, + const mbe_scaled_font_t *scaled); +extern void mbe_set_source_rgb(mbe_t *canvas, co_aix r, co_aix g, co_aix b); +extern void mbe_set_line_width(mbe_t *canvas, co_aix width); +extern mbe_font_face_t *mbe_get_font_face(mbe_t *canvas); +extern void mbe_fill_preserve(mbe_t *canvas); +extern void mbe_set_source(mbe_t *canvas, mbe_pattern_t *source); +extern void mbe_reset_clip(mbe_t *canvas); +extern mbe_surface_t *mbe_get_target(mbe_t *canvas); +extern void mbe_close_path(mbe_t *canvas); +extern void mbe_text_path(mbe_t *canvas, const char *txt); +extern void mbe_rectangle(mbe_t *canvas, co_aix x, co_aix y, + co_aix width, co_aix height); +extern int mbe_in_stroke(mbe_t *canvas, co_aix x, co_aix y); +extern void mbe_new_path(mbe_t *canvas); +extern void mbe_curve_to(mbe_t *canvas, co_aix x1, co_aix y1, + co_aix x2, co_aix y2, + co_aix x3, co_aix y3); +extern void mbe_restore(mbe_t *canvas); +extern void mbe_move_to(mbe_t *canvas, co_aix x, co_aix y); +extern void mbe_line_to(mbe_t *canvas, co_aix x, co_aix y); +extern int mbe_in_fill(mbe_t *canvas, co_aix x, co_aix y); +extern void mbe_stroke(mbe_t *canvas); +extern mbe_t *mbe_create(mbe_surface_t *target); +extern void mbe_destroy(mbe_t *canvas); +extern void mbe_paint(mbe_t *canvas); +extern void mbe_save(mbe_t *canvas); +extern void mbe_fill(mbe_t *canvas); +extern void mbe_clip(mbe_t *canvas); + +extern mbe_font_face_t * mbe_query_font_face(const char *family, + int slant, int weight); +extern void mbe_free_font_face(mbe_font_face_t *face); + +extern void mbe_clear(mbe_t *canvas); +extern void mbe_copy_source(mbe_t *src, mbe_t *dst); +extern void mbe_transform(mbe_t *mbe, co_aix matrix[6]); +extern void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, + co_aix angle_start, co_aix angle_stop); +/* @} */ + +#endif /* __MB_GE_SKIA_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_paint.h --- a/include/mb_paint.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb_paint.h Wed Jun 09 17:30:09 2010 +0800 @@ -7,8 +7,6 @@ #include "mb_img_ldr.h" #include "mb_tools.h" -typedef float co_comp_t; - extern paint_t *rdman_paint_color_new(redraw_man_t *rdman, co_comp_t r, co_comp_t g, co_comp_t b, co_comp_t a); @@ -30,11 +28,6 @@ #define paint_destroy(_paint) -typedef struct _grad_stop { - co_aix offset; - co_comp_t r, g, b, a; -} grad_stop_t; - extern paint_t *rdman_paint_linear_new(redraw_man_t *rdman, co_aix x1, co_aix y1, co_aix x2, co_aix y2); diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_redraw_man.h --- a/include/mb_redraw_man.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb_redraw_man.h Wed Jun 09 17:30:09 2010 +0800 @@ -55,6 +55,7 @@ elmpool_t *coord_canvas_pool; coords_t dirty_coords; + coords_t dirty_pcache_area_coords; geos_t dirty_geos; int n_dirty_areas; /*!< \brief Number of all dirty areas. */ @@ -109,8 +110,6 @@ } while(0) extern int rdman_shape_free(redraw_man_t *rdman, shape_t *shape); -#define rdman_paint_man(rdman, paint) \ - STAILQ_INS_TAIL(rdman->paints, paint_t, pnt_next, shape) extern int rdman_paint_free(redraw_man_t *rdman, paint_t *paint); extern coord_t *rdman_coord_new(redraw_man_t *rdman, coord_t *parent); @@ -157,25 +156,31 @@ #define _rdman_paint_remove_child(rdman, paint, shape) \ do { \ if((shape)->fill == (shape)->stroke && \ - (shape)->stroke == paint) \ + (shape)->stroke == (paint)) \ break; \ _rdman_paint_real_remove_child(rdman, paint, shape); \ } while(0) -#define rdman_paint_fill(rdman, paint, shape) \ - do { \ - if((shape)->fill == paint) \ - break; \ - _rdman_paint_remove_child(rdman, paint, shape); \ - _rdman_paint_child(rdman, paint, shape); \ - (shape)->fill = paint; \ +#define rdman_paint_fill(rdman, paint, shape) \ + do { \ + if((shape)->fill == paint) \ + break; \ + if((shape)->fill) \ + _rdman_paint_remove_child(rdman, (shape)->fill, \ + shape); \ + if(paint) \ + _rdman_paint_child(rdman, paint, shape); \ + (shape)->fill = paint; \ } while(0) -#define rdman_paint_stroke(rdman, paint, shape) \ - do { \ - if((shape)->stroke == paint) \ - break; \ - _rdman_paint_remove_child(rdman, paint, shape); \ - _rdman_paint_child(rdman, paint, shape); \ - (shape)->stroke = paint; \ +#define rdman_paint_stroke(rdman, paint, shape) \ + do { \ + if((shape)->stroke == paint) \ + break; \ + if((shape)->stroke) \ + _rdman_paint_remove_child(rdman, (shape)->stroke, \ + shape); \ + if(paint) \ + _rdman_paint_child(rdman, paint, shape); \ + (shape)->stroke = paint; \ } while(0) extern int rdman_paint_changed(redraw_man_t *rdman, paint_t *paint); diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_shapes.h --- a/include/mb_shapes.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb_shapes.h Wed Jun 09 17:30:09 2010 +0800 @@ -7,11 +7,16 @@ #ifndef __SHAPES_H_ #define __SHAPES_H_ +#include "mb_config.h" + +#ifdef SH_TEXT +#include +#endif + #include "mb_graph_engine.h" #include "mb_types.h" #include "mb_redraw_man.h" #include "mb_img_ldr.h" -#include /*! \page define_shape How to Define Shapes * @@ -60,7 +65,7 @@ /*! \defgroup shape_path Shape of Path * @{ */ -extern shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data); +extern shape_t *rdman_shape_path_new(redraw_man_t *rdman, const char *data); extern shape_t *rdman_shape_path_new_from_binary(redraw_man_t *rdman, char *commands, co_aix *pnts, @@ -71,6 +76,7 @@ extern void sh_path_draw(shape_t *shape, mbe_t *cr); /* @} */ +#ifdef SH_TEXT /*! \defgroup shape_text Shape of Text * @{ */ @@ -92,6 +98,7 @@ extern void sh_text_transform(shape_t *shape); extern void sh_text_draw(shape_t *shape, mbe_t *cr); /* @} */ +#endif /*! \defgroup mb_text_t Shape of Text * @{ diff -r aa2b388fba4e -r dcd7adb2c0fc include/mb_types.h --- a/include/mb_types.h Sun Nov 08 00:37:29 2009 +0800 +++ b/include/mb_types.h Wed Jun 09 17:30:09 2010 +0800 @@ -123,6 +123,7 @@ #define GEF_HIDDEN 0x2 /*!< The geo is hidden. */ #define GEF_FREE 0x4 #define GEF_OV_DRAW 0x8 /*!< To flag drawed for a overlay testing. */ +#define GEF_SWAP 0x10 extern int areas_are_overlay(area_t *r1, area_t *r2); extern void area_init(area_t *area, int n_pos, co_aix pos[][2]); @@ -161,9 +162,10 @@ */ area_t aggr_dirty_areas[2]; /*!< Used to aggregate updates to parent. */ area_t cached_dirty_area; /*!< Used to dirty an area in cached space. */ - area_t owner_mems_area; /*!< \brief The area is covered by members - * of owner. - */ + area_t pcache_areas[2]; /*!< The area in the space of parent + * cached. */ + area_t *pcache_cur_area; /*!< Current area for parent cached. */ + area_t *pcache_last_area; /*!< Last area for parent cached. */ } coord_canvas_info_t; /*! \brief A coordination system. @@ -241,6 +243,16 @@ * It is used by clean_rdman_dirties(). */ #define COF_TEMP_MARK 0x400 /*!< \brief Temporary mark a coord. */ +#define COF_JUST_ZERO 0x800 /*!< \brief The coord is real peformed zeroing. + * + * It's canvas is changed by zeroing. + */ +#define COF_DIRTY_PCACHE_AREA 0x1000 /*!< \brief pcache_area shoud be + * updated. + */ +#define COF_SKIP_ZERO 0x2000 /*!< \brief The coord just skip zeroing. + * No real zeroing was performed. + */ /* @} */ extern void matrix_mul(co_aix *m1, co_aix *m2, co_aix *dst); @@ -251,6 +263,7 @@ extern co_aix coord_trans_size(coord_t *co, co_aix size); extern void compute_aggr_of_coord(coord_t *coord); extern void compute_aggr_of_cached_coord(coord_t *coord); +extern void compute_aggr(coord_t *coord); extern void compute_reverse(co_aix *orig, co_aix *reverse); extern void update_aggr_matrix(coord_t *start); extern coord_t *preorder_coord_subtree(coord_t *root, coord_t *last); @@ -277,7 +290,7 @@ (co)->flags &= ~COF_CACHE_MASK; \ } while(0) #define coord_is_root(co) ((co)->parent == NULL) -#define coord_is_cached(co) ((co)->flags & COF_CACHE_MASK) +#define coord_is_cached(co) ((co)->flags & COF_OWN_CANVAS) #define coord_is_fast_cached(co) ((co)->flags & COF_FAST_MASK) #define coord_is_precise_cached(co) ((co)->flags & COF_PRECISE_MASK) #define coord_is_zeroing(co) ((co)->flags & COF_MUST_ZEROING) @@ -287,11 +300,13 @@ do { (co)->flags &= ~COF_MUST_ZEROING; } while(0) #define coord_set_flags(co, _flags) \ do { (co)->flags |= (_flags); } while(0) +#define coord_get_parent(co) ((co)->parent) #define coord_get_flags(co, _flags) ((co)->flags & (_flags)) #define coord_clear_flags(co, _flags) \ do { (co)->flags &= ~(_flags); } while(0) #define coord_get_mouse_event(coord) ((coord)->mouse_event) #define coord_get_aggr_matrix(coord) ((coord)->aggr_matrix) +#define coord_get_matrix(coord) ((coord)->matrix) #define FOR_COORDS_POSTORDER(coord, cur) \ for((cur) = postorder_coord_subtree((coord), NULL); \ (cur) != NULL; \ @@ -323,12 +338,19 @@ shape = geo_get_shape_safe(STAILQ_NEXT(geo_t, coord_next, \ sh_get_geo(shape)))) #define coord_get_area(coord) ((coord)->cur_area) +#define coord_get_last_area(coord) ((coord)->last_area) +#define coord_get_pcache_area(coord) ((coord)->canvas_info->pcache_cur_area) +#define coord_get_pcache_last_area(coord) \ + ((coord)->canvas_info->pcache_last_area) +#define coord_get_cached(coord) ((coord)->canvas_info->owner) #define _coord_get_canvas(coord) ((coord)->canvas_info->canvas) #define _coord_set_canvas(coord, _canvas) \ do { \ (coord)->canvas_info->canvas = _canvas; \ } while(0) #define _coord_get_dirty_areas(coord) (&(coord)->canvas_info->dirty_areas) +#define _coord_get_aggr_dirty_areas(coord) \ + ((coord)->canvas_info->aggr_dirty_areas) /* @} */ @@ -377,6 +399,8 @@ #define sh_get_aggr_matrix(sh) (coord_get_aggr_matrix(sh_get_coord(sh))) #define sh_get_fill(sh) ((sh)->fill) #define sh_get_stroke(sh) ((sh)->stroke) +#define sh_set_stroke_width(sh, v) do { (sh)->stroke_width = (v); } while(0) +#define sh_get_stroke_width(sh) (sh)->stroke_width /*! \brief A sprite is a set of graphics that being an object in animation. diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/Makefile.am Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,24 @@ + +mbfly_node_SRCS = mbfly_njs.cc X_supp_njs.c coord.cc shapes.cc paints.cc +mbfly_node_CFLAGS= -I$(abs_top_builddir)/include \ + -I$(abs_top_srcdir)/include \ + -I$(prefix)/include \ + @pangocairo_CFLAGS@ $(CFLAGS) +mbfly_node_LDFLAGS = -L$(abs_top_builddir)/src/.libs @pangocairo_LIBS@ + +all: mbfly.node +clean: clean-mbfly-node + +mbfly.node: wscript $(mbfly_node_SRCS) + cd $(srcdir); \ + CFLAGS="$(mbfly_node_CFLAGS)" \ + CXXFLAGS="$(mbfly_node_CFLAGS)" \ + LDFLAGS="$(mbfly_node_LDFLAGS)" \ + TOP_BUILDDIR="$(abs_top_builddir)" \ + WAFLOCK=$(abs_builddir)/.lock-wscript \ + $(NODE_WAF) configure build --blddir=$(abs_builddir) + +clean-mbfly-node: + cd $(srcdir); \ + WAFLOCK=$(abs_builddir)/.lock-wscript \ + $(NODE_WAF) clean diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/X_supp_njs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/X_supp_njs.c Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,151 @@ +/*! \brief Implement X11 backend for nodejs plugin. + * + * Since nodejs use libev to handle event loops, part of X11 backend + * code can not be used directly. The part of code should be rewrote. + * The part is about + */ +#include +#include +#include +#include +#include "mb_X_supp.h" +#include "mb_tools.h" +#include "X_supp_njs.h" + +#ifndef ASSERT +#define ASSERT(x) +#endif + +static void timer_cb(EV_P_ ev_timer *tmwatcher, int revent); + +/*! \brief Register next timeout with libev. + */ +static void +set_next_timeout(njs_runtime_t *rt) { + mb_tman_t *tman; + mb_timeval_t now, tmo; + ev_tstamp tout; + int r; + + tman = X_MB_tman(rt->xrt); + get_now(&now); + r = mb_tman_next_timeout(tman, &now, &tmo); + if(r == 0) { + MB_TIMEVAL_DIFF(&tmo, &now); + tout = (ev_tstamp)MB_TIMEVAL_SEC(&tmo) + + (ev_tstamp)MB_TIMEVAL_USEC(&tmo) / 1000000; + ev_timer_init(&rt->tmwatcher, timer_cb, tout, 0); + ev_timer_start(&rt->tmwatcher); + rt->enable_timer = 1; + } else + rt->enable_timer = 0; +} + +static void +x_conn_cb(EV_P_ ev_io *iowatcher, int revent) { + njs_runtime_t *rt = MEM2OBJ(iowatcher, njs_runtime_t, iowatcher); + redraw_man_t *rdman; + extern void _X_MB_handle_x_event_for_nodejs(void *rt); + + rdman = X_MB_rdman(rt->xrt); + _X_MB_handle_x_event_for_nodejs(rt->xrt); + rdman_redraw_changed(rdman); + + if(rt->enable_timer == 0) /* no installed timeout */ + set_next_timeout(rt); +} + +static void +timer_cb(EV_P_ ev_timer *tmwatcher, int revent) { + njs_runtime_t *rt = MEM2OBJ(tmwatcher, njs_runtime_t, tmwatcher); + mb_tman_t *tman; + redraw_man_t *rdman; + mb_timeval_t now; + extern int _X_MB_flush_x_conn_for_nodejs(void *rt); + + tman = X_MB_tman(rt->xrt); + get_now(&now); + mb_tman_handle_timeout(tman, &now); + + rdman = X_MB_rdman(rt->xrt); + rdman_redraw_changed(rdman); + _X_MB_flush_x_conn_for_nodejs(rt->xrt); + + set_next_timeout(rt); +} + +/*! \brief Handle connection coming data and timeout of timers. + * + * \param rt is a runtime object for X. + */ +void +X_njs_MB_init_handle_connection(njs_runtime_t *rt) { + void *xrt = rt->xrt; + mb_tman_t *tman; + mb_timeval_t now, tmo; + ev_tstamp tout; + int fd; + int r; + extern int _X_MB_get_x_conn_for_nodejs(void *rt); + + /* + * Setup watcher for X connection. + */ + fd = _X_MB_get_x_conn_for_nodejs(xrt); + ev_io_init(&rt->iowatcher, x_conn_cb, fd, EV_READ); + ev_io_start(&rt->iowatcher); + rt->enable_io = 1; + + set_next_timeout(rt); +} + +/*! \brief Free njs_runtime_t. + */ +void +X_njs_MB_free(njs_runtime_t *rt) { + /* + * stop IO and timer watcher + */ + if(rt->enable_io) + ev_io_stop(&rt->iowatcher); + if(rt->enable_timer) + ev_timer_stop(&rt->tmwatcher); + + X_MB_free(rt->xrt); + free(rt); +} + +int +X_njs_MB_flush(njs_runtime_t *rt) { + void *xrt = rt->xrt; + int r; + extern int _X_MB_flush_x_conn_for_nodejs(void *rt); + + _X_MB_flush_x_conn_for_nodejs(xrt); + + return r; +} + +njs_runtime_t * +X_njs_MB_new(char *display_name, int w, int h) { + njs_runtime_t *rt; + void *xrt; + + rt = (njs_runtime_t *)malloc(sizeof(njs_runtime_t)); + ASSERT(rt != NULL); + + xrt = X_MB_new(display_name, w, h); + + rt->xrt = xrt; + rt->enable_io = 0; + rt->enable_timer = 0; /* no timer, now */ + + return rt; +} + +/*! \brief Get X runtime that is backend of this njs runtime. + */ +void * +_X_njs_MB_get_X_runtime(njs_runtime_t *rt) { + return rt->xrt; +} diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/X_supp_njs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/X_supp_njs.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,26 @@ +#ifndef __X_SUPP_NJS_H_ +#define __X_SUPP_NJS_H_ + +#include + +typedef struct _njs_runtime { + ev_io iowatcher; + ev_timer tmwatcher; + int enable_io; + int enable_timer; + void *xrt; +} njs_runtime_t; + +extern void X_njs_MB_init_handle_connection(njs_runtime_t *rt); +extern void X_njs_MB_free(njs_runtime_t *rt); +extern njs_runtime_t *X_njs_MB_new(char *display_name, int w, int h); +extern int X_njs_MB_flush(njs_runtime_t *rt); +extern void *_X_njs_MB_get_X_runtime(njs_runtime_t *rt); + +#define X_njs_MB_kbevents(rt) X_MB_kbevents((rt)->xrt) +#define X_njs_MB_rdman(rt) X_MB_rdman((rt)->xrt) +#define X_njs_MB_tman(rt) X_MB_tman((rt)->xrt) +#define X_njs_MB_ob_factory(rt) X_MB_ob_factory((rt)->xrt) +#define X_njs_MB_img_ldr(rt) X_MB_img_ldr((rt)->xrt) + +#endif /* __X_SUPP_NJS_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/coord.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/coord.cc Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,194 @@ +#include +#include + +extern "C" { +#include "mb.h" +#include "mb_X_supp.h" +#include "mb_tools.h" +#include "X_supp_njs.h" +} + +#include "mbfly_njs.h" + +#ifndef ASSERT +#define ASSERT(x) +#endif + +using namespace v8; + +static Handle +xnjsmb_coord_get_index(uint32_t index, const AccessorInfo &info) { + HandleScope scope; + Handle self; + coord_t *coord; + co_aix v; + + if(index < 0 || index >= 6) + THROW("Invalid index"); + + self = info.This(); + coord = (coord_t *)UNWRAP(self); + v = coord_get_matrix(coord)[index]; + + return Number::New(v); +} + +static Handle +xnjsmb_coord_set_index(uint32_t index, Local value, + const AccessorInfo &info) { + + HandleScope scope; + Handle self; + Handle js_rt; + redraw_man_t *rdman; + coord_t *coord; + co_aix v; + + if(index < 0 || index >= 6) + THROW("Invalid Index"); + if(!value->IsNumber()) + THROW("Invalid value"); + + self = info.This(); + coord = (coord_t *)UNWRAP(self); + v = value->NumberValue(); + coord_get_matrix(coord)[index] = v; + + js_rt = GET(self, "mbrt")->ToObject(); + rdman = xnjsmb_rt_rdman(js_rt); + rdman_coord_changed(rdman, coord); + + return value; +} + +/*! \brief Callback functio to add a shape to a coord in Javascript. + * + * coord.add_shape(shape) + */ +static Handle +xnjsmb_coord_add_shape(const Arguments &args) { + int argc = args.Length(); + Handle self = args.This(); + Handle shape_obj; + Handle rt_obj; + Handle rt_val; + redraw_man_t *rdman; + coord_t *coord; + shape_t *sh; + int r; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + + shape_obj = args[0]->ToObject(); + sh = (shape_t *)UNWRAP(shape_obj); + ASSERT(sh != NULL); + + coord = (coord_t *)UNWRAP(self); + ASSERT(coord != NULL); + + rt_val = GET(self, "mbrt"); + rt_obj = rt_val->ToObject(); + rdman = xnjsmb_rt_rdman(rt_obj); + + r = rdman_add_shape(rdman, sh, coord); + if(r != 0) + THROW("Unknown error"); + + return Null(); +} + +static Persistent coord_obj_temp; + +static void +xnjsmb_init_temp(void) { + Handle add_shape_temp; + + coord_obj_temp = Persistent::New(ObjectTemplate::New()); + coord_obj_temp->SetIndexedPropertyHandler(xnjsmb_coord_get_index, + xnjsmb_coord_set_index); + coord_obj_temp->SetInternalFieldCount(1); + + add_shape_temp = FunctionTemplate::New(xnjsmb_coord_add_shape); + SET(coord_obj_temp, "add_shape", add_shape_temp); +} + +/*! \brief Create and initialize a Javascript object for a coord. + */ +static Handle +xnjsmb_coord_new_jsobj(coord_t *coord, Handle parent_obj, + Handle js_rt) { + Handle coord_obj; + static int init_temp = 0; + + if(!init_temp) { + xnjsmb_init_temp(); + init_temp = 1; + } + + coord_obj = coord_obj_temp->NewInstance(); + ASSERT(coord_obj != NULL); + WRAP(coord_obj, coord); + + if(!parent_obj.IsEmpty()) + SET(coord_obj, "parent", parent_obj); + SET(coord_obj, "mbrt", js_rt); + + return coord_obj; +} + +/*! \brief Create a coord object associated with the rdman of the runtime. + * + * Two internal fields, coord and rdman. + */ +Handle +xnjsmb_coord_new(const Arguments &args) { + HandleScope scope; + Handle js_rt; + Handle coord_obj, parent_obj; + njs_runtime_t *rt; + redraw_man_t *rdman; + coord_t *coord, *parent = NULL; + int argc; + + argc = args.Length(); + if(argc > 1) + THROW("Too many arguments (> 1)"); + + js_rt = args.This(); + rt = (njs_runtime_t *)UNWRAP(js_rt); + rdman = X_njs_MB_rdman(rt); + + if(argc == 1) { + parent_obj = args[0]->ToObject(); + parent = (coord_t *)UNWRAP(parent_obj); + } + + coord = rdman_coord_new(rdman, parent); + ASSERT(coord != NULL); + coord_obj = xnjsmb_coord_new_jsobj(coord, parent_obj, js_rt); + + scope.Close(coord_obj); + + return coord_obj; +} + +/*! \brief Initialize Javascript object for root coord of a runtime. + * + * \param js_rt is the runtime object to create the root object for. + * + * After the function, js_rt.root is the object for root coord in + * Javascript. + */ +void +xnjsmb_coord_mkroot(Handle js_rt) { + redraw_man_t *rdman; + coord_t *root; + Handle obj; + + rdman = xnjsmb_rt_rdman(js_rt); + root = rdman_get_root(rdman); + obj = xnjsmb_coord_new_jsobj(root, Handle(NULL), js_rt); + + SET(js_rt, "root", obj); +} diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/mbfly_njs.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/mbfly_njs.cc Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,152 @@ +#include +#include + +extern "C" { +#include "X_supp_njs.h" +} + +#include "mbfly_njs.h" + +using namespace v8; + +/*! \defgroup njs_template_cb Callback functions for v8 engine and nodejs. + * + * @{ + */ + +/*! \brief to Create a njs runtime object for MadButterfly. + * + * Three arguments are requried. They are + * - display name, + * - width, and + * - height. + */ +static Handle +xnjsmb_new(const Arguments &args) { + HandleScope scope; + int argc; + Handle exc; + njs_runtime_t *rt; + char *display_name; + int width, height; + Handle self; + + argc = args.Length(); + if(argc != 3) { + exc = Exception::Error(String::New("Need 3 arguments.")); + return ThrowException(exc); + } + + if(!args[0]->IsString() || !args[1]->IsInt32() || !args[2]->IsInt32()) { + exc = Exception::Error(String::New("Invalid argument type.")); + return ThrowException(exc); + } + + String::Utf8Value disp_utf8(args[0]->ToString()); + display_name = *disp_utf8; + width = args[1]->Int32Value(); + height = args[2]->Int32Value(); + rt = X_njs_MB_new(display_name, width, height); + + self = args.This(); + WRAP(self, rt); + xnjsmb_coord_mkroot(self); + + X_njs_MB_init_handle_connection(rt); + + return Null(); +} + +static Handle +xnjsmb_handle_connection(const Arguments &args) { +} + +static Handle +xnjsmb_rt_redraw_changed(const Arguments &args) { + Handle self = args.This(); + njs_runtime_t *rt; + redraw_man_t *rdman; + + rdman = xnjsmb_rt_rdman(self); + rdman_redraw_changed(rdman); + + rt = (njs_runtime_t *)UNWRAP(self); + X_njs_MB_flush(rt); + + return Null(); +} + +static Handle +xnjsmb_rt_redraw_all(const Arguments &args) { + Handle self = args.This(); + njs_runtime_t *rt; + redraw_man_t *rdman; + + rdman = xnjsmb_rt_rdman(self); + rdman_redraw_all(rdman); + + rt = (njs_runtime_t *)UNWRAP(self); + X_njs_MB_flush(rt); + + return Null(); +} + +/* @} */ + +/*! \brief Get rdman associated with the runtime. + */ +redraw_man_t * +xnjsmb_rt_rdman(Handle mbrt) { + HandleScope scope; + njs_runtime_t *rt; + redraw_man_t *rdman; + + rt = (njs_runtime_t *)UNWRAP(mbrt); + rdman = X_njs_MB_rdman(rt); + + return rdman; +} + +Handle +hello_func(const Arguments &args) { + HandleScope scope; + + return String::Concat(String::New("World"), args[0]->ToString()); +} + +extern "C" void +init(Handle target) { + HandleScope scope; + Handle func, mb_rt_func; + Handle rt_instance_temp, rt_proto_temp; + + func = FunctionTemplate::New(hello_func); + target->Set(String::New("Hello"), func->GetFunction()); + + /* + * Initialize template for MadButterfly runtime objects. + */ + mb_rt_func = FunctionTemplate::New(xnjsmb_new); + mb_rt_func->SetClassName(String::New("mb_rt")); + + rt_instance_temp = mb_rt_func->InstanceTemplate(); + rt_instance_temp->SetInternalFieldCount(1); + + rt_proto_temp = mb_rt_func->PrototypeTemplate(); + func = FunctionTemplate::New(xnjsmb_coord_new); + SET(rt_proto_temp, "coord_new", func); + + func = FunctionTemplate::New(xnjsmb_rt_redraw_changed); + SET(rt_proto_temp, "redraw_changed", func); + + func = FunctionTemplate::New(xnjsmb_rt_redraw_all); + SET(rt_proto_temp, "redraw_all", func); + + /* + * Add properties to mb_rt templates for other modules. + */ + xnjsmb_shapes_init_mb_rt_temp(mb_rt_func); + xnjsmb_paints_init_mb_rt_temp(mb_rt_func); + + target->Set(String::New("mb_rt"), mb_rt_func->GetFunction()); +} diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/mbfly_njs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/mbfly_njs.h Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,32 @@ +#ifndef __MBFLY_NJS_H_ +#define __MBFLY_NJS_H_ + +#include +extern "C" { +#include +} + +#define THROW(x) \ + do { \ + v8::Handle exc; \ + exc = v8::Exception::Error(v8::String::New(x)); \ + return v8::ThrowException(exc); \ + } while(0) +#define UNWRAP(o) v8::External::Unwrap((o)->GetInternalField(0)) +#define WRAP(o, v) (o)->SetInternalField(0, v8::External::Wrap(v)) +#define SET(o, n, v) (o)->Set(v8::String::New(n), v) +#define GET(o, n) (o)->Get(v8::String::New(n)) + +redraw_man_t *xnjsmb_rt_rdman(v8::Handle mbrt); + +/* From coord.cc */ +v8::Handle xnjsmb_coord_new(const v8::Arguments &args); +void xnjsmb_coord_mkroot(v8::Handle js_rt); + +/* From shapes.cc */ +void xnjsmb_shapes_init_mb_rt_temp(v8::Handle rt_temp); + +/* From paints.cc */ +void xnjsmb_paints_init_mb_rt_temp(v8::Handle rt_temp); + +#endif /* __MBFLY_NJS_H_ */ diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/paints.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/paints.cc Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,206 @@ +#include + +extern "C" { +#include "mb.h" +} + +#include "mbfly_njs.h" + +using namespace v8; + +#ifndef ASSERT +#define ASSERT(x) +#endif + + +/*! \brief Fill a shape with the paint. + */ +static Handle +xnjsmb_paint_fill(const Arguments &args) { + int argc = args.Length(); + Handle self = args.This(); + Handle sh_obj; + Handle rt; + Handle rt_val; + paint_t *paint; + shape_t *sh; + redraw_man_t *rdman; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + if(!args[0]->IsObject()) + THROW("Invalid argument type (shape)"); + + paint = (paint_t *)UNWRAP(self); + + sh_obj = args[0]->ToObject(); + sh = (shape_t *)UNWRAP(sh_obj); + + rt_val = GET(self, "mbrt"); + rt = rt_val->ToObject(); + rdman = xnjsmb_rt_rdman(rt); + + rdman_paint_fill(rdman, paint, sh); + + rdman_shape_changed(rdman, sh); + + return Null(); +} + +/*! \brief Stroke a shape with the paint. + */ +static Handle +xnjsmb_paint_stroke(const Arguments &args) { + int argc = args.Length(); + Handle self = args.This(); + Handle sh_obj; + Handle rt; + Handle rt_val, sh_val; + paint_t *paint; + shape_t *sh; + redraw_man_t *rdman; + + if(argc != 1) + THROW("Invalid number of arguments (!= 1)"); + if(!args[0]->IsObject()) + THROW("Invalid argument type (shape)"); + + paint = (paint_t *)UNWRAP(self); + + sh_val = args[0]; + sh_obj = sh_val->ToObject(); + sh = (shape_t *)UNWRAP(sh_obj); + + rt_val = GET(self, "mbrt"); + rt = rt_val->ToObject(); + rdman = xnjsmb_rt_rdman(rt); + + rdman_paint_stroke(rdman, paint, sh); + + rdman_shape_changed(rdman, sh); + + return Null(); +} + +/*! \brief Constructor of color paint_color_t object for Javascript. + */ +static Handle +xnjsmb_paint_color(const Arguments &args) { + int argc = args.Length(); + Handle self = args.This(); + Handle rt; + redraw_man_t *rdman; + paint_t *paint; + float r, g, b, a; + + if(argc != 5) + THROW("Invalid number of arguments (!= 5)"); + if(!args[0]->IsObject() || !args[1]->IsNumber() || + !args[2]->IsNumber() || !args[3]->IsNumber() || + !args[4]->IsNumber()) + THROW("Invalid argument type"); + + rt = args[0]->ToObject(); + r = args[1]->ToNumber()->Value(); + g = args[2]->ToNumber()->Value(); + b = args[3]->ToNumber()->Value(); + a = args[4]->ToNumber()->Value(); + + rdman = xnjsmb_rt_rdman(rt); + paint = rdman_paint_color_new(rdman, r, g, b, a); + ASSERT(sh != NULL); + + WRAP(self, paint); + SET(self, "mbrt", rt); + + return Null(); +} + +static Persistent xnjsmb_paint_temp; +static Persistent xnjsmb_paint_color_temp; + +/*! \brief Create and return a paint_color object. + */ +static Handle +xnjsmb_paint_color_new(const Arguments &args) { + HandleScope scope; + Handle rt = args.This(); + Handle paint_color_obj; + Handle paint_color_func; + Handle pc_args[5]; + int argc; + int i; + + argc = args.Length(); + if(argc != 4) + THROW("Invalid number of arguments (r, g, b, a)"); + for(i = 0; i < 4; i++) + if(!args[i]->IsNumber()) + THROW("Invalid argument type"); + + pc_args[0] = rt; + pc_args[1] = args[0]; // r + pc_args[2] = args[1]; // g + pc_args[3] = args[2]; // b + pc_args[4] = args[3]; // a + paint_color_func = xnjsmb_paint_color_temp->GetFunction(); + paint_color_obj = paint_color_func->NewInstance(5, pc_args); + + scope.Close(paint_color_obj); + return paint_color_obj; +} + +static Persistent xnjsmb_paint_color_new_temp; + +/*! \brief Create templates for paint types. + * + * This function is only called one time for every execution. + */ +static void +xnjsmb_init_paints(void) { + Handle temp, meth; + Handle inst_temp; + Handle proto_temp; + + /* + * Base type of paint types. + */ + temp = FunctionTemplate::New(); + xnjsmb_paint_temp = Persistent::New(temp); + xnjsmb_paint_temp->SetClassName(String::New("paint")); + + meth = FunctionTemplate::New(xnjsmb_paint_fill); + proto_temp = xnjsmb_paint_temp->PrototypeTemplate(); + SET(proto_temp, "fill", meth); + + meth = FunctionTemplate::New(xnjsmb_paint_stroke); + proto_temp = xnjsmb_paint_temp->PrototypeTemplate(); + SET(proto_temp, "stroke", meth); + + /* + * Paint color + */ + temp = FunctionTemplate::New(xnjsmb_paint_color); + xnjsmb_paint_color_temp = Persistent::New(temp); + xnjsmb_paint_color_temp->SetClassName(String::New("paint_color")); + xnjsmb_paint_color_temp->Inherit(xnjsmb_paint_temp); + + inst_temp = xnjsmb_paint_color_temp->InstanceTemplate(); + inst_temp->SetInternalFieldCount(1); + + temp = FunctionTemplate::New(xnjsmb_paint_color_new); + xnjsmb_paint_color_new_temp = Persistent::New(temp); +} + +void xnjsmb_paints_init_mb_rt_temp(Handle rt_temp) { + static int init_flag = 0; + Handle rt_proto_temp; + + if(!init_flag) { + xnjsmb_init_paints(); + init_flag = 1; + } + + rt_proto_temp = rt_temp->PrototypeTemplate(); + SET(rt_proto_temp, "paint_color_new", xnjsmb_paint_color_new_temp); +} diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/shapes.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/shapes.cc Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,213 @@ +#include +#include "mbfly_njs.h" + +extern "C" { +#include +} + +#ifndef ASSERT +#define ASSERT(x) +#endif + +using namespace v8; + +/*! \defgroup shape_temp Templates for shape and derivations. + * + * @{ + */ +static Persistent xnjsmb_shape_temp; + +static Handle +xnjsmb_shape_show(const Arguments &args) { + shape_t *sh; + Handle self; + + self = args.This(); + sh = (shape_t *)UNWRAP(self); + sh_show(sh); + + return Null(); +} + +static Handle +xnjsmb_shape_hide(const Arguments &args) { + shape_t *sh; + Handle self; + + self = args.This(); + sh = (shape_t *)UNWRAP(self); + sh_hide(sh); + + return Null(); +} + +/*! \brief Get stroke width of a shape. + */ +static Handle +xnjsmb_shape_stroke_width_getter(Local property, + const AccessorInfo &info) { + Handle self = info.This(); + shape_t *sh; + float w; + Handle w_val; + + sh = (shape_t *)UNWRAP(self); + w = sh_get_stroke_width(sh); + w_val = Number::New(w); + + return w_val; +} + +/*! \brief Set stroke width of a shape. + */ +static void +xnjsmb_shape_stroke_width_setter(Local property, + Local value, + const AccessorInfo &info) { + Handle self = info.This(); + Handle rt; + shape_t *sh; + redraw_man_t *rdman; + float w; + Handle w_num; + + sh = (shape_t *)UNWRAP(self); + w_num = value->ToNumber(); + w = w_num->Value(); + + sh_set_stroke_width(sh, w); + + /* + * Mark changed. + */ + rt = GET(self, "mbrt")->ToObject(); + ASSERT(rt != NULL); + rdman = xnjsmb_rt_rdman(rt); + + rdman_shape_changed(rdman, sh); +} + +static void +xnjsmb_init_shape_temp(void) { + Handle temp; + Handle proto_temp; + Handle method_temp; + + temp = FunctionTemplate::New(); + temp->SetClassName(String::New("shape")); + xnjsmb_shape_temp = Persistent::New(temp); + proto_temp = temp->PrototypeTemplate(); + + method_temp = FunctionTemplate::New(xnjsmb_shape_show); + SET(proto_temp, "show", method_temp); + method_temp = FunctionTemplate::New(xnjsmb_shape_hide); + SET(proto_temp, "hide", method_temp); + + proto_temp->SetAccessor(String::New("stroke_width"), + xnjsmb_shape_stroke_width_getter, + xnjsmb_shape_stroke_width_setter); +} + +/* @} */ + +/*! \defgroup path_temp Templates for path objects. + * + * @{ + */ +static Persistent xnjsmb_path_temp; + +/*! \brief Callback of constructor of path objects for Javascript. + */ +static Handle +xnjsmb_shape_path(const Arguments &args) { + shape_t *sh; + redraw_man_t *rdman; + Handle self = args.This(); // path object + Handle rt; + char *dstr; + int argc; + + argc = args.Length(); + if(argc != 2) + THROW("Invalid number of arugments (!= 1)"); + if(!args[0]->IsString()) + THROW("Invalid argument type (should be a string)"); + if(!args[1]->IsObject()) + THROW("Invalid argument type (should be an object)"); + + String::Utf8Value dutf8(args[0]->ToString()); + dstr = *dutf8; + + rt = args[1]->ToObject(); + rdman = xnjsmb_rt_rdman(rt); + sh = rdman_shape_path_new(rdman, dstr); + + WRAP(self, sh); + SET(self, "mbrt", rt); + + return Null(); +} + +/*! \brief Initial function template for constructor of path objects. + */ +static void +xnjsmb_init_path_temp(void) { + Handle temp; + Handle inst_temp; + + temp = FunctionTemplate::New(xnjsmb_shape_path); + temp->Inherit(xnjsmb_shape_temp); + temp->SetClassName(String::New("path")); + + inst_temp = temp->InstanceTemplate(); + inst_temp->SetInternalFieldCount(1); + + xnjsmb_path_temp = Persistent::New(temp); +} + +/*! \brief Callback function of mb_rt.path_new(). + */ +static Handle +xnjsmb_shape_path_new(const Arguments &args) { + HandleScope scope; + Handle self = args.This(); // runtime object + Handle path_obj; + Handle path_args[2]; + int argc; + + argc = args.Length(); + if(argc != 1) + THROW("Invalid number of arugments (!= 1)"); + if(!args[0]->IsString()) + THROW("Invalid argument type (shoud be a string)"); + + path_args[0] = args[0]; + path_args[1] = self; + + path_obj = xnjsmb_path_temp->GetFunction()->NewInstance(2, path_args); + + scope.Close(path_obj); + return path_obj; +} + +/* @} */ + +/*! \brief Set properties of template of mb_rt. + */ +void +xnjsmb_shapes_init_mb_rt_temp(Handle rt_temp) { + Handle path_new_temp; + Handle rt_proto_temp; + static int temp_init_flag = 0; + + if(temp_init_flag == 0) { + xnjsmb_init_shape_temp(); + xnjsmb_init_path_temp(); + temp_init_flag = 1; + } + + rt_proto_temp = rt_temp->PrototypeTemplate(); + + path_new_temp = FunctionTemplate::New(xnjsmb_shape_path_new); + SET(rt_proto_temp, "path_new", path_new_temp); +} diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/testcase.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/testcase.js Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,37 @@ +var mbfly = require("mbfly"); +var r = mbfly.Hello(" test"); +var sys = require("sys"); +sys.puts(r); + +var mb_rt = new mbfly.mb_rt(":0.0", 300, 200); +var root = mb_rt.root; +sys.puts("root matrix: " + + [root[0], root[1], root[2], root[3], root[4], root[5]]); +var coord = mb_rt.coord_new(root); +sys.puts("coord matrix: " + + [coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]]); + +sys.puts(mb_rt.path_new); +var path = mb_rt.path_new("m 100,50 L 120,50 L 200,150 L 180,150 z"); +sys.puts(path); +sys.puts(coord.add_shape); +coord.add_shape(path); + +sys.puts(mb_rt.paint_color_new); +var paint = mb_rt.paint_color_new(1.0, 1.0, 1.0, 1.0); +sys.puts(paint); +paint.stroke(path); + +sys.puts(path.stroke_width); +path.stroke_width = 2; +sys.puts(path.stroke_width); + +mb_rt.redraw_all(); + +var i = 0; +setInterval(function() { + var deg = (i++) * 0.1; + coord[2] = (i % 20) * 10; + mb_rt.redraw_changed(); + }, 50); +setTimeout(function() { sys.puts("timeout"); }, 1000); diff -r aa2b388fba4e -r dcd7adb2c0fc nodejs/wscript --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nodejs/wscript Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,33 @@ +srcdir = '.' +blddir = 'build' +VERSION = '0.0.1' + +def set_options(opt): + opt.tool_options('compiler_cxx') + opt.tool_options('compiler_cc') + pass + +def configure(conf): + import Options + import os + + conf.check_tool('compiler_cxx') + conf.check_tool('compiler_cc') + conf.check_tool('node_addon') + conf.env.SRCDIR = Options.options.srcdir + conf.env.TOP_BUILDDIR = os.environ['TOP_BUILDDIR'] + pass + +def build(conf): + import Utils + + obj = conf.new_task_gen('cxx', 'shlib', 'node_addon') + obj.target = 'mbfly' + obj.source = 'mbfly_njs.cc coord.cc shapes.cc paints.cc' + obj.add_objects = 'X_supp_njs.o' + obj.staticlib = 'mbfly' + + obj = conf.new_task_gen('cc', 'shlib', 'node_addon') + obj.target = 'X_supp_njs.o' + obj.source = 'X_supp_njs.c' + pass diff -r aa2b388fba4e -r dcd7adb2c0fc src/Makefile.am --- a/src/Makefile.am Sun Nov 08 00:37:29 2009 +0800 +++ b/src/Makefile.am Wed Jun 09 17:30:09 2010 +0800 @@ -12,11 +12,16 @@ noinst_PROGRAMS += testcase endif +if X_SUPP MBAF_SOURCES=mbaf/mbapp.c mbaf/mbbutton.c mbaf/mbobject.c mbaf/animated_menu.c +else +MBAF_SOURCES= +endif + libmbfly_la_SOURCES= animate.c chgcolor.c coord.c event.c geo.c \ observer.c paint.c redraw_man.c rotate.c shape_path.c \ shape_rect.c shift.c subtree_free.c timer.c \ - timertool.c tools.c visibility.c X_supp.c prop.c sprite.c \ + timertool.c tools.c visibility.c prop.c sprite.c \ mouse.c shape_image.c img_ldr.c $(MBAF_SOURCES) if SH_TEXT @@ -27,8 +32,20 @@ libmbfly_la_SOURCES += shape_stext.c endif +if X_SUPP +libmbfly_la_SOURCES += X_supp.c +endif + +if CAIRO_GRAPH_ENGINE +libmbfly_la_SOURCES += graph_engine_cairo.c + libmbfly_la_CPPFLAGS = @cairo_CFLAGS@ @pangocairo_CFLAGS@ libmbfly_la_LDFLAGS = @cairo_LIBS@ @pangocairo_LIBS@ +endif + +if SKIA_GRAPH_ENGINE +libmbfly_la_SOURCES += graph_engine_skia.cpp +endif X_main_SOURCES = X_main.c X_main_LDADD = $(top_builddir)/src/libmbfly.la diff -r aa2b388fba4e -r dcd7adb2c0fc src/X_main.c --- a/src/X_main.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/X_main.c Wed Jun 09 17:30:09 2010 +0800 @@ -122,6 +122,7 @@ void draw_path(mbe_t *cr, int w, int h) { mbe_t *tmpcr; mbe_surface_t *tmpsuf; + mbe_pattern_t *tmpptn; redraw_man_t rdman; shape_t *path1, *path2, *rect; coord_t *coord1, *coord2, *coord3; @@ -141,9 +142,10 @@ PangoAttrList *attrs = pango_attr_list_new(); tmpsuf = mbe_image_surface_create(MB_IFMT_ARGB32, w, h); + tmpptn = mbe_pattern_create_for_surface(tmpsuf); tmpcr = mbe_create(tmpsuf); - mbe_set_source_surface(cr, tmpsuf, 0, 0); + mbe_set_source(cr, tmpptn); redraw_man_init(&rdman, tmpcr, cr); coord1 = rdman_coord_new(&rdman, rdman.root_coord); coord2 = rdman_coord_new(&rdman, rdman.root_coord); diff -r aa2b388fba4e -r dcd7adb2c0fc src/X_supp.c --- a/src/X_supp.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/X_supp.c Wed Jun 09 17:30:09 2010 +0800 @@ -37,6 +37,7 @@ Window win; Visual *visual; mbe_surface_t *surface, *backend_surface; + mbe_pattern_t *surface_ptn; mbe_t *cr, *backend_cr; redraw_man_t *rdman; mb_tman_t *tman; @@ -201,6 +202,10 @@ int in_stroke; int r; + /* XXX: For some unknown reason, it causes a segmentation fault to + * called XEventsQueued() after receiving first Expose event + * and before redraw for the event. + */ while(XEventsQueued(display, QueuedAfterReading) > 0) { r = XNextEvent(display, &evt); if(r == -1) @@ -466,6 +471,9 @@ xmb_rt->surface = mbe_image_surface_create(MB_IFMT_ARGB32, w, h); + + xmb_rt->surface_ptn = + mbe_pattern_create_for_surface(xmb_rt->surface); xmb_rt->backend_surface = mbe_xlib_surface_create(xmb_rt->display, @@ -476,7 +484,7 @@ xmb_rt->cr = mbe_create(xmb_rt->surface); xmb_rt->backend_cr = mbe_create(xmb_rt->backend_surface); - mbe_set_source_surface(xmb_rt->backend_cr, xmb_rt->surface, 0, 0); + mbe_set_source(xmb_rt->backend_cr, xmb_rt->surface_ptn); xmb_rt->rdman = (redraw_man_t *)malloc(sizeof(redraw_man_t)); redraw_man_init(xmb_rt->rdman, xmb_rt->cr, xmb_rt->backend_cr); @@ -522,6 +530,8 @@ if(xmb_rt->surface) mbe_surface_destroy(xmb_rt->surface); + if(xmb_rt->surface_ptn) + mbe_pattern_destroy(xmb_rt->surface_ptn); if(xmb_rt->backend_surface) mbe_surface_destroy(xmb_rt->backend_surface); @@ -540,8 +550,10 @@ return NULL; r = X_MB_init(display_name, w, h, rt); - if(r != OK) + if(r != OK) { + free(rt); return NULL; + } return rt; } @@ -583,7 +595,7 @@ return img_ldr; } -void X_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) +void X_MB_add_event(void *rt, int type, int fd, mb_eventcb_t f,void *arg) { X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; int i; @@ -613,7 +625,7 @@ xmb_rt->n_monitor=i; } -void X_remove_event(void *rt, int type, int fd) +void X_MB_remove_event(void *rt, int type, int fd) { X_MB_runtime_t *xmb_rt = (X_MB_runtime_t *) rt; int i; @@ -626,8 +638,8 @@ } mb_backend_t backend = { X_MB_new, X_MB_free, - X_add_event, - X_remove_event, + X_MB_add_event, + X_MB_remove_event, X_MB_handle_connection, X_MB_kbevents, X_MB_rdman, @@ -635,4 +647,27 @@ X_MB_ob_factory, X_MB_img_ldr }; - +/*! \defgroup x_supp_nodejs_sup Export functions for supporting nodejs plugin. + * + * These functions are for internal using. + * @{ + */ +/*! \brief Exported for nodejs plugin to call handle_x_event. + */ +void _X_MB_handle_x_event_for_nodejs(void *rt) { + handle_x_event((X_MB_runtime_t *)rt); +} + +/*! \brief Get X connect for nodejs plugin. + */ +int _X_MB_get_x_conn_for_nodejs(void *rt) { + return XConnectionNumber(((X_MB_runtime_t *)rt)->display); +} + +/*! \brief Flush buffer for the X connection of a runtime object. + */ +int _X_MB_flush_x_conn_for_nodejs(void *rt) { + return XFlush(((X_MB_runtime_t *)rt)->display); +} + +/* @} */ diff -r aa2b388fba4e -r dcd7adb2c0fc src/coord.c --- a/src/coord.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/coord.c Wed Jun 09 17:30:09 2010 +0800 @@ -63,7 +63,7 @@ * matrix as aggregated matrix. */ static void compute_transform_function(coord_t *visit) { - if(visit->parent) + if(!coord_is_root(visit)) mul_matrix(visit->parent->aggr_matrix, visit->matrix, visit->aggr_matrix); else @@ -83,7 +83,7 @@ co_aix cache_p_matrix[6]; co_aix cache_scale_x, cache_scale_y; - if(visit->parent) { + if(!coord_is_root(visit)) { p_matrix = coord_get_aggr_matrix(visit->parent); cache_scale_x = sqrtf(p_matrix[0] * p_matrix[0] + p_matrix[3] * p_matrix[3]); @@ -105,6 +105,14 @@ compute_transform_function_cached(coord); } +void +compute_aggr(coord_t *coord) { + if(coord->flags & COF_OWN_CANVAS) + compute_transform_function_cached(coord); + else + compute_transform_function(coord); +} + void compute_reverse(co_aix *orig, co_aix *reverse) { co_aix working[6]; co_aix factor; diff -r aa2b388fba4e -r dcd7adb2c0fc src/event.c --- a/src/event.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/event.c Wed Jun 09 17:30:09 2010 +0800 @@ -9,7 +9,7 @@ #include "mb_redraw_man.h" #include "mb_shapes.h" #endif -#include "../config.h" +#include "config.h" #define OK 0 #define ERR -1 diff -r aa2b388fba4e -r dcd7adb2c0fc src/graph_engine_cairo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/graph_engine_cairo.c Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,154 @@ +#include +#include +#include "mb_graph_engine_cairo.h" +#include "mb_shapes.h" + +#ifndef ASSERT +#define ASSERT(x) +#endif + +/*! \brief Find out a font pattern. + * + * This function use fontconfig to decide a font file in pattern. It can + * replaced by other mechanism if you think it is not what you want. + * + * \param slant make font prune if it it non-zero. + * \param weight make font normal if it is 100. + */ +static +FcPattern *query_font_pattern(const char *family, int slant, int weight) { + FcPattern *ptn, *p, *fn_ptn; + FcValue val; + FcConfig *cfg; + FcBool r; + FcResult result; + static int slant_map[] = { /* from MB_FONT_SLANT_* to FC_SLANT_* */ + FC_SLANT_ROMAN, + FC_SLANT_ROMAN, + FC_SLANT_ITALIC, + FC_SLANT_OBLIQUE}; + + cfg = FcConfigGetCurrent(); + ptn = FcPatternCreate(); + p = FcPatternCreate(); + if(ptn == NULL || p == NULL) + goto err; + + val.type = FcTypeString; + val.u.s = family; + FcPatternAdd(ptn, "family", val, FcTrue); + + val.type = FcTypeInteger; + val.u.i = slant_map[slant]; + FcPatternAdd(ptn, "slant", val, FcTrue); + + val.type = FcTypeInteger; + val.u.i = weight; + FcPatternAdd(ptn, "weight", val, FcTrue); + + r = FcConfigSubstituteWithPat(cfg, ptn, NULL, FcMatchPattern); + if(!r) + goto err; + + r = FcConfigSubstituteWithPat(cfg, p, ptn, FcMatchFont); + if(!r) + goto err; + + FcDefaultSubstitute(p); + + fn_ptn = FcFontMatch(cfg, p, &result); + + /* It is supposed to return FcResultMatch. But, it is no, now. + * I don't know why. Someone should figure out the issue. + */ +#if 0 + if(result != FcResultMatch) { + printf("%d %d\n", result, FcResultMatch); + goto err; + } +#endif + if(fn_ptn == NULL) + goto err; + + FcPatternDestroy(ptn); + FcPatternDestroy(p); + + return fn_ptn; + +err: + if(ptn) + FcPatternDestroy(ptn); + if(p) + FcPatternDestroy(p); + return NULL; + +} + +/*! \brief Find out a font face for a pattern specified. + * + * The pattern, here, is a vector of family, slant, and weight. + * This function base on fontconfig and cairo FreeType font supporting. + * You can replace this function with other font mechanisms. + */ +mbe_font_face_t * +mbe_query_font_face(const char *family, int slant, int weight) { + mbe_font_face_t *cface; + FcPattern *ptn; + + ptn = query_font_pattern(family, slant, weight); + cface = cairo_ft_font_face_create_for_pattern(ptn); + FcPatternDestroy(ptn); + + return cface; +} + +void +mbe_free_font_face(mbe_font_face_t *face) { + ASSERT(face == NULL); + + mbe_font_face_destroy(face); +} + +mbe_pattern_t * +mbe_pattern_create_radial(co_aix cx0, co_aix cy0, co_aix radius0, + co_aix cx1, co_aix cy1, co_aix radius1, + grad_stop_t *stops, int stop_cnt) { + cairo_pattern_t *ptn; + grad_stop_t *stop; + int i; + + ptn = cairo_pattern_create_radial(cx0, cy0, radius0, + cx1, cy1, radius1); + if(ptn == NULL) + return NULL; + + stop = stops; + for(i = 0; i < stop_cnt; i++) { + cairo_pattern_add_color_stop_rgba(ptn, stop->offset, + stop->r, stop->g, stop->b, stop->a); + stop++; + } + + return ptn; +} + +mbe_pattern_t * +mbe_pattern_create_linear(co_aix x0, co_aix y0, co_aix x1, co_aix y1, + grad_stop_t *stops, int stop_cnt) { + cairo_pattern_t *ptn; + grad_stop_t *stop; + int i; + + ptn = cairo_pattern_create_linear(x0, y0, x1, y1); + if(ptn == NULL) + return NULL; + + stop = stops; + for(i = 0; i < stop_cnt; i++) { + cairo_pattern_add_color_stop_rgba(ptn, stop->offset, + stop->r, stop->g, stop->b, stop->a); + stop++; + } + + return ptn; +} diff -r aa2b388fba4e -r dcd7adb2c0fc src/graph_engine_skia.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/graph_engine_skia.cpp Wed Jun 09 17:30:09 2010 +0800 @@ -0,0 +1,869 @@ +/*! \page ge_layer Graphic Engine Layer + * + * Graphic Engine Layer is an abstract of graphic engine; likes Cairo + * and Skia. It provides portability for the rest of MadButterfly. + * + * The basic stratage of interface of graphic engine layer is defined + * according purpose of MadButterfly. For example, MadButterfly wants + * a function that can clear a canvas, we define a clear function. + * Never define a indirectly way to finish the function. Never define + * a way to finish the function for the reason that some engine + * require you to finish the task in that procedure. It avoids + * binding graphic engine layer with any behavior of a graphic engine, + * and provides more compatible with other engines, to define + * interface of graphic engine layer according purpose of + * MadButterfly. + * + * \section ge_mem Graphic Engine Layer Memory Management + * + * MadButterfly is responsible for management of objects and memory + * blocks returned by graphic engine layer, even for graphic engines + * that have management model. MadButterfly supposes memory blocks + * only be released when they are no more used. MadBufferfly is + * responsible for release them. So, even a graphic engine has + * reference count with objects, MadButterfly still keep a reference + * for every object returned by the engine until no one will use it. + * + * \section ge_transform Transformation of Coordination System + * + * Points of pathes are transformed when it is added to the canvas + * with the transformation matrix at the time. So, changes of + * transformation matrix of an canvas will not affect points that had + * been added. It only affects points been added when the matrix is + * setted. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define C_START extern "C" { +#define C_END } + +C_START + +#include "mb_graph_engine_skia.h" +#include "mb_shapes.h" +#include "mb_img_ldr.h" + +/*! \brief Source pattern + * + * For Skia, source pattern is SkShader with some decoration. Since + * SkShade will repeative tiling or extenting edge color, it can not + * stop tiling and extenting for fixed size bitmap. So, we need to + * translate mbe_paint() into a drawing of a rectangle. + */ +struct _mbe_pattern_t { + SkShader *shader; + int w, h; + int has_size; + co_aix matrix[6]; +}; + +struct _mbe_scaled_font_t { + struct _mb_font_face_t *face; + co_aix fnt_mtx[6]; + co_aix ctm[6]; +}; +struct _mbe_font_face_t {}; +/*! \brief MadButterfly Graphic Engine Context. + * + * A context comprises source pattern, target surface, path, + * line-width, and transform matrix. + */ +struct _mbe_t { + SkCanvas *canvas; + SkPath *path, *subpath; + SkPaint *paint; + SkRegion *saved_region; + + struct _mbe_states_t *states; +}; + +struct _mbe_states_t { + mbe_pattern_t *ptn; + int ptn_owned; + co_aix line_width; + co_aix matrix[6]; + struct _mbe_states_t *next; +}; + +#ifndef ASSERT +#define ASSERT(x) +#endif + +#define PI 3.1415926535897931 + +#define CO_AIX_2_SKSCALAR(a) ((SkScalar)a) +#define SKSCALAR_2_CO_AIX(a) ((co_aix)(a)) +#define MB_MATRIX_2_SKMATRIX(sk, mb) { \ + (sk).setScaleX(CO_AIX_2_SKSCALAR((mb)[0])); \ + (sk).setSkewX(CO_AIX_2_SKSCALAR((mb)[1])); \ + (sk).setTranslateX(CO_AIX_2_SKSCALAR((mb)[2])); \ + (sk).setSkewY(CO_AIX_2_SKSCALAR((mb)[3])); \ + (sk).setScaleY(CO_AIX_2_SKSCALAR((mb)[4])); \ + (sk).setTranslateY(CO_AIX_2_SKSCALAR((mb)[5])); \ + (sk).setPerspX(0); \ + (sk).setPerspY(0); \ + (sk).set(SkMatrix::kMPersp2, 1); \ + } +#define SKMATRIX_2_MB_MATRIX(mb, sk) { \ + (mb)[0] = SKSCALAR_2_CO_AIX((sk).getScaleX()); \ + (mb)[1] = SKSCALAR_2_CO_AIX((sk).getSkewX()); \ + (mb)[2] = SKSCALAR_2_CO_AIX((sk).getTranslateX()); \ + (mb)[3] = SKSCALAR_2_CO_AIX((sk).getSkewY()); \ + (mb)[4] = SKSCALAR_2_CO_AIX((sk).getScaleY()); \ + (mb)[5] = SKSCALAR_2_CO_AIX((sk).getTranslateY()); \ + } +#define MBSTOP_2_SKCOLOR(c) \ + ((((int)((c)->a * 255)) << 24) | \ + (((int)((c)->r * 255)) << 16) | \ + (((int)((c)->g * 255)) << 8) | \ + (((int)((c)->b * 255)))) +#define MB_CO_COMP_2_SK(c) (((int)((c) * 255)) & 0xff) + +static const co_aix id_matrix[6] = { 1, 0, 0, 0, 1, 0 }; + +static void +_prepare_sized_pattern(mbe_t *mbe, mbe_pattern_t *ptn) { + SkCanvas *canvas = mbe->canvas; + SkPath path; + co_aix x, y; + co_aix reverse[6]; + + *mbe->saved_region = canvas->getTotalClip(); + + compute_reverse(ptn->matrix, reverse); + x = 0; y = 0; + matrix_trans_pos(reverse, &x, &y); + path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); + x = 0; y = ptn->h; + matrix_trans_pos(reverse, &x, &y); + path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); + x = ptn->w; y = ptn->h; + matrix_trans_pos(reverse, &x, &y); + path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); + path.close(); + + canvas->clipPath(path, SkRegion::kIntersect_Op); +} + +static void +_finish_sized_pattern(mbe_t *mbe) { + SkCanvas *canvas = mbe->canvas; + + canvas->setClipRegion(*mbe->saved_region); +} + +static void +_canvas_device_region(SkCanvas *canvas, SkRegion *region) { + SkDevice *device; + int w, h; + + device = canvas->getDevice(); + w = device->width(); + h = device->height(); + region->setRect(0, 0, w, h); +} + +static void +_update_path(mbe_t *mbe) { + SkPath *path = mbe->path; + SkPath *subpath = mbe->subpath; + SkMatrix canvas_matrix; + SkPoint point; + + MB_MATRIX_2_SKMATRIX(canvas_matrix, mbe->states->matrix); + path->addPath(*subpath, canvas_matrix); + + subpath->getLastPt(&point); + subpath->rewind(); + subpath->moveTo(point); +} + +/* + * When a function want to use the paint associated with a canvas to + * draw, it should call _prepare_paint() can make the paint ready. + * And, call _finish_paint() when the paint is no more used. + */ +static void +_prepare_paint(mbe_t *mbe, SkPaint::Style style) { + SkPaint *paint = mbe->paint; + mbe_pattern_t *ptn = mbe->states->ptn; + SkShader *shader; + co_aix matrix[6]; + SkMatrix skmatrix; + + paint->setStyle(style); + + if(ptn != NULL) { + /* Local matrix of SkShader is a mapping from source pattern to + * user space. Unlikely, for Cairo is a mapping from user space + * to source pattern. + */ + shader = ptn->shader; + matrix_mul(mbe->states->matrix, ptn->matrix, matrix); + MB_MATRIX_2_SKMATRIX(skmatrix, matrix); + shader->setLocalMatrix(skmatrix); + paint->setShader(shader); + } + + if(style == SkPaint::kStroke_Style) + paint->setStrokeWidth(CO_AIX_2_SKSCALAR(mbe->states->line_width)); + + if(ptn != NULL && ptn->has_size) + _prepare_sized_pattern(mbe, ptn); +} + +static void +_finish_paint(mbe_t *mbe) { + mbe_pattern_t *ptn = mbe->states->ptn; + + mbe->paint->reset(); + if(ptn != NULL && ptn->has_size) + _finish_sized_pattern(mbe); +} + +mbe_pattern_t *mbe_pattern_create_for_surface(mbe_surface_t *surface) { + mbe_pattern_t *ptn; + SkBitmap *bitmap = (SkBitmap *)surface; + + ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); + ptn->shader = SkShader::CreateBitmapShader(*bitmap, + SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode); + if(ptn->shader == NULL) { + free(ptn); + return NULL; + } + + ptn->has_size = 1; + ptn->w = bitmap->width(); + ptn->h = bitmap->height(); + + memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); + + return ptn; +} + +mbe_pattern_t * +mbe_pattern_create_radial(co_aix cx0, co_aix cy0, co_aix radius0, + co_aix cx1, co_aix cy1, co_aix radius1, + grad_stop_t *stops, int stop_cnt) { + mbe_pattern_t *ptn; + SkColor *colors; + SkScalar *poses; + grad_stop_t *stop; + SkPoint center; + int i; + + ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); + colors = new SkColor[stop_cnt]; + poses = new SkScalar[stop_cnt]; + if(ptn == NULL || colors == NULL || poses == NULL) + goto fail; + + center.set(CO_AIX_2_SKSCALAR(cx1), CO_AIX_2_SKSCALAR(cy1)); + + stop = stops; + for(i = 0; i < stop_cnt; i++) { + colors[i] = MBSTOP_2_SKCOLOR(stop); + poses[i] = CO_AIX_2_SKSCALAR(stop->offset); + } + + /* + * cx0, cy0 and radius0 is not used. Since Skia is still not + * support two circles radial. And, SVG 1.2 is also not support + * two circles. + */ + ptn->shader = + SkGradientShader::CreateRadial(center, CO_AIX_2_SKSCALAR(radius1), + colors, poses, stop_cnt, + SkShader::kClamp_TileMode); + if(ptn->shader == NULL) + goto fail; + + memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); + + delete colors; + delete poses; + return ptn; + + fail: + if(ptn) free(ptn); + if(colors) delete colors; + if(poses) delete poses; + return NULL; +} + +mbe_pattern_t * +mbe_pattern_create_linear(co_aix x0, co_aix y0, + co_aix x1, co_aix y1, + grad_stop_t *stops, int stop_cnt) { + mbe_pattern_t *ptn; + SkColor *colors; + SkScalar *poses; + grad_stop_t *stop; + SkPoint points[2]; + int i; + + ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); + colors = new SkColor[stop_cnt]; + poses = new SkScalar[stop_cnt]; + if(ptn == NULL || colors == NULL || poses == NULL) + goto fail; + + points[0].set(CO_AIX_2_SKSCALAR(x0), CO_AIX_2_SKSCALAR(y0)); + points[1].set(CO_AIX_2_SKSCALAR(x1), CO_AIX_2_SKSCALAR(y1)); + + stop = stops; + for(i = 0; i < stop_cnt; i++) { + colors[i] = MBSTOP_2_SKCOLOR(stop); + poses[i] = CO_AIX_2_SKSCALAR(stop->offset); + } + + /* + * cx0, cy0 and radius0 is not used. Since Skia is still not + * support two circles radial. And, SVG 1.2 is also not support + * two circles. + */ + ptn->shader = + SkGradientShader::CreateLinear(points, colors, poses, stop_cnt, + SkShader::kClamp_TileMode); + if(ptn->shader == NULL) + goto fail; + + memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); + + delete colors; + delete poses; + return ptn; + + fail: + if(ptn) free(ptn); + if(colors) delete colors; + if(poses) delete poses; + return NULL; +} + +void mbe_pattern_set_matrix(mbe_pattern_t *ptn, const co_aix matrix[6]) { + SkMatrix skmatrix; + + MB_MATRIX_2_SKMATRIX(skmatrix, matrix); + + ptn->shader->setLocalMatrix(skmatrix); +} + +void mbe_pattern_destroy(mbe_pattern_t *ptn) { + if(ptn->shader) + delete ptn->shader; + free(ptn); +} + +int mbe_image_surface_get_stride(mbe_surface_t *surface) { + return ((SkBitmap *)surface)->rowBytes(); +} + +int mbe_image_surface_get_height(mbe_surface_t *surface) { + return ((SkBitmap *)surface)->height(); +} + +int mbe_image_surface_get_width(mbe_surface_t *surface) { + return ((SkBitmap *)surface)->width(); +} + +unsigned char *mbe_image_surface_get_data(mbe_surface_t *surface) { + return (unsigned char *)((SkBitmap *)surface)->getPixels(); +} + +mbe_surface_t *mbe_image_surface_create_from_png(const char *filename) {} + +mbe_surface_t * +mbe_image_surface_create_for_data(unsigned char *data, + mb_img_fmt_t fmt, + int width, int height, + int stride) { + SkBitmap *bitmap; + SkBitmap::Config cfg; + + switch(fmt) { + case MB_IFMT_ARGB32: + cfg = SkBitmap::kARGB_8888_Config; break; + + case MB_IFMT_A8: + cfg = SkBitmap::kA8_Config; break; + + case MB_IFMT_A1: + cfg = SkBitmap::kA1_Config; break; + + case MB_IFMT_RGB16_565: + cfg = SkBitmap::kRGB_565_Config; break; + + case MB_IFMT_RGB24: + default: + return NULL; + } + + bitmap = new SkBitmap(); + if(bitmap == NULL) + return NULL; + + bitmap->setConfig(cfg, width, height, stride); + bitmap->setPixels(data); + + return (mbe_surface_t *)bitmap; +} + +mb_img_fmt_t mbe_image_surface_get_format(mbe_surface_t *surface) { + SkBitmap *bitmap = (SkBitmap *)surface; + mb_img_fmt_t fmt; + SkBitmap::Config cfg; + + cfg = bitmap->getConfig(); + switch(cfg) { + case SkBitmap::kARGB_8888_Config: + fmt = MB_IFMT_ARGB32; break; + + case SkBitmap::kA8_Config: + fmt = MB_IFMT_A8; break; + + case SkBitmap::kA1_Config: + fmt = MB_IFMT_A1; break; + + case SkBitmap::kRGB_565_Config: + fmt = MB_IFMT_RGB16_565; break; + + default: + fmt = MB_IFMT_DUMMY; + } + + return fmt; +} + +mbe_surface_t * +mbe_image_surface_create(mb_img_fmt_t fmt, int width, int height) { + SkBitmap *bitmap; + SkBitmap::Config cfg; + + switch(fmt) { + case MB_IFMT_ARGB32: + cfg = SkBitmap::kARGB_8888_Config; break; + + case MB_IFMT_A8: + cfg = SkBitmap::kA8_Config; break; + + case MB_IFMT_A1: + cfg = SkBitmap::kA1_Config; break; + + case MB_IFMT_RGB16_565: + cfg = SkBitmap::kRGB_565_Config; break; + + case MB_IFMT_RGB24: + default: + return NULL; + } + + bitmap = new SkBitmap(); + if(bitmap == NULL) + return NULL; + + bitmap->setConfig(cfg, width, height); + bitmap->allocPixels(); + + return (mbe_surface_t *)bitmap; +} + +mbe_scaled_font_t *mbe_scaled_font_reference(mbe_scaled_font_t *scaled) { +} + +void mbe_scaled_font_destroy(mbe_scaled_font_t *scaled) {} +mbe_font_face_t *mbe_font_face_reference(mbe_font_face_t *face) {} +mbe_scaled_font_t * +mbe_scaled_font_create(mbe_font_face_t *face, co_aix fnt_mtx[6], + co_aix ctm[6]) {} +mbe_scaled_font_t *mbe_get_scaled_font(mbe_t *canvas) {} +void mbe_scaled_font_text_extents(mbe_scaled_font_t *scaled, + const char *txt, + mbe_text_extents_t *extents) {} + +void mbe_font_face_destroy(mbe_font_face_t *face) {} + +void mbe_paint_with_alpha(mbe_t *canvas, co_aix alpha) { + SkPaint *paint = canvas->paint; + SkColorFilter *filter; + SkColor color; + + color = ((uint32_t)(alpha * 255)) << 24; + filter = + SkColorFilter::CreatePorterDuffFilter(color, + SkPorterDuff::kSrcOver_Mode); + mbe_paint(canvas); + +} + +void mbe_surface_destroy(mbe_surface_t *surface) { + SkBitmap *bmap = (SkBitmap *)surface; + + delete bmap; +} + +void mbe_set_source_rgba(mbe_t *canvas, + co_aix r, co_aix g, co_aix b, co_aix a) { + canvas->paint->setARGB(MB_CO_COMP_2_SK(a), + MB_CO_COMP_2_SK(r), + MB_CO_COMP_2_SK(g), + MB_CO_COMP_2_SK(b)); + canvas->states->ptn = NULL; +} + +void mbe_set_scaled_font(mbe_t *canvas, + const mbe_scaled_font_t *scaled) {} +void mbe_set_source_rgb(mbe_t *canvas, co_aix r, co_aix g, co_aix b) {} + +void mbe_set_line_width(mbe_t *canvas, co_aix width) { + canvas->states->line_width = width; +} + +mbe_font_face_t *mbe_get_font_face(mbe_t *canvas) {} + +void mbe_fill_preserve(mbe_t *canvas) { + mbe_pattern_t *ptn = canvas->states->ptn; + SkPaint *paint = canvas->paint; + SkPath *path = canvas->path; + SkRegion *saved_clip = NULL; + co_aix x, y; + + ASSERT(paint); + ASSERT(ptn); + ASSERT(path); + + if(!canvas->subpath->isEmpty()) + _update_path(canvas); + + _prepare_paint(canvas, SkPaint::kFill_Style); + + canvas->canvas->drawPath(*path, *paint); + + _finish_paint(canvas); +} + +void mbe_set_source(mbe_t *canvas, mbe_pattern_t *source) { + canvas->states->ptn = source; +} + +void mbe_reset_clip(mbe_t *canvas) { + SkRegion clip; + + _canvas_device_region(canvas->canvas, &clip); + canvas->canvas->setClipRegion(clip); +} + +mbe_surface_t *mbe_get_target(mbe_t *canvas) { + return (mbe_surface_t *)&canvas->canvas->getDevice()->accessBitmap(false); +} + +void mbe_close_path(mbe_t *canvas) { + canvas->subpath->close(); +} + +void mbe_text_path(mbe_t *canvas, const char *txt) {} + +void mbe_rectangle(mbe_t *canvas, co_aix x, co_aix y, + co_aix width, co_aix height) { + SkPath *subpath = canvas->subpath; + + subpath->addRect(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y), + CO_AIX_2_SKSCALAR(x + width), + CO_AIX_2_SKSCALAR(y + height)); +} + +int mbe_in_stroke(mbe_t *canvas, co_aix x, co_aix y) { + return 0; +} + +void mbe_new_path(mbe_t *canvas) { + canvas->subpath->rewind(); + canvas->path->rewind(); +} + +void mbe_curve_to(mbe_t *canvas, co_aix x1, co_aix y1, + co_aix x2, co_aix y2, + co_aix x3, co_aix y3) { + SkPath *subpath = canvas->subpath; + + subpath->cubicTo(CO_AIX_2_SKSCALAR(x1), CO_AIX_2_SKSCALAR(y1), + CO_AIX_2_SKSCALAR(x2), CO_AIX_2_SKSCALAR(y2), + CO_AIX_2_SKSCALAR(x3), CO_AIX_2_SKSCALAR(y3)); +} + +void mbe_restore(mbe_t *canvas) { + struct _mbe_states_t *states; + + _update_path(canvas); + + states = canvas->states; + ASSERT(states->next); + canvas->states = states->next; + free(states); +} + +void mbe_move_to(mbe_t *canvas, co_aix x, co_aix y) { + canvas->subpath->moveTo(CO_AIX_2_SKSCALAR(x), + CO_AIX_2_SKSCALAR(y)); +} + +void mbe_line_to(mbe_t *canvas, co_aix x, co_aix y) { + canvas->subpath->lineTo(CO_AIX_2_SKSCALAR(x), + CO_AIX_2_SKSCALAR(y)); +} + +int mbe_in_fill(mbe_t *canvas, co_aix x, co_aix y) { + SkRegion region, dev_region; + bool in_fill; + + if(!canvas->subpath->isEmpty()) + _update_path(canvas); + + _canvas_device_region(canvas->canvas, &dev_region); + region.setPath(*canvas->path, dev_region); + + in_fill = region.contains(x, y); + + return in_fill; +} + +void mbe_stroke(mbe_t *canvas) { + SkPath *path = canvas->path; + SkPaint *paint = canvas->paint; + + ASSERT(ptn); + ASSERT(path); + ASSERT(paint); + + if(!canvas->subpath->isEmpty()) + _update_path(canvas); + + _prepare_paint(canvas, SkPaint::kStroke_Style); + + canvas->canvas->drawPath(*path, *paint); + + _finish_paint(canvas); + + path->rewind(); + canvas->subpath->rewind(); +} + +/*! \brief Create a mbe from a SkCanvas. + * + * It is only used for Android JNI. It is used to create mbe_t from a + * SkCanvas created by Canvas class of Android Java application. + */ +mbe_t *skia_mbe_create_by_canvas(SkCanvas *canvas) { + mbe_t *mbe; + struct _mbe_states_t *states; + + mbe = (mbe_t *)malloc(sizeof(mbe_t)); + if(mbe == NULL) + return NULL; + + mbe->states = (struct _mbe_states_t *) + malloc(sizeof(struct _mbe_states_t)); + states = mbe->states; + if(states == NULL) { + free(mbe); + return NULL; + } + + canvas->ref(); + mbe->canvas = canvas; + mbe->path = new SkPath(); + mbe->subpath = new SkPath(); + mbe->saved_region = new SkRegion(); + mbe->paint = new SkPaint(); + states->ptn = NULL; + states->ptn_owned = 0; + states->line_width = 0; + states->next = NULL; + + if(mbe->path == NULL || + mbe->subpath == NULL || mbe->paint == NULL || + mbe->saved_region == NULL) + goto fail; + + memcpy(states->matrix, id_matrix, sizeof(co_aix) * 6); + + return mbe; + + fail: + canvas->unref(); + if(mbe->path) delete mbe->path; + if(mbe->subpath) delete mbe->subpath; + if(mbe->paint) delete mbe->paint; + if(mbe->saved_region) delete mbe->saved_region; + free(states); + free(mbe); + + return NULL; +} + +mbe_t *mbe_create(mbe_surface_t *target) { + mbe_t *mbe; + SkBitmap *bitmap = (SkBitmap *)target; + SkCanvas *canvas; + + canvas = new SkCanvas(*bitmap); + if(canvas == NULL) { + delete bitmap; + return NULL; + } + + mbe = skia_mbe_create_by_canvas(canvas); + canvas->unref(); + + if(mbe == NULL) { + delete bitmap; + } + + return mbe; +} + +void mbe_destroy(mbe_t *canvas) { + struct _mbe_states_t *states; + + canvas->canvas->unref(); + delete canvas->path; + delete canvas->subpath; + delete canvas->paint; + delete canvas->saved_region; + while(canvas->states) { + states = canvas->states; + canvas->states = states->next; + + if(states->ptn && states->ptn_owned) + mbe_pattern_destroy(states->ptn); + free(states); + } + free(canvas); +} + +void mbe_paint(mbe_t *canvas) { + SkPaint *paint = canvas->paint; + + ASSERT(paint); + + _prepare_paint(canvas, SkPaint::kFill_Style); + + canvas->canvas->drawPaint(*paint); + + _finish_paint(canvas); +} + +void mbe_save(mbe_t *canvas) { + struct _mbe_states_t *states; + + states = (struct _mbe_states_t *)malloc(sizeof(struct _mbe_states_t)); + ASSERT(states); + + memcpy(states, canvas->states, sizeof(struct _mbe_states_t)); + states->next = canvas->states; + canvas->states = states; +} + +void mbe_fill(mbe_t *canvas) { + mbe_fill_preserve(canvas); + canvas->path->rewind(); + canvas->subpath->rewind(); +} + +void mbe_clip(mbe_t *canvas) { + if(!canvas->subpath->isEmpty()) + _update_path(canvas); + + canvas->canvas->clipPath(*canvas->path, SkRegion::kIntersect_Op); + canvas->path->rewind(); + canvas->subpath->rewind(); +} + +mbe_font_face_t * mbe_query_font_face(const char *family, + int slant, int weight) {} +void mbe_free_font_face(mbe_font_face_t *face) {} + +void mbe_clear(mbe_t *canvas) { + SkColor color = 0; + + canvas->canvas->drawColor(color, SkPorterDuff::kClear_Mode); +} + +void mbe_copy_source(mbe_t *src, mbe_t *dst) { + SkPaint *paint = dst->paint; + const SkBitmap *bmap; + SkXfermode *mode; + + /* _prepare_paint(dst, SkPaint::kFill_Style); */ + mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kSrc_Mode); + paint->setXfermode(mode); + bmap = &src->canvas->getDevice()->accessBitmap(false); + + dst->canvas->drawBitmap(*bmap, 0, 0, paint); + + paint->reset(); + mode->unref(); + /* _finish_paint(dst); */ +} + +void mbe_transform(mbe_t *mbe, co_aix matrix[6]) { + _update_path(mbe); + + matrix_mul(matrix, mbe->states->matrix, mbe->states->matrix); +} + +void mbe_arc(mbe_t *mbe, co_aix x, co_aix y, co_aix radius, + co_aix angle_start, co_aix angle_stop) { + SkPoint point; + SkPath *subpath = mbe->subpath; + SkRect rect; + SkScalar x0, y0; + SkScalar ang_start, ang_stop; + SkScalar sweep; + SkScalar r; /* radius */ + + subpath->getLastPt(&point); + x0 = point.fX; + y0 = point.fX; + r = CO_AIX_2_SKSCALAR(radius); + ang_start = CO_AIX_2_SKSCALAR(angle_start * 180 / PI); + ang_stop = CO_AIX_2_SKSCALAR(angle_stop * 180 / PI); + + /* Skia can only draw an arc in clockwise directly. We negative + * start and stop point to draw the arc in the mirror along x-axis + * in a sub-path. Then, the sub-path are reflected along x-axis, + * again. We get a right path, and add it to the path of mbe_t. + */ + if(ang_start > ang_stop) { + SkPath tmppath; + SkMatrix matrix; + co_aix reflect[6] = { 1, 0, 0, + 0, -1, 0}; + + rect.set(-r, -r, r, r); + sweep = ang_start - ang_stop; + tmppath.arcTo(rect, -ang_start, sweep, false); + + reflect[2] = x; + reflect[5] = y; + MB_MATRIX_2_SKMATRIX(matrix, reflect); + subpath->addPath(tmppath, matrix); + } else { + rect.set(x0 - r, y0 - r, x0 + r, y0 + r); + sweep = ang_stop - ang_start; + subpath->arcTo(rect, ang_start, sweep, false); + } +} + + +C_END diff -r aa2b388fba4e -r dcd7adb2c0fc src/paint.c --- a/src/paint.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/paint.c Wed Jun 09 17:30:09 2010 +0800 @@ -92,13 +92,9 @@ mbe_pattern_destroy(ptn); linear->flags &= ~LIF_DIRTY; ptn = mbe_pattern_create_linear(linear->x1, linear->y1, - linear->x2, linear->y2); - for(i = 0; i < linear->n_stops; i++) { - stop = &linear->stops[i]; - mbe_pattern_add_color_stop_rgba(ptn, stop->offset, - stop->r, stop->g, stop->b, - stop->a); - } + linear->x2, linear->y2, + linear->stops, linear->n_stops); + ASSERT(ptn != NULL); linear->ptn = ptn; } @@ -177,20 +173,15 @@ static void paint_radial_prepare(paint_t *paint, mbe_t *cr) { paint_radial_t *radial = (paint_radial_t *)paint; mbe_pattern_t *ptn; - grad_stop_t *stop; int i; if(radial->flags & RDF_DIRTY) { ptn = mbe_pattern_create_radial(radial->cx, radial->cy, 0, radial->cx, radial->cy, - radial->r); + radial->r, + radial->stops, + radial->n_stops); ASSERT(ptn != NULL); - stop = radial->stops; - for(i = 0; i < radial->n_stops; i++, stop++) { - mbe_pattern_add_color_stop_rgba(ptn, stop->offset, - stop->r, stop->g, - stop->b, stop->a); - } mbe_pattern_destroy(radial->ptn); radial->ptn = ptn; } @@ -328,15 +319,8 @@ */ void paint_image_set_matrix(paint_t *paint, co_aix matrix[6]) { paint_image_t *img_paint = (paint_image_t *)paint; - mbe_matrix_t cmatrix; - cmatrix.xx = matrix[0]; - cmatrix.xy = matrix[1]; - cmatrix.x0 = matrix[2]; - cmatrix.yx = matrix[3]; - cmatrix.yy = matrix[4]; - cmatrix.y0 = matrix[5]; - mbe_pattern_set_matrix(img_paint->ptn, &cmatrix); + mbe_pattern_set_matrix(img_paint->ptn, matrix); } void paint_image_get_size(paint_t *paint, int *w, int *h) { diff -r aa2b388fba4e -r dcd7adb2c0fc src/redraw_man.c --- a/src/redraw_man.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/redraw_man.c Wed Jun 09 17:30:09 2010 +0800 @@ -9,7 +9,7 @@ #include "mb_redraw_man.h" #include "mb_observer.h" #include "mb_prop.h" -#include "../config.h" +#include "config.h" /* required by rdman_img_ldr_load_paint() */ #include "mb_paint.h" @@ -39,7 +39,7 @@ * Whenever a coord is marked dirty and put into redraw_man_t::dirty_coords * list, all it's children should also be marked. * - * The procedure of clean coords comprises recomputing aggregate + * The procedure of clean coords comprises recomputing aggregated * transform matrix and area where members spreading in. The aggregated * transform matrix can reduce number of matrix mul to transform * positions from space of a coord to the closest cached ancestor coord. @@ -229,12 +229,12 @@ * * \section cache_imp Implementation of Cache * Both cached coords and coords that opacity != 1 need a canvas to - * draw descendants on. Both cases are traded in the same way. - * Every of them own a canvas_info to describe canvas and related + * draw descendants on. Both cases are traded in the same way. Every + * of them own a canvas_info to describe canvas and related * information. aggr_matrix of descendants must be adjusted to make - * left-top of range just at origin of canvas. It can save space by setting - * just large enough to hold rendering result of descendants. The process - * of adjusting is zeroing. + * left-top of bounding box just at origin (0, 0) of canvas. It saves + * space to give a canvas just enough for rending descadants. The + * process of adjusting left-top of bounding box is zeroing. * * Following is rules. * - zeroing on a cached coord is performed by adjust coord_t::aggr_matrix @@ -242,18 +242,20 @@ * - Clean coords works just like before without change. * - in preorder * - never perform zeroing on root_coord. - * - zeroing on cached coords marked with \ref COF_MUST_ZEROING. + * - do zeroing on cached coords marked with \ref COF_MUST_ZEROING. * - when clean a descendant that moves out-side of it's canvas, * respective cached coord is marked with \ref COF_MUST_ZEROING. * - zeroing is performed immediately after clean coords. - * - zeroing will not propagate acrossing boundary of cached coord. - * - It will be stopped at descendants which are cached coords. + * - zeroing will not be propagated to ancestors of a cached coord. + * - It will be stopped once a cached coord being found. * - coord_t::cur_area and coord_t::aggr_matrix of cached coords * must be ajdusted. * - the area of a cached coord is defined in parent space. * - areas of descendants are defined in space defined by aggr_matrix of * cached coord. - * - parent know the area in where cached coord and descendnats will + * - coord_t::aggr_matrix of cached coord defines coordination of + * descendants. + * - the parent knows the area in where cached coord and descendnats will * be draw. * - cached coords keep their private dirty area list. * - private dirty areas of a cached coord are transformed and added to @@ -285,14 +287,15 @@ * - Cached ancestors of zeroed ones should also be zeroed. * - zeroing * - Add more dirty areas if canvas should be fully redrawed. - * - From leaf to root. + * - From leaves to root. + * - Adjust area of child cached coords. * - add aggregated dirty areas from descendant cached coords to ancestors. * - Must include old area of cached coords if it is just clean and * parent cached one is not just clean. * - Just clean is a coord cleaned in last time of cleaning coords. * - draw dirty areas * - areas are rounded to N at first. - * - from leaf to root. + * - from leaves to root. */ #ifndef ASSERT @@ -370,8 +373,6 @@ (member) = STAILQ_NEXT(paint_t, next, member)) #define RM_PAINTMEMBER(paint, member) \ STAILQ_REMOVE((paint)->members, shnode_t, next, member) -#define RM_PAINT(rdman, paint) \ - STAILQ_REMOVE((rdman)->paints, paint_t, pnt_next, paint) /*! \brief Sort a list of element by a unsigned integer. * @@ -456,6 +457,9 @@ static int add_dirty_area(redraw_man_t *rdman, coord_t *coord, area_t *area) { int r; + if(area->w < 0.01 || area->h < 0.01) + return OK; + rdman->n_dirty_areas++; r = areas_add(_coord_get_dirty_areas(coord), area); return r == 0? OK: ERR; @@ -467,6 +471,12 @@ return OK; } +static int add_dirty_pcache_area_coord(redraw_man_t *rdman, coord_t *coord) { + coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); + ADD_DATA(coords, dirty_pcache_area_coords, coord); + return OK; +} + static int add_free_obj(redraw_man_t *rdman, void *obj, free_func_t free_func) { int max; @@ -586,6 +596,10 @@ info->owner = coord; info->canvas = canvas; DARRAY_INIT(&info->dirty_areas); + + bzero(info->pcache_areas, sizeof(area_t) * 2); + info->pcache_cur_area = &info->pcache_areas[0]; + info->pcache_last_area = &info->pcache_areas[1]; return info; } @@ -608,6 +622,7 @@ memset(rdman, 0, sizeof(redraw_man_t)); DARRAY_INIT(&rdman->dirty_coords); + DARRAY_INIT(&rdman->dirty_pcache_area_coords); DARRAY_INIT(&rdman->dirty_geos); DARRAY_INIT(&rdman->gen_geos); DARRAY_INIT(&rdman->zeroing_coords); @@ -654,7 +669,7 @@ rdman->root_coord->mouse_event = subject_new(&rdman->ob_factory, rdman->root_coord, OBJT_COORD); - rdman->root_coord->flags |= COF_OWN_CANVAS; + coord_set_flags(rdman->root_coord, COF_OWN_CANVAS); rdman->root_coord->canvas_info = coord_canvas_info_new(rdman, rdman->root_coord, cr); rdman->root_coord->opacity = 1; @@ -663,7 +678,6 @@ rdman->backend = backend; STAILQ_INIT(rdman->shapes); - STAILQ_INIT(rdman->paints); /* \note To make root coord always have at leat one observer. * It triggers mouse interpreter to be installed on root. @@ -694,6 +708,7 @@ if(rdman->coord_canvas_pool) elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); + DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -710,6 +725,13 @@ free_free_objs(rdman); free_objs_destroy(rdman); + /* Mark rdman clean that shapes and coords can be freed + * successfully. + */ + DARRAY_CLEAN(&rdman->dirty_coords); + DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); + DARRAY_CLEAN(&rdman->dirty_geos); + coord = postorder_coord_subtree(rdman->root_coord, NULL); while(coord) { saved_coord = coord; @@ -719,27 +741,19 @@ } rdman_coord_free(rdman, saved_coord); } -#if 0 - FORMEMBERS(saved_coord, member) { - rdman_shape_free(rdman, member->shape); - } -#endif /* Resources of root_coord is free by elmpool_free() or * caller; for canvas */ - shape = saved_shape = STAILQ_HEAD(rdman->shapes); - while(shape && (shape = STAILQ_NEXT(shape_t, sh_next, shape))) { - rdman_shape_free(rdman, saved_shape); -#if 0 - STAILQ_REMOVE(rdman->shapes, shape_t, sh_next, saved_shape); -#endif - saved_shape = shape; + while((shape = STAILQ_HEAD(rdman->shapes)) != NULL) { + rdman_shape_free(rdman, shape); } - if(saved_shape != NULL) - rdman_shape_free(rdman, saved_shape); coord_canvas_info_free(rdman, rdman->root_coord->canvas_info); + + /* XXX: paints are not freed, here. All resources of paints would + * be reclaimed by freeing elmpools. + */ elmpool_free(rdman->coord_pool); elmpool_free(rdman->geo_pool); @@ -751,6 +765,7 @@ elmpool_free(rdman->coord_canvas_pool); DARRAY_DESTROY(&rdman->dirty_coords); + DARRAY_DESTROY(&rdman->dirty_pcache_area_coords); DARRAY_DESTROY(&rdman->dirty_geos); DARRAY_DESTROY(&rdman->gen_geos); DARRAY_DESTROY(&rdman->zeroing_coords); @@ -835,6 +850,11 @@ return OK; } + if(shape->stroke != NULL) + rdman_paint_stroke(rdman, (paint_t *)NULL, shape); + if(shape->fill != NULL) + rdman_paint_fill(rdman, (paint_t *)NULL, shape); + if(geo != NULL) { subject_free(geo->mouse_event); geo_detach_coord(geo, shape->coord); @@ -848,6 +868,7 @@ if(rdman->last_mouse_over == (mb_obj_t *)shape) rdman->last_mouse_over = NULL; + return OK; } @@ -865,6 +886,7 @@ int rdman_paint_free(redraw_man_t *rdman, paint_t *paint) { shnode_t *shnode, *saved_shnode; + shape_t *shape; if(rdman_is_dirty(rdman)) { if(!(paint->flags & PNTF_FREE)) @@ -879,16 +901,29 @@ FORPAINTMEMBERS(paint, shnode) { if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); + + shape = saved_shnode->shape; + if(shape->stroke == paint) + rdman_paint_stroke(rdman, (paint_t *)NULL, shape); + if(shape->fill == paint) + rdman_paint_fill(rdman, (paint_t *)NULL, shape); + shnode_free(rdman, saved_shnode); } saved_shnode = shnode; } if(saved_shnode) { RM_PAINTMEMBER(paint, saved_shnode); + + shape = saved_shnode->shape; + if(shape->stroke == paint) + rdman_paint_stroke(rdman, (paint_t *)NULL, shape); + if(shape->fill == paint) + rdman_paint_fill(rdman, (paint_t *)NULL, shape); + shnode_free(rdman, saved_shnode); } - RM_PAINT(rdman, paint); paint->free(rdman, paint); return OK; } @@ -1003,7 +1038,7 @@ return rdman_coord_free_postponse(rdman, coord); /* Free canvas and canvas_info (\ref redraw) */ - if(coord->flags & COF_OWN_CANVAS) { + if(coord_is_cached(coord)) { canvas_free(_coord_get_canvas(coord)); coord_canvas_info_free(rdman, coord->canvas_info); } @@ -1076,6 +1111,9 @@ * into dirty_coords list. rdman_coord_changed() should be called * for a coord after it been changed to notify redraw manager to * redraw shapes grouped by it. + * + * Once a coord is changed, all its descendants are also put marked + * dirty. */ int rdman_coord_changed(redraw_man_t *rdman, coord_t *coord) { coord_t *child; @@ -1099,12 +1137,12 @@ continue; } - add_dirty_coord(rdman, child); - - if(child->flags & COF_OWN_CANVAS) { + if(coord_is_cached(child)) { preorder_coord_skip_subtree(child); continue; } + + add_dirty_coord(rdman, child); } return OK; @@ -1205,16 +1243,16 @@ return; if(coord->opacity != 1 || coord_is_cached(coord)) { - if(!(coord->flags & COF_OWN_CANVAS)) { + if(!coord_is_cached(coord)) { /* canvas is assigned latter, in zeroing_coord() */ coord->canvas_info = coord_canvas_info_new(rdman, coord, NULL); - coord->flags |= COF_OWN_CANVAS; + coord_set_flags(coord, COF_OWN_CANVAS); } } else { - if(coord->flags & COF_OWN_CANVAS) { + if(coord_is_cached(coord)) { canvas_free(_coord_get_canvas(coord)); coord_canvas_info_free(rdman, coord->canvas_info); - coord->flags &= ~COF_OWN_CANVAS; + coord_clear_flags(coord, COF_OWN_CANVAS); } /* This must here to keep coords that do not own canvas * can always point to right canvas_info. Since, they @@ -1224,20 +1262,95 @@ } } -static int coord_clean_members_n_compute_area(coord_t *coord) { - geo_t *geo; - /*! \note poses is shared by invokings, it is not support reentrying. */ +/* \brief Compute matrix from cached canvas to parent device space. + */ +static void compute_cached_2_pdev_matrix(coord_t *coord, + co_aix canvas2pdev_matrix[6]) { + coord_t *parent; + co_aix *aggr; + co_aix *matrix, *paggr; + co_aix scale_x, scale_y; + co_aix shift_x, shift_y; + co_aix canvas2p[6]; + + aggr = coord_get_aggr_matrix(coord); + matrix = coord->matrix; + parent = coord->parent; + paggr = coord_get_aggr_matrix(parent); + + scale_x = matrix[0] / aggr[0]; + scale_y = matrix[3] / aggr[3]; + shift_x = matrix[2] - scale_x * aggr[2]; + shift_y = matrix[5] - scale_y * aggr[5]; + + canvas2p[0] = scale_x; + canvas2p[1] = 0; + canvas2p[2] = shift_x; + canvas2p[3] = 0; + canvas2p[4] = scale_y; + canvas2p[5] = shift_y; + + matrix_mul(paggr, canvas2p, canvas2pdev_matrix); +} + +/*! \brief Compute area in parent cached coord for a cached coord. + * + * The coordination system of cached coord and descendants is resized, + * and shifted. It makes all descendants bound by a box, canvas box, + * at 0, 0 and size is the same as the canvas. + * + * The bounding box where the canvas would be draw on the canvas on + * ancestral cached coord can be retreived by shifting and resizing + * canvas box in reverse and transform to coordination system of + * ancestral cached coord. + */ +static void compute_pcache_area(coord_t *coord) { + co_aix cached2pdev[6]; + int c_w, c_h; + canvas_t *canvas; + coord_canvas_info_t *canvas_info; + co_aix poses[4][2]; + + canvas_info = coord->canvas_info; + SWAP(canvas_info->pcache_cur_area, canvas_info->pcache_last_area, + area_t *); + compute_cached_2_pdev_matrix(coord, cached2pdev); + + canvas = _coord_get_canvas(coord); + canvas_get_size(canvas, &c_w, &c_h); + + poses[0][0] = 0; + poses[0][1] = 0; + poses[1][0] = c_w; + poses[1][1] = c_h; + poses[2][0] = 0; + poses[2][1] = c_h; + poses[3][0] = c_w; + poses[3][1] = 0; + matrix_trans_pos(cached2pdev, &poses[0][0], &poses[0][1]); + matrix_trans_pos(cached2pdev, &poses[1][0], &poses[1][1]); + matrix_trans_pos(cached2pdev, &poses[2][0], &poses[2][1]); + matrix_trans_pos(cached2pdev, &poses[3][0], &poses[3][1]); + + area_init(coord_get_pcache_area(coord), 4, poses); + + coord_set_flags(coord, COF_DIRTY_PCACHE_AREA); +} + +/*! \brief Compute area of a coord. + */ +static int +compute_area(coord_t *coord) { static co_aix (*poses)[2]; static int max_poses = 0; + geo_t *geo; int cnt, pos_cnt; - /* Clean member shapes. */ cnt = 0; FORMEMBERS(coord, geo) { - clean_shape(geo->shape); cnt++; } - + if(max_poses < (cnt * 2)) { free(poses); max_poses = cnt * 2; @@ -1246,34 +1359,52 @@ return ERR; } - /* Compute area of the coord. */ pos_cnt = 0; FORMEMBERS(coord, geo) { area_to_positions(geo->cur_area, poses + pos_cnt); pos_cnt += 2; } - area_init(coord->cur_area, pos_cnt, poses); + area_init(coord_get_area(coord), pos_cnt, poses); + + return OK; +} + +static int coord_clean_members_n_compute_area(coord_t *coord) { + geo_t *geo; + int r; + /*! \note poses is shared by invokings, it is not support reentrying. */ + /* Clean member shapes. */ + FORMEMBERS(coord, geo) { + clean_shape(geo->shape); + } + + r = compute_area(coord); + if(r != OK) + return ERR; + return OK; } /*! \brief Clean dirty coords. * + * This function compute aggregation matrix and area for dirty + * coords. But, aggregation matrix of a cached coord is different from + * normal one. (see compute_aggr_of_cached_coord()). + * * \note coords their opacity != 1 are also traded as cached ones. */ static int clean_coord(redraw_man_t *rdman, coord_t *coord) { + coord_t *child; int r; setup_canvas_info(rdman, coord); - if(coord->flags & COF_OWN_CANVAS) - compute_aggr_of_cached_coord(coord); - else - compute_aggr_of_coord(coord); + compute_aggr(coord); /* Areas of cached coords are computed in two phase. - * Phase 1 works like other normal ones. Phase 2, is collect + * Phase 1 works like other normal ones. Phase 2, collects * all areas of descendants to compute a minimum covering area. * Phase 2 is performed by zeroing_coord(). */ @@ -1281,15 +1412,29 @@ if(r != OK) return ERR; - coord->flags &= ~COF_DIRTY; + add_dirty_area(rdman, coord, coord->cur_area); + add_dirty_area(rdman, coord, coord->last_area); + coord_clear_flags(coord, COF_DIRTY); + coord_set_flags(coord, COF_JUST_CLEAN); + + FORCHILDREN(coord, child) { + if(coord_is_cached(child)) + add_dirty_pcache_area_coord(rdman, child); + } + return OK; } /*! \brief Clean coord_t objects. + * + * It computes aggregation matrix and area for dirty coords. + * + * This function also responsible for computing area of parent cached + * coord, coord_canvas_info_t::pcache_cur_area, for its cached children. */ static int clean_rdman_coords(redraw_man_t *rdman) { - coord_t *coord; + coord_t *coord, *child; coord_t **dirty_coords; int n_dirty_coords; int i, r; @@ -1298,17 +1443,14 @@ if(n_dirty_coords > 0) { dirty_coords = rdman->dirty_coords.ds; _insert_sort((void **)dirty_coords, n_dirty_coords, - OFFSET(coord_t, order)); + OFFSET(coord_t, order)); /* ascend order */ for(i = 0; i < n_dirty_coords; i++) { coord = dirty_coords[i]; - if(!(coord->flags & COF_DIRTY)) + if(!coord_get_flags(coord, COF_DIRTY | COF_JUST_CLEAN)) continue; r = clean_coord(rdman, coord); if(r != OK) return ERR; - /* These two steps can be avoided for drawing all. */ - add_dirty_area(rdman, coord, &coord->areas[0]); - add_dirty_area(rdman, coord, &coord->areas[1]); } } return OK; @@ -1347,7 +1489,8 @@ static void zeroing_coord(redraw_man_t *rdman, coord_t *coord) { coord_t *cur; - area_t *area; + area_t *area, *saved_area; + geo_t *geo; co_aix min_x, min_y; co_aix max_x, max_y; co_aix x, y; @@ -1355,7 +1498,7 @@ int c_w, c_h; mbe_t *canvas; co_aix *aggr; - co_aix poses[2][2]; + co_aix poses[4][2]; if(coord->parent == NULL) /*! \note Should not zeroing root coord */ abort(); @@ -1367,7 +1510,7 @@ /* * Compute minimum overing area of sub-graphic */ - area = &coord->canvas_info->owner_mems_area; + area = coord_get_area(coord); min_x = area->x; min_y = area->y; max_x = min_x + area->w; @@ -1389,39 +1532,34 @@ max_x = x; if(y > max_y) max_y = y; - if(cur->flags & COF_OWN_CANVAS) + if(coord_is_cached(cur)) preorder_coord_skip_subtree(cur); } w = max_x - min_x; h = max_y - min_y; - /* - * Setup area of the coord - */ - aggr = coord_get_aggr_matrix(coord); - x = y = 0; - coord_trans_pos(coord->parent, &x, &y); - poses[0][0] = x; - poses[0][1] = y; - x = w; - y = h; - coord_trans_pos(coord->parent, &x, &y); - poses[1][0] = x; - poses[1][1] = y; - - area_init(coord_get_area(coord), 2, poses); - canvas = _coord_get_canvas(coord); if(canvas) canvas_get_size(canvas, &c_w, &c_h); else c_w = c_h = 0; - + + /* Without COF_JUST_CLEAN means the coordination system and matrix + * of the coord have not changed since last time of zeroing. So, + * if canvas box cover all descendants, we don't need rezeroing, + * and avoid redraw all descendants. + * + * Width and height of actually drawing area should not be smaller + * than half of canvas's width and height. + */ if(!coord_get_flags(coord, COF_JUST_CLEAN) && - min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h) + min_x >= 0 && min_y >= 0 && max_x <= c_w && max_y <= c_h && + h >= (c_h >> 2) && w >= (c_w >> 2)) { /* Canvas fully cover sub-graphic. */ + coord_set_flags(coord, COF_SKIP_ZERO); return; + } /* * Adjust matrics of descendants to align left-top corner of @@ -1429,25 +1567,32 @@ * zeroing coord. */ FOR_COORDS_PREORDER(coord, cur) { + if(coord_is_cached(cur) && coord != cur) { + /* + * Cached coords are zeroed from root to leaves, so + * changes of aggr_matrix would be propagated to next + * level of cached. + */ + preorder_coord_skip_subtree(cur); + } + /* Shift space */ aggr = coord_get_aggr_matrix(cur); aggr[3] -= min_x; aggr[5] -= min_y; - if(coord_get_flags(cur, COF_OWN_CANVAS)) { - /* - * Coords, zeroing, is zeroed in preorder of tree. - * So, they are zeroed after ancesters with correctly - * coord_t::aggr_matrix of parent coord to zeroing. - */ - preorder_coord_skip_subtree(cur); - area = coord_get_area(cur); - area->x -= min_x; - area->y -= min_y; - } else - coord_clean_members_n_compute_area(cur); + + FOR_COORD_MEMBERS(coord, geo) { + /* \see GEO_SWAP() */ + if(!geo_get_flags(geo, GEF_SWAP)) + SWAP(geo->cur_area, geo->last_area, area_t *); + } + coord_clean_members_n_compute_area(cur); } /* * Setup canvas + * + * Canvas of a cached coord is not setted in + * coord_canvas_info_new(). It should be setted, here. */ if(canvas == NULL || w > c_w || h > c_w) { if(canvas) @@ -1456,16 +1601,10 @@ _coord_set_canvas(coord, canvas); } - area = &coord->canvas_info->cached_dirty_area; - area->x = 0; - area->y = 0; - area->w = w; - area->h = h; - DARRAY_CLEAN(_coord_get_dirty_areas(coord)); - add_dirty_area(rdman, coord, area); + coord_set_flags(coord, COF_JUST_ZERO); } -/*! \brief Add canvas owner of dirty geos to coord_t::zeroing_coords. +/*! \brief Add canvas owner of dirty geos to redraw_man_t::zeroing_coords. * * All possible coords that need a zeroing have at least one dirty geo. */ @@ -1476,37 +1615,46 @@ int n_dirty_coords; coord_t **dirty_coords, *coord; + /* Mark all cached ancestral coords of dirty geos */ n_dirty_geos = rdman->dirty_geos.num; dirty_geos = rdman->dirty_geos.ds; for(i = 0; i < n_dirty_geos; i++) { geo = dirty_geos[i]; - coord = geo_get_coord(geo)->canvas_info->owner; + coord = coord_get_cached(geo_get_coord(geo)); while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { - coord_set_flags(coord, COF_TEMP_MARK); if(coord_is_root(coord)) break; - coord = coord->parent->canvas_info->owner; + coord_set_flags(coord, COF_TEMP_MARK); + coord = coord_get_cached(coord_get_parent(coord)); } } + /* Mark all cached ancestral coords of dirty coords */ n_dirty_coords = rdman->dirty_coords.num; dirty_coords = rdman->dirty_coords.ds; for(i = 0; i < n_dirty_coords; i++) { - coord = dirty_coords[i]->canvas_info->owner; + coord = coord_get_cached(dirty_coords[i]); while(!coord_get_flags(coord, COF_MUST_ZEROING | COF_TEMP_MARK)) { - coord_set_flags(coord, COF_TEMP_MARK); if(coord_is_root(coord)) break; - coord = coord->parent->canvas_info->owner; + coord_set_flags(coord, COF_TEMP_MARK); + coord = coord_get_cached(coord_get_parent(coord)); } } + /* Add all marked coords into redraw_man_t::zeroing_coords list */ FOR_COORDS_PREORDER(rdman->root_coord, coord) { + if(!coord_is_cached(coord)) + continue; /* skip coords that is not cached */ + if(!coord_get_flags(coord, COF_TEMP_MARK)) { + if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) + add_dirty_pcache_area_coord(rdman, coord); preorder_coord_skip_subtree(coord); continue; } add_zeroing_coord(rdman, coord); + coord_clear_flags(coord, COF_TEMP_MARK); } @@ -1515,7 +1663,9 @@ /*! \brief Zeroing coords in redraw_man_t::zeroing_coords. * - * \note redraw_man_t::zeroing_coords must in ascent partial order of tree. + * \note redraw_man_t::zeroing_coords must in descent partial order of + * tree. The size of a cached coord is effected by cached + * descendants. */ static int zeroing_rdman_coords(redraw_man_t *rdman) { int i; @@ -1523,45 +1673,48 @@ coord_t *coord; all_zeroing = &rdman->zeroing_coords; + /*! Zeroing is performed from leaves to root. + * + * REASON: The size of canvas is also effected by cached + * descedants. A cached coord is only effected by parent + * cached coord when it-self is dirty. When a cached + * coord is dirty, it is clean (compute aggregated matrix) + * by recomputing a scale for x and y-axis from aggregated + * matrix of parent coord. And, cleaning coord is + * performed before zeroing. It means ancestors of a + * cached coord would not effect it when zeroing. + */ for(i = all_zeroing->num - 1; i >= 0; i--) { coord = all_zeroing->ds[i]; - if(coord_is_root(coord)) - continue; zeroing_coord(rdman, coord); + compute_pcache_area(coord); } - + return OK; } -/* \brief Compute matrix from cached canvas to parent device space. +/*! \brief Compute pcache_area for coords whoes pcache_area is dirty. + * + * coord_t::dirty_pcache_area_coords also includes part of coords in + * coord_t::zeroing_coords. The pcache_area of coords that is in + * coord_t::dirty_pcache_area_coords, but is not in + * coord_t::zeroing_coords should be computed here. + * zeroing_rdman_coords() is responsible for computing pcache_area for + * zeroing ones. */ -static void compute_cached_2_pdev_matrix(coord_t *coord, - co_aix canvas2pdev_matrix[6]) { - coord_t *parent; - co_aix *aggr; - co_aix *matrix, *paggr; - co_aix scale_x, scale_y; - co_aix shift_x, shift_y; - co_aix canvas2p[6]; - - aggr = coord_get_aggr_matrix(coord); - matrix = coord->matrix; - parent = coord->parent; - paggr = coord_get_aggr_matrix(parent); +static int +compute_rdman_coords_pcache_area(redraw_man_t *rdman) { + coords_t *all_coords; + coord_t *coord; + int i; - scale_x = matrix[0] / aggr[0]; - scale_y = matrix[3] / aggr[3]; - shift_x = matrix[2] - scale_x * aggr[2]; - shift_y = matrix[5] - scale_y * aggr[5]; - - canvas2p[0] = scale_x; - canvas2p[1] = 0; - canvas2p[2] = shift_x; - canvas2p[3] = 0; - canvas2p[4] = scale_y; - canvas2p[5] = shift_y; - - matrix_mul(paggr, canvas2p, canvas2pdev_matrix); + all_coords = &rdman->dirty_pcache_area_coords; + for(i = 0; i < all_coords->num; i++) { + coord = all_coords->ds[i]; + if(coord_get_flags(coord, COF_DIRTY_PCACHE_AREA)) + compute_pcache_area(coord); + } + return OK; } /*! \brief Add aggregated dirty areas to ancestor. @@ -1574,6 +1727,7 @@ coord_t *coord) { int i; int n_areas; + int enable_poses1 = 0; co_aix poses0[2][2], poses1[2][2]; co_aix reverse[6]; co_aix canvas2pdev_matrix[6]; @@ -1586,27 +1740,27 @@ if(n_areas == 0) abort(); /* should not happen! */ - area0 = coord->canvas_info->aggr_dirty_areas; + area0 = _coord_get_aggr_dirty_areas(coord); area1 = area0 + 1; + /* TODO: Since both cur & last area of coords are added into dirty + * area list, position of both areas shoud be adjusted for + * all descendants when zeroing a cached coord. + */ for(i = 0; i < n_areas; i++) { area = areas[i]; if(area->w != 0 || area->h != 0) break; } - if(i < n_areas) { - area = areas[i++]; - poses0[0][0] = area->x; - poses0[0][1] = area->y; - poses0[1][0] = area->x + area->w; - poses0[1][1] = area->y + area->h; - } else { - poses0[0][0] = 0; - poses0[0][1] = 0; - poses0[1][0] = 0; - poses0[1][1] = 0; - } + if(i >= n_areas) + return; + + area = areas[i++]; + poses0[0][0] = area->x; + poses0[0][1] = area->y; + poses0[1][0] = area->x + area->w; + poses0[1][1] = area->y + area->h; if(i < n_areas) { area = areas[i++]; @@ -1620,7 +1774,7 @@ poses1[1][0] = 0; poses1[1][1] = 0; } - + for(; i < n_areas - 1;) { /* Even areas */ area = areas[i++]; @@ -1639,7 +1793,7 @@ poses1[1][1] = MB_MAX(poses1[1][1], area->y + area->h); } } - + if(i < n_areas) { area = areas[i]; if(area->w != 0 || area->h != 0) { @@ -1649,110 +1803,206 @@ poses0[1][1] = MB_MAX(poses0[1][1], area->y + area->h); } } - - parent = coord->parent; - pcached_coord = parent->canvas_info->owner; + + parent = coord_get_parent(coord); + pcached_coord = coord_get_cached(parent); compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); - + + /* Add dirty areas to parent cached coord. */ matrix_trans_pos(canvas2pdev_matrix, poses0[0], poses0[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses0[1], poses0[1] + 1); area_init(area0, 2, poses0); add_dirty_area(rdman, pcached_coord, area0); - + matrix_trans_pos(canvas2pdev_matrix, poses1[0], poses1[0] + 1); matrix_trans_pos(canvas2pdev_matrix, poses1[1], poses1[1] + 1); area_init(area1, 2, poses1); - if(area1->w != 0 || area1->h != 0) - if(area0->x != area1->x || area0->y != area1->y || - area0->w != area1->w || area0->h != area1->h) - add_dirty_area(rdman, pcached_coord, area1); + add_dirty_area(rdman, pcached_coord, area1); if(coord_get_flags(coord, COF_JUST_CLEAN) && !coord_get_flags(pcached_coord, COF_JUST_CLEAN)) add_dirty_area(rdman, pcached_coord, coord->last_area); } +/*! \brief To test if redrawing all elements on the canvas of a cached coord. + */ +#define IS_CACHE_REDRAW_ALL(co) \ + (coord_get_flags((co), COF_JUST_CLEAN | COF_JUST_ZERO)) + +/* Aggregate dirty areas and propagate them to ancestor cached coord. + * + * The aggregation is performed from leaves to root. But, this + * function do not aggregate dirty areas for root coord. The dirty + * areas of a cached coord are aggregated into two areas, one for old + * areas and one or new areas. Both aggregation areas are add into + * dirty_areas list of closet ancestral cached coord. + */ static int add_rdman_aggr_dirty_areas(redraw_man_t *rdman) { int i; int n_zeroing; coord_t **zeroings; - coord_t *coord; + coord_t *coord, *pcached_coord; + int n_dpca_coords; /* number of dirty pcache area coords */ + coord_t **dpca_coords; /* dirty pcache area coords */ + /* Add aggregated areas to parent cached one for coords in zeroing + * list + */ n_zeroing = rdman->zeroing_coords.num; zeroings = rdman->zeroing_coords.ds; - for(i = n_zeroing - 1; i >= 0; i--) { + for(i = 0; i < n_zeroing; i++) { + if(coord_get_flags(coord, COF_TEMP_MARK)) + continue; + coord_set_flags(coord, COF_TEMP_MARK); + coord = zeroings[i]; - if(!coord_is_root(coord)) + pcached_coord = coord_get_cached(coord_get_parent(coord)); + + if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) + continue; + + if(IS_CACHE_REDRAW_ALL(coord)) { + add_dirty_area(rdman, pcached_coord, + coord_get_pcache_area(coord)); + add_dirty_area(rdman, pcached_coord, + coord_get_pcache_last_area(coord)); + } else { add_aggr_dirty_areas_to_ancestor(rdman, coord); + } + } + + /* Add pcache_areas to parent cached one for coord that is + * non-zeroing and its parent is changed. + */ + n_dpca_coords = rdman->dirty_pcache_area_coords.num; + dpca_coords = rdman->dirty_pcache_area_coords.ds; + for(i = 0; i < n_dpca_coords; i++) { + if(coord_get_flags(coord, COF_TEMP_MARK)) + continue; + coord_set_flags(coord, COF_TEMP_MARK); + + coord = dpca_coords[i]; + pcached_coord = coord_get_cached(coord_get_parent(coord)); + + if(coord_is_root(coord) || IS_CACHE_REDRAW_ALL(pcached_coord)) + continue; + + add_dirty_area(rdman, pcached_coord, + coord_get_pcache_area(coord)); + add_dirty_area(rdman, pcached_coord, + coord_get_pcache_last_area(coord)); } - return OK; -} - -static int add_rdman_cached_dirty_areas(redraw_man_t *rdman) { - int i; - coord_t *coord, **dirty_coords; - int n_dirty_coords; - - n_dirty_coords = rdman->dirty_coords.num; - dirty_coords = rdman->dirty_coords.ds; - for(i = 0; i < n_dirty_coords; i++) { - coord = dirty_coords[i]; - if(coord_get_flags(coord, COF_OWN_CANVAS)) { - add_dirty_area(rdman, coord, coord->cur_area); - add_dirty_area(rdman, coord, coord->last_area); - } + /* Remove temporary mark */ + for(i = 0; i < n_zeroing; i++) { + coord_clear_flags(zeroings[i], COF_TEMP_MARK); + } + for(i = 0; i < n_dpca_coords; i++) { + coord_clear_flags(dpca_coords[i], COF_TEMP_MARK); } return OK; } -static int clean_rdman_dirties(redraw_man_t *rdman) { +/*! \brief Swap geo_t::cur_area and geo_t::last_area for a geo_t. + * + * It is call by rdman_clean_dirties() to swap areas for members of + * dirty coord in redraw_man_t::dirty_coords and dirty geos in + * redraw_man_t::dirty_geos. + * + * zeroing_coord() would also swap some areas for members of + * descendants of a cached coord. But, only members that was not + * swapped, without GEF_SWAP flag, in this round of redrawing. + * zeroing_coord() would not mark geos with GEF_SWAP since it not not + * referenced later. We don't mark geos in zeroing_coord() because we + * don't want to unmark it later. To unmark it, we should re-travel + * forest of cached coords in redraw_man_t::zeroing_coords. It is + * expansive. + */ +#define GEO_SWAP(g) \ + if(!geo_get_flags((g), GEF_SWAP)) { \ + SWAP((g)->cur_area, (g)->last_area, area_t *); \ + geo_set_flags((g), GEF_SWAP); \ + } + +/* \brief Clean dirty coords and shapes. + * + * The procedure of clean dirty coords and shapes include 3 major steps. + * + * - Add dirty coords and shapes to rdman. + * - All descendants of a dirty coord are also dirty, except + * descendants of cached descendants. + * - Recompute aggregated transformation matrix from root to leaves + * for dirty coords. + * - The aggregated transformation matrix for a cached coord is + * different from other coords. + * - Compute new area for every dirty coord. + * - Area of a dirty coord is an aggregation of areas of all members. + * - A cached coord has two type of areas, one is for members of the cached + * coord, another one is for the block that cached coord and descendants + * will be mapped in parent cached coord. + * - Areas, for parent cached coord (pcache_cur_area), of + * non-dirty cached coord would be recomputed when cleaning + * parent coord. + * - Areas, for parent cached coord (pcache_cur_area), of dirty + * cached coord would be recomputed when zeroing the cached + * coord. (because zeroing would change aggregated matrix, and + * zeroing was performed after cleaning) + * - Areas, for members, of dirty cached coord would only be + * recomputed when cleaning the coord. + * - Perform zeroing on some cached coords that + * - dirty, is, + * - dirty descendants, has. + * - Propagate dirty areas to dirty area list of parent cached coord + * for every cached coords, not only for dirty cached coords. + * + * The cur_area of a cached coord is where members of the coord will + * be draw in cache buffer, i.e. surface. The area of the cached + * coord and descendants is described by pcache_cur_area and + * pcache_last_area in coord_canvas_info_t. + */ +static int rdman_clean_dirties(redraw_man_t *rdman) { int r; int i; coord_t **coords, *coord; geo_t **geos; + geo_t *geo; /* coord_t::cur_area of coords are temporary pointed to * coord_canvas_info_t::owner_mems_area for store area - * by clean_coor(). + * by clean_coord(). */ coords = rdman->dirty_coords.ds; for(i = 0; i < rdman->dirty_coords.num; i++) { coord = coords[i]; - if(coord->flags & COF_DIRTY) { - if(!coord_get_flags(coord, COF_OWN_CANVAS)) - SWAP(coord->cur_area, coord->last_area, area_t *); - else { - coord->last_area = coord->cur_area; - coord->cur_area = &coord->canvas_info->owner_mems_area; - } + SWAP(coord->cur_area, coord->last_area, area_t *); + FOR_COORD_MEMBERS(coord, geo) { + GEO_SWAP(geo); } } geos = rdman->dirty_geos.ds; - for(i = 0; i < rdman->dirty_geos.num; i++) - if(geos[i]->flags & GEF_DIRTY) - SWAP(geos[i]->cur_area, geos[i]->last_area, area_t *); - + for(i = 0; i < rdman->dirty_geos.num; i++) { + geo = geos[i]; + GEO_SWAP(geo); + } + r = clean_rdman_coords(rdman); if(r != OK) return ERR; - - coords = rdman->dirty_coords.ds; - for(i = 0; i < rdman->dirty_coords.num; i++) { - coord = coords[i]; - coord_set_flags(coord, COF_JUST_CLEAN); - coord->cur_area = - (coord->last_area == coord->areas)? - coord->areas + 1: coord->areas; - } + + /* TODO: save area of cached coord and descendants in + * cached_dirty_area for parent cached coord space. + */ r = clean_rdman_geos(rdman); if(r != OK) return ERR; + /* Zeroing must be performed after clearing to get latest position + * of shapes for computing new bounding box + */ r = add_rdman_zeroing_coords(rdman); if(r != OK) return ERR; @@ -1761,17 +2011,40 @@ if(r != OK) return ERR; + r = compute_rdman_coords_pcache_area(rdman); + if(r != OK) + return ERR; + r = add_rdman_aggr_dirty_areas(rdman); if(r != OK) return ERR; - r = add_rdman_cached_dirty_areas(rdman); - if(r != OK) - return ERR; - + /* + * Clear all flags setted by zeroing. + */ coords = rdman->dirty_coords.ds; - for(i = 0; i < rdman->dirty_coords.num; i++) - coord_clear_flags(coords[i], COF_JUST_CLEAN); + for(i = 0; i < rdman->dirty_coords.num; i++) { + coord = coords[i]; + coord_clear_flags(coord, COF_JUST_CLEAN); + /* \see GEO_SWAP() */ + FOR_COORD_MEMBERS(coord, geo) { + geo_clear_flags(geo, GEF_SWAP); + } + } + coords = rdman->zeroing_coords.ds; + for(i = 0; i < rdman->zeroing_coords.num; i++) + coord_clear_flags(coords[i], + COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); + coords = rdman->dirty_pcache_area_coords.ds; + for(i = 0; i < rdman->dirty_pcache_area_coords.num; i++) + coord_clear_flags(coords[i], + COF_JUST_CLEAN | COF_JUST_ZERO | COF_SKIP_ZERO); + + /* \see GEO_SWAP() */ + for(i = 0; i < rdman->dirty_geos.num; i++) { + geo = geos[i]; + geo_clear_flags(geo, GEF_SWAP); + } return OK; } @@ -1865,12 +2138,7 @@ #ifndef UNITTEST static void clear_canvas(canvas_t *canvas) { - mbe_operator_t old_op; - - old_op = mbe_get_operator(canvas); - mbe_set_operator(canvas, MBE_OPERATOR_CLEAR); - mbe_paint(canvas); - mbe_set_operator(canvas, old_op); + mbe_clear(canvas); } static void make_clip(mbe_t *cr, int n_dirty_areas, @@ -1881,6 +2149,8 @@ mbe_new_path(cr); for(i = 0; i < n_dirty_areas; i++) { area = dirty_areas[i]; + if(area->w < 0.1 || area->h < 0.1) + continue; mbe_rectangle(cr, area->x, area->y, area->w, area->h); } mbe_clip(cr); @@ -1892,15 +2162,10 @@ static void copy_cr_2_backend(redraw_man_t *rdman, int n_dirty_areas, area_t **dirty_areas) { - mbe_operator_t saved_op; - if(n_dirty_areas) make_clip(rdman->backend, n_dirty_areas, dirty_areas); - saved_op = mbe_get_operator(rdman->backend); - mbe_set_operator(rdman->backend, MBE_OPERATOR_SOURCE); - mbe_paint(rdman->backend); - mbe_set_operator(rdman->backend, saved_op); + mbe_copy_source(rdman->cr, rdman->backend); } #else /* UNITTEST */ static void make_clip(mbe_t *cr, int n_dirty_areas, @@ -1923,7 +2188,6 @@ mbe_t *pcanvas, *canvas; mbe_surface_t *surface; mbe_pattern_t *pattern; - mbe_matrix_t cr_matrix; co_aix reverse[6]; co_aix canvas2pdev_matrix[6]; @@ -1933,18 +2197,11 @@ compute_cached_2_pdev_matrix(coord, canvas2pdev_matrix); compute_reverse(canvas2pdev_matrix, reverse); - cr_matrix.xx = reverse[0]; - cr_matrix.xy = reverse[1]; - cr_matrix.x0 = reverse[2]; - cr_matrix.yx = reverse[3]; - cr_matrix.yy = reverse[4]; - cr_matrix.y0 = reverse[5]; - canvas = _coord_get_canvas(coord); pcanvas = _coord_get_canvas(coord->parent); surface = mbe_get_target(canvas); pattern = mbe_pattern_create_for_surface(surface); - mbe_pattern_set_matrix(pattern, &cr_matrix); + mbe_pattern_set_matrix(pattern, reverse); mbe_set_source(pcanvas, pattern); mbe_paint_with_alpha(pcanvas, coord->opacity); } @@ -1972,7 +2229,7 @@ child = FIRST_CHILD(coord); while(child != NULL || member != NULL) { if(child && child->before_pmem == mem_idx) { - if(child->flags & COF_OWN_CANVAS) { + if(coord_is_cached(child)) { if(!(child->flags & COF_HIDDEN) && is_area_in_areas(coord_get_area(child), n_areas, areas)) { update_cached_canvas_2_parent(rdman, child); @@ -2002,11 +2259,28 @@ static int draw_dirty_cached_coord(redraw_man_t *rdman, coord_t *coord) { area_t **areas, *area; + area_t full_area; int n_areas; mbe_t *canvas; + mbe_surface_t *surface; int i; int r; + canvas = _coord_get_canvas(coord); + + if(IS_CACHE_REDRAW_ALL(coord)) { + /* + * full_area covers all dirty areas of the cached coord. + */ + DARRAY_CLEAN(_coord_get_dirty_areas(coord)); + surface = mbe_get_target(canvas); + full_area.x = 0; + full_area.y = 0; + full_area.w = mbe_image_surface_get_width(surface); + full_area.h = mbe_image_surface_get_height(surface); + add_dirty_area(rdman, coord, &full_area); + } + areas = _coord_get_dirty_areas(coord)->ds; n_areas = _coord_get_dirty_areas(coord)->num; @@ -2018,7 +2292,6 @@ area->h = ceilf(area->h); } - canvas = _coord_get_canvas(coord); make_clip(canvas, n_areas, areas); clear_canvas(canvas); @@ -2030,13 +2303,27 @@ } static void draw_shapes_in_dirty_areas(redraw_man_t *rdman) { + int num; + coord_t **zeroings; + coord_t *coord; int i; - coord_t *coord; - for(i = rdman->zeroing_coords.num - 1; i >= 0; i--) { - coord = rdman->zeroing_coords.ds[i]; + zeroings = rdman->zeroing_coords.ds; + num = rdman->zeroing_coords.num; + /* Draw cached ones from leaves to root. + * Since content of cached ones depend on descendants. + */ + for(i = num - 1; i >= 0; i--) { + coord = zeroings[i]; + if(coord_get_flags(coord, COF_TEMP_MARK)) + continue; draw_dirty_cached_coord(rdman, coord); + coord_set_flags(coord, COF_TEMP_MARK); } + for(i = 0; i < num; i++) + coord_clear_flags(coord, COF_TEMP_MARK); + + draw_dirty_cached_coord(rdman, rdman->root_coord); } @@ -2081,7 +2368,7 @@ int n_areas; area_t **areas; - r = clean_rdman_dirties(rdman); + r = rdman_clean_dirties(rdman); if(r != OK) return ERR; @@ -2098,18 +2385,14 @@ coord = rdman->zeroing_coords.ds[i]; DARRAY_CLEAN(_coord_get_dirty_areas(coord)); } + DARRAY_CLEAN(_coord_get_dirty_areas(rdman->root_coord)); rdman->n_dirty_areas = 0; } - coords = rdman->zeroing_coords.ds; - for(i = 0; i < rdman->zeroing_coords.num; i++) { - coord = coords[i]; - coord_clear_flags(coord, COF_MUST_ZEROING); - } - DARRAY_CLEAN(&rdman->dirty_coords); DARRAY_CLEAN(&rdman->dirty_geos); DARRAY_CLEAN(&rdman->zeroing_coords); + DARRAY_CLEAN(&rdman->dirty_pcache_area_coords); /* Free postponsed removing */ free_free_objs(rdman); @@ -2196,7 +2479,7 @@ int rdman_force_clean(redraw_man_t *rdman) { int r; - r = clean_rdman_dirties(rdman); + r = rdman_clean_dirties(rdman); return r; } diff -r aa2b388fba4e -r dcd7adb2c0fc src/shape_image.c --- a/src/shape_image.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/shape_image.c Wed Jun 09 17:30:09 2010 +0800 @@ -104,7 +104,6 @@ co_aix img_matrix[6]; co_aix x_factor, y_factor; int img_w, img_h; - mbe_matrix_t cmatrix; int i; poses = img->poses; @@ -158,7 +157,6 @@ void sh_image_draw(shape_t *shape, mbe_t *cr) { sh_image_t *img = (sh_image_t *)shape; mbe_pattern_t *saved_source; - mbe_matrix_t matrix, saved_matrix; co_aix *aggr; mbe_move_to(cr, img->poses[0][0], img->poses[0][1]); diff -r aa2b388fba4e -r dcd7adb2c0fc src/shape_path.c --- a/src/shape_path.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/shape_path.c Wed Jun 09 17:30:09 2010 +0800 @@ -385,9 +385,9 @@ * * \todo Notify programmers that syntax or value error of path data. */ -static int sh_path_cmd_arg_cnt(char *data, int *cmd_cntp, int *pnt_cntp, +static int sh_path_cmd_arg_cnt(const char *data, int *cmd_cntp, int *pnt_cntp, int *float_arg_cntp) { - char *p, *old; + const char *p, *old; int cmd_cnt, pnt_cnt, float_arg_cnt; int i; @@ -564,8 +564,8 @@ #define TO_ABSX islower(cmd)? x + atof(old): atof(old) #define TO_ABSY islower(cmd)? y + atof(old): atof(old) -static int sh_path_cmd_arg_fill(char *data, sh_path_t *path) { - char *p, *old; +static int sh_path_cmd_arg_fill(const char *data, sh_path_t *path) { + const char *p, *old; char *cmds; char cmd; co_aix *pnts; @@ -738,7 +738,7 @@ /*! \brief Create a path from value of 'data' of SVG path. */ -shape_t *rdman_shape_path_new(redraw_man_t *rdman, char *data) { +shape_t *rdman_shape_path_new(redraw_man_t *rdman, const char *data) { sh_path_t *path; int cmd_cnt, pnt_cnt, float_arg_cnt; int msz; diff -r aa2b388fba4e -r dcd7adb2c0fc src/shape_stext.c --- a/src/shape_stext.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/shape_stext.c Wed Jun 09 17:30:09 2010 +0800 @@ -1,7 +1,6 @@ #include +#include #include "mb_graph_engine.h" -#include -#include #include "mb_shapes.h" #include "mb_tools.h" @@ -59,8 +58,6 @@ move_xys[move_cnt][0] = x; \ move_xys[move_cnt++][1] = y; \ } while(0) -#undef mbe_show_text -#define mbe_show_text(cr, txt) #undef mbe_scaled_font_destroy #define mbe_scaled_font_destroy(scaled) #undef mbe_text_path @@ -128,106 +125,16 @@ #define MBE_SET_WIDTH(ext, v) do { ((ext)->width) = v; } while(0) #define MBE_SET_HEIGHT(ext, v) do { ((ext)->height) = v; } while(0) -/*! \brief Find out a font pattern. - * - * This function use fontconfig to decide a font file in pattern. It can - * replaced by other mechanism if you think it is not what you want. - * - * \param slant make font prune if it it non-zero. - * \param weight make font normal if it is 100. - */ -static -FcPattern *query_font_pattern(const char *family, int slant, int weight) { - FcPattern *ptn, *p, *fn_ptn; - FcValue val; - FcConfig *cfg; - FcBool r; - FcResult result; - static int slant_map[] = { /* from MB_FONT_SLANT_* to FC_SLANT_* */ - FC_SLANT_ROMAN, - FC_SLANT_ROMAN, - FC_SLANT_ITALIC, - FC_SLANT_OBLIQUE}; - - cfg = FcConfigGetCurrent(); - ptn = FcPatternCreate(); - p = FcPatternCreate(); - if(ptn == NULL || p == NULL) - goto err; - - val.type = FcTypeString; - val.u.s = family; - FcPatternAdd(ptn, "family", val, FcTrue); - - val.type = FcTypeInteger; - val.u.i = slant_map[slant]; - FcPatternAdd(ptn, "slant", val, FcTrue); - - val.type = FcTypeInteger; - val.u.i = weight; - FcPatternAdd(ptn, "weight", val, FcTrue); - - r = FcConfigSubstituteWithPat(cfg, ptn, NULL, FcMatchPattern); - if(!r) - goto err; - - r = FcConfigSubstituteWithPat(cfg, p, ptn, FcMatchFont); - if(!r) - goto err; - - FcDefaultSubstitute(p); - - fn_ptn = FcFontMatch(cfg, p, &result); - - /* It is supposed to return FcResultMatch. But, it is no, now. - * I don't know why. Someone should figure out the issue. - */ -#if 0 - if(result != FcResultMatch) { - printf("%d %d\n", result, FcResultMatch); - goto err; - } -#endif - if(fn_ptn == NULL) - goto err; - - FcPatternDestroy(ptn); - FcPatternDestroy(p); - - return fn_ptn; - -err: - if(ptn) - FcPatternDestroy(ptn); - if(p) - FcPatternDestroy(p); - return NULL; - +static mb_font_face_t * +query_font_face(const char *family, int slant, int weight) { + return (mb_font_face_t *)mbe_query_font_face(family, slant, weight); } -/*! \brief Find out a font face for a pattern specified. - * - * The pattern, here, is a vector of family, slant, and weight. - * This function base on fontconfig and cairo FreeType font supporting. - * You can replace this function with other font mechanisms. - */ -static -mb_font_face_t *query_font_face(const char *family, int slant, int weight) { - mbe_font_face_t *cface; - FcPattern *ptn; - - ptn = query_font_pattern(family, slant, weight); - cface = mbe_ft_font_face_create_for_pattern(ptn); - FcPatternDestroy(ptn); - - return (mb_font_face_t *)cface; -} - -static -void free_font_face(mb_font_face_t *face) { +static void +free_font_face(mb_font_face_t *face) { ASSERT(face == NULL); - mbe_font_face_destroy((mbe_font_face_t *)face); + mbe_free_font_face((mbe_font_face_t *)face); } /*! \brief This is scaled font for specified size and extent. @@ -242,31 +149,13 @@ mb_scaled_font_t *make_scaled_font_face_matrix(mb_font_face_t *face, co_aix *matrix) { mbe_scaled_font_t *scaled_font; - mbe_matrix_t font_matrix; - static mbe_matrix_t id = { - 1, 0, - 0, 1, - 0, 0 - }; - static mbe_font_options_t *opt = NULL; + static co_aix id[6] = { 1, 0, 0, + 0, 1, 0 }; ASSERT(matrix != NULL); - if(opt == NULL) { - opt = mbe_font_options_create(); - if(opt == NULL) - return NULL; - } - - font_matrix.xx = *matrix++; - font_matrix.xy = *matrix++; - font_matrix.x0 = *matrix++; - font_matrix.yx = *matrix++; - font_matrix.yy = *matrix++; - font_matrix.y0 = *matrix; scaled_font = mbe_scaled_font_create((mbe_font_face_t *)face, - &font_matrix, - &id, opt); + matrix, &id); return (mb_scaled_font_t *)scaled_font; } @@ -705,12 +594,9 @@ static void test_query_font_face(void) { mb_font_face_t *face; - mbe_status_t status; face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - status = mbe_font_face_status((mbe_font_face_t *)face); - CU_ASSERT(status == MBE_STATUS_SUCCESS); free_font_face(face); } @@ -720,17 +606,12 @@ co_aix matrix[6] = {5, 0, 0, 0, 5, 0}; mb_font_face_t *face; mb_scaled_font_t *scaled; - mbe_status_t status; face = query_font_face("serif", MB_FONT_SLANT_ROMAN, 100); CU_ASSERT(face != NULL); - status = mbe_font_face_status((mbe_font_face_t *)face); - CU_ASSERT(status == MBE_STATUS_SUCCESS); scaled = make_scaled_font_face_matrix(face, matrix); CU_ASSERT(scaled != NULL); - status = mbe_scaled_font_status((mbe_scaled_font_t *)scaled); - CU_ASSERT(status == MBE_STATUS_SUCCESS); scaled_font_free(scaled); free_font_face(face); diff -r aa2b388fba4e -r dcd7adb2c0fc src/shape_text.c --- a/src/shape_text.c Sun Nov 08 00:37:29 2009 +0800 +++ b/src/shape_text.c Wed Jun 09 17:30:09 2010 +0800 @@ -204,10 +204,7 @@ } static int get_extents(sh_text_t *text, PangoRectangle *extents) { - mbe_matrix_t fmatrix; - mbe_matrix_t ctm; mbe_scaled_font_t *new_scaled; - mbe_font_options_t *fopt; pango_layout_get_extents(text->layout, NULL, extents); pango_extents_to_pixels(extents,NULL);