├── .gitmodules
├── README.md
├── examples
├── java-bitmap
│ ├── AndroidManifest.xml
│ ├── Makefile
│ ├── default.properties
│ ├── jni
│ │ ├── Android.mk
│ │ ├── Application.mk
│ │ ├── cairo
│ │ ├── cairo-extra
│ │ ├── cairo.mk
│ │ ├── java-bitmap.c
│ │ ├── pixman
│ │ ├── pixman-extra
│ │ └── pixman.mk
│ ├── res
│ │ └── values
│ │ │ └── strings.xml
│ └── src
│ │ └── com
│ │ └── example
│ │ └── cairo
│ │ └── Cairo.java
└── pure-ndk
│ ├── AndroidManifest.xml
│ ├── Makefile
│ ├── default.properties
│ ├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── cairo
│ ├── cairo-extra
│ ├── cairo.mk
│ ├── pixman
│ ├── pixman-extra
│ ├── pixman.mk
│ └── pure-ndk.c
│ ├── res
│ └── values
│ │ └── strings.xml
│ └── screenshot.png
└── jni
├── cairo-extra
├── cairo-features.h
└── locale.h
├── cairo.mk
├── pixman-extra
├── pixman-combine32.c
├── pixman-combine32.h
├── pixman-combine64.c
├── pixman-combine64.h
├── pixman-elf-fix.h
└── pixman-version.h
└── pixman.mk
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "jni/cairo"]
2 | path = jni/cairo
3 | url = git://git.cairographics.org/git/cairo
4 | [submodule "jni/pixman"]
5 | path = jni/pixman
6 | url = git://git.cairographics.org/git/pixman.git
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository contains Android build files and various additional
2 | files needed to build your self a version of libcairo and libpixman
3 | that you can use on Android devices.
4 |
5 | This is for Android applications that are using the NDK for some or
6 | all of their work - only the C/C++ headers are present, there are
7 | no Java bindings included.
8 |
9 |
10 | Obtaining the source code
11 | =========================
12 |
13 | This git repository uses submodules to track the official cairo
14 | and pixman repositories, as such you'll need to do a
15 |
16 | git clone --recursive git@github.com:anoek/android-cairo.git
17 |
18 | to pull down not only the android-cairo source, but also the
19 | cairo and pixman source.
20 |
21 |
22 | Compiling & Using
23 | =================
24 |
25 | The contents of the jni/ directory are meant to be either copied
26 | or symlinked into your application's jni/ directory. Once done,
27 | you can then include the cairo.mk and pixman.mk files into your
28 | own Android.mk file, modify your LOCAL_CFLAGS variable to add
29 | include paths for each of the cairo/pixman/cairo-extra/pixman-extra
30 | directories, then finally add libcairo and libpixman to your
31 | LOCAL_STATIC_LIBRARIES variable.
32 |
33 | Once all of that is done, simply run ndk-build to compile everything
34 | together to produce your application's .so file.
35 |
36 | For more concrete usage information, see the example applications
37 | in examples/
38 |
39 | Screenshots
40 | ===========
41 |
42 | 
43 |
--------------------------------------------------------------------------------
/examples/java-bitmap/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/java-bitmap/Makefile:
--------------------------------------------------------------------------------
1 | all: config install
2 |
3 | config: local.properties build.xml
4 |
5 | install:
6 | ndk-build
7 | ant debug install
8 |
9 |
10 | local.properties build.xml:
11 | android update project --name java-bitmap --path .
12 |
13 | clean:
14 | ndk-build clean
15 | ant clean
16 | rm -Rf obj libs
17 |
18 |
19 | .PHONY: all config clean
20 |
--------------------------------------------------------------------------------
/examples/java-bitmap/default.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "build.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-8
12 |
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include jni/pixman.mk
4 | include jni/cairo.mk
5 | include $(CLEAR_VARS)
6 |
7 | LOCAL_MODULE := java-bitmap
8 | LOCAL_CFLAGS := -O2 --std=c99 -I. -Ijni/pixman/pixman -Ijni/cairo/src -Ijni/cairo-extra -Ijni/pixman-extra -Wno-missing-field-initializers
9 | LOCAL_LDLIBS := -lm -llog -ljnigraphics
10 | LOCAL_SRC_FILES := java-bitmap.c
11 | LOCAL_STATIC_LIBRARIES := libcairo libpixman cpufeatures
12 |
13 | include $(BUILD_SHARED_LIBRARY)
14 |
15 | $(call import-module,android/cpufeatures)
16 |
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/Application.mk:
--------------------------------------------------------------------------------
1 | # The ARMv7 is significanly faster due to the use of the hardware FPU
2 | APP_ABI := armeabi armeabi-v7a
3 | APP_PLATFORM := android-8
4 |
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/cairo:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/cairo-extra:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo-extra
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/cairo.mk:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo.mk
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/java-bitmap.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "cairo/src/cairo.h"
27 |
28 | #define LOG_TAG "android-cairo-java-bitmap"
29 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
30 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
31 |
32 |
33 | int tick = 0;
34 |
35 | static void draw_frame(AndroidBitmapInfo *info, void *pixels) {
36 | cairo_surface_t *surface = NULL;
37 |
38 | /* Setup our cairo surface to render directly to the bitmap */
39 | if (info->format == ANDROID_BITMAP_FORMAT_RGB_565) {
40 | surface = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_RGB16_565, info->width, info->height, info->stride);
41 | } else if (info->format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
42 | surface = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_RGB24, info->width, info->height, info->stride);
43 | } else {
44 | LOGE("Unsupported buffer format: %d", info->format);
45 | return;
46 | }
47 |
48 | cairo_t *cr = cairo_create(surface);
49 |
50 | /* clear the screen */
51 | memset(pixels, 0, info->stride*info->height);
52 |
53 | /* Normalize our canvas size to make our lives easier */
54 | cairo_scale(cr, info->width, info->height);
55 |
56 |
57 | /* Draw the big X */
58 | double position = (tick%30)*(1.0/30);
59 | cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.7);
60 | cairo_move_to (cr, 0.1, position);
61 | cairo_line_to (cr, 0.9, 1.0-position);
62 | cairo_move_to (cr, 0.9, position);
63 | cairo_line_to (cr, 0.1, 1.0-position);
64 | cairo_set_line_width (cr, 0.1);
65 | cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
66 | cairo_stroke (cr);
67 |
68 | /* Draw three color squares */
69 | cairo_rectangle (cr, 0, 0,0.5, 0.5);
70 | cairo_set_source_rgba (cr, 1, 0, 0, 0.50);
71 | cairo_fill (cr);
72 |
73 | cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
74 | cairo_set_source_rgba (cr, 0, 1, 0, 0.50);
75 | cairo_fill (cr);
76 |
77 | cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
78 | cairo_set_source_rgba (cr, 0, 0, 1, 0.50);
79 | cairo_fill (cr);
80 |
81 | /* Draw a more complicated path */
82 | cairo_set_line_width (cr, 0.04);
83 | cairo_scale(cr, 0.5, 0.5);
84 | cairo_translate(cr, 0.5, 1.0);
85 | cairo_set_source_rgba (cr, 1.0, 0.2, 0.0, 0.5);
86 | cairo_move_to (cr, 0.25, 0.25);
87 | cairo_line_to (cr, 0.5, 0.375);
88 | cairo_rel_line_to (cr, 0.25, -0.125);
89 | cairo_arc (cr, 0.5, 0.5, 0.25 * sqrt(2), -0.25 * M_PI, 0.25 * M_PI);
90 | cairo_rel_curve_to (cr, -0.25, -0.125, -0.25, 0.125, -0.5, 0);
91 | cairo_close_path (cr);
92 | cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
93 | cairo_stroke (cr);
94 |
95 | /* Clean up. */
96 | cairo_destroy(cr);
97 | cairo_surface_destroy(surface);
98 | }
99 |
100 |
101 | JNIEXPORT void JNICALL Java_com_example_cairo_CairoView_drawFrame(JNIEnv * env, jobject obj, jobject bitmap) {
102 | AndroidBitmapInfo info;
103 | void* pixels;
104 | int ret;
105 |
106 | ++tick;
107 |
108 | if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
109 | LOGE("AndroidBitmap_getInfo() failed: error=%d", ret);
110 | return;
111 | }
112 |
113 | if (info.format != ANDROID_BITMAP_FORMAT_RGB_565 && info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
114 | LOGE("Bitmap format is not RGB_565 or RGBA_8888");
115 | return;
116 | }
117 |
118 | if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
119 | LOGE("AndroidBitmap_lockPixels() failed: error=%d", ret);
120 | }
121 |
122 | /* Now fill the values with a nice little plasma */
123 | draw_frame(&info, pixels);
124 |
125 | AndroidBitmap_unlockPixels(env, bitmap);
126 | }
127 |
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/pixman:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/pixman-extra:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman-extra
--------------------------------------------------------------------------------
/examples/java-bitmap/jni/pixman.mk:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman.mk
--------------------------------------------------------------------------------
/examples/java-bitmap/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Android Cairo - Java Bitmap
4 |
5 |
--------------------------------------------------------------------------------
/examples/java-bitmap/src/com/example/cairo/Cairo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.example.cairo;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 | import android.content.Context;
21 | import android.view.View;
22 | import android.graphics.Bitmap;
23 | import android.graphics.Canvas;
24 |
25 | public class Cairo extends Activity {
26 | @Override public void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(new CairoView(this));
29 | }
30 |
31 | static {
32 | System.loadLibrary("java-bitmap");
33 | }
34 | }
35 |
36 | class CairoView extends View {
37 | /* implementend by libjava-bitmap.so */
38 | private static native void drawFrame(Bitmap bitmap);
39 |
40 | private Bitmap bmp;
41 |
42 | public CairoView(Context context) {
43 | super(context);
44 | bmp = Bitmap.createBitmap(10,10, Bitmap.Config.RGB_565);
45 |
46 | }
47 |
48 | @Override protected void onDraw(Canvas canvas) {
49 | if (bmp.getWidth() != canvas.getWidth() || bmp.getHeight() != canvas.getHeight()) {
50 | bmp = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.RGB_565);
51 | }
52 |
53 | drawFrame(bmp);
54 | canvas.drawBitmap(bmp, 0, 0, null);
55 | invalidate(); /* force redreaw */
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/examples/pure-ndk/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/examples/pure-ndk/Makefile:
--------------------------------------------------------------------------------
1 | all: config install
2 |
3 | config: local.properties build.xml
4 |
5 | install:
6 | ndk-build
7 | ant install
8 |
9 |
10 | local.properties build.xml:
11 | android update project --name pure-ndk --path .
12 |
13 | clean:
14 | ndk-build clean
15 | ant clean
16 | rm -Rf obj libs
17 |
18 |
19 | .PHONY: all config clean
20 |
--------------------------------------------------------------------------------
/examples/pure-ndk/default.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "build.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-9
12 |
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include jni/pixman.mk
4 | include jni/cairo.mk
5 | include $(CLEAR_VARS)
6 |
7 | LOCAL_MODULE := pure-ndk
8 | LOCAL_CFLAGS := -O2 --std=c99 -I. -Ijni/pixman/pixman -Ijni/cairo/src -Ijni/cairo-extra -Ijni/pixman-extra -Wno-missing-field-initializers
9 | LOCAL_LDLIBS := -lm -llog -landroid
10 | LOCAL_SRC_FILES := pure-ndk.c
11 | LOCAL_STATIC_LIBRARIES := android_native_app_glue libcairo libpixman cpufeatures
12 |
13 | include $(BUILD_SHARED_LIBRARY)
14 |
15 | $(call import-module,android/cpufeatures)
16 | $(call import-module,android/native_app_glue)
17 |
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := armeabi armeabi-v7a
2 | APP_PLATFORM := android-9
3 |
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/cairo:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/cairo-extra:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo-extra/
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/cairo.mk:
--------------------------------------------------------------------------------
1 | ../../../jni/cairo.mk
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/pixman:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/pixman-extra:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman-extra/
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/pixman.mk:
--------------------------------------------------------------------------------
1 | ../../../jni/pixman.mk
--------------------------------------------------------------------------------
/examples/pure-ndk/jni/pure-ndk.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | #include "cairo/src/cairo.h"
15 |
16 | #define LOG_TAG "android-cairo-pure-ndk"
17 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
18 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
19 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
20 |
21 | bool app_has_focus = false;
22 | int tick = 0;
23 |
24 | static void draw_frame(ANativeWindow_Buffer *buffer);
25 | static void handle_app_command(struct android_app* app, int32_t cmd);
26 | static int32_t handle_input(struct android_app* app, AInputEvent* event);
27 |
28 |
29 | void android_main(struct android_app* app) {
30 | // Make sure glue isn't stripped.
31 | app_dummy();
32 |
33 | app->userData = NULL;
34 | app->onAppCmd = handle_app_command;
35 | app->onInputEvent = handle_input;
36 |
37 | while (1) {
38 | // Read all pending events. If app_has_focus is true, then we are going
39 | // to read any events that are ready then render the screen. If we don't
40 | // have focus, we are going to block and spin around the poll loop until
41 | // we get focus again, preventing us from doing a bunch of rendering
42 | // when the app isn't even visible.
43 | int ident;
44 | int events;
45 | struct android_poll_source* source;
46 |
47 | while ((ident=ALooper_pollAll(app_has_focus ? 0 : -1, NULL, &events, (void**)&source)) >= 0) {
48 | // Process this event.
49 | if (source != NULL) {
50 | source->process(app, source);
51 | }
52 |
53 | // Check if we are exiting.
54 | if (app->destroyRequested != 0) {
55 | LOGI("Engine thread destroy requested!");
56 | return;
57 | }
58 | }
59 |
60 |
61 | /* Now that we've delt with input, draw stuff */
62 | if (app->window != NULL) {
63 | ++tick;
64 | LOGI("Rendering frame %d", tick);
65 | ANativeWindow_Buffer buffer;
66 | if (ANativeWindow_lock(app->window, &buffer, NULL) < 0) {
67 | LOGW("Unable to lock window buffer");
68 | continue;
69 | }
70 |
71 | draw_frame(&buffer);
72 |
73 | ANativeWindow_unlockAndPost(app->window);
74 | }
75 | }
76 | }
77 |
78 |
79 | static void handle_app_command(struct android_app* app, int32_t cmd) {
80 | /* app->userData is available here */
81 |
82 | switch (cmd) {
83 | case APP_CMD_INIT_WINDOW:
84 | app_has_focus=true;
85 | break;
86 | case APP_CMD_LOST_FOCUS:
87 | app_has_focus=false;
88 | break;
89 | case APP_CMD_GAINED_FOCUS:
90 | app_has_focus=true;
91 | break;
92 | }
93 | }
94 |
95 | static int32_t handle_input(struct android_app* app, AInputEvent* event) {
96 | /* app->userData is available here */
97 |
98 | if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
99 | app_has_focus = true;
100 | return 1;
101 | } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY) {
102 | LOGI("Key event: action=%d keyCode=%d metaState=0x%x",
103 | AKeyEvent_getAction(event),
104 | AKeyEvent_getKeyCode(event),
105 | AKeyEvent_getMetaState(event));
106 | }
107 |
108 | return 0;
109 | }
110 |
111 |
112 |
113 | static void draw_frame(ANativeWindow_Buffer *buffer) {
114 | int pixel_size = 0;
115 | cairo_surface_t *surface = NULL;
116 |
117 | /* Setup our cairo surface to render directly to the native window buffer */
118 | if (buffer->format == WINDOW_FORMAT_RGB_565) {
119 | pixel_size = 2;
120 | surface = cairo_image_surface_create_for_data(buffer->bits, CAIRO_FORMAT_RGB16_565, buffer->width, buffer->height, buffer->stride*pixel_size);
121 | } else if (buffer->format == WINDOW_FORMAT_RGBA_8888 || buffer->format == WINDOW_FORMAT_RGBX_8888) {
122 | pixel_size = 4;
123 | surface = cairo_image_surface_create_for_data(buffer->bits, CAIRO_FORMAT_RGB24, buffer->width, buffer->height, buffer->stride*pixel_size);
124 | } else {
125 | LOGE("Unsupported buffer format: %d", buffer->format);
126 | return;
127 | }
128 |
129 | cairo_t *cr = cairo_create(surface);
130 |
131 | /* clear the screen */
132 | memset(buffer->bits, 0, buffer->stride*pixel_size*buffer->height);
133 |
134 | /* Normalize our canvas size to make our lives easier */
135 | cairo_scale(cr, buffer->width, buffer->height);
136 |
137 |
138 | /* Draw the big X */
139 | double position = (tick%30)*(1.0/30);
140 | cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.7);
141 | cairo_move_to (cr, 0.1, position);
142 | cairo_line_to (cr, 0.9, 1.0-position);
143 | cairo_move_to (cr, 0.9, position);
144 | cairo_line_to (cr, 0.1, 1.0-position);
145 | cairo_set_line_width (cr, 0.1);
146 | cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
147 | cairo_stroke (cr);
148 |
149 | /* Draw three color squares */
150 | cairo_rectangle (cr, 0, 0,0.5, 0.5);
151 | cairo_set_source_rgba (cr, 1, 0, 0, 0.50);
152 | cairo_fill (cr);
153 |
154 | cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
155 | cairo_set_source_rgba (cr, 0, 1, 0, 0.50);
156 | cairo_fill (cr);
157 |
158 | cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
159 | cairo_set_source_rgba (cr, 0, 0, 1, 0.50);
160 | cairo_fill (cr);
161 |
162 | /* Draw a more complicated path */
163 | cairo_set_line_width (cr, 0.04);
164 | cairo_scale(cr, 0.5, 0.5);
165 | cairo_translate(cr, 0.5, 1.0);
166 | cairo_set_source_rgba (cr, 1.0, 0.2, 0.0, 0.5);
167 | cairo_move_to (cr, 0.25, 0.25);
168 | cairo_line_to (cr, 0.5, 0.375);
169 | cairo_rel_line_to (cr, 0.25, -0.125);
170 | cairo_arc (cr, 0.5, 0.5, 0.25 * sqrt(2), -0.25 * M_PI, 0.25 * M_PI);
171 | cairo_rel_curve_to (cr, -0.25, -0.125, -0.25, 0.125, -0.5, 0);
172 | cairo_close_path (cr);
173 | cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
174 | cairo_stroke (cr);
175 |
176 | /* Clean up. */
177 | cairo_destroy(cr);
178 | cairo_surface_destroy(surface);
179 | }
180 |
--------------------------------------------------------------------------------
/examples/pure-ndk/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Android Cairo - Pure NDK
4 |
5 |
--------------------------------------------------------------------------------
/examples/pure-ndk/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anoek/android-cairo/908b4c34eaea98a81d9ea526e2d80c5263a1cb02/examples/pure-ndk/screenshot.png
--------------------------------------------------------------------------------
/jni/cairo-extra/cairo-features.h:
--------------------------------------------------------------------------------
1 | #ifndef CAIRO_FEATURES_H
2 | #define CAIRO_FEATURES_H
3 |
4 | //#define CAIRO_HAS_FC_FONT 1
5 | //#define CAIRO_HAS_FT_FONT 1
6 | #define CAIRO_HAS_IMAGE_SURFACE 1
7 | #define CAIRO_HAS_RECORDING_SURFACE 1
8 | #define CAIRO_HAS_TEE_SURFACE 1
9 | //#define CAIRO_HAS_USER_FONT 1
10 |
11 | /*#undef CAIRO_HAS_EGL_FUNCTIONS */
12 | /*#undef CAIRO_HAS_PDF_SURFACE */
13 | /*#undef CAIRO_HAS_PNG_FUNCTIONS */
14 | /*#undef CAIRO_HAS_SVG_SURFACE */
15 | /*#undef CAIRO_HAS_GLX_FUNCTIONS */
16 | /*#undef CAIRO_HAS_GOBJECT_FUNCTIONS */
17 | /*#undef CAIRO_HAS_PS_SURFACE */
18 | /*#undef CAIRO_HAS_QUARTZ_FONT */
19 | /*#undef CAIRO_HAS_QUARTZ_SURFACE */
20 | /*#undef CAIRO_HAS_WGL_FUNCTIONS */
21 | /*#undef CAIRO_HAS_WIN32_FONT */
22 | /*#undef CAIRO_HAS_WIN32_SURFACE */
23 | /*#undef CAIRO_HAS_XCB_SHM_FUNCTIONS */
24 | /*#undef CAIRO_HAS_XLIB_SURFACE */
25 | /*#undef CAIRO_HAS_XLIB_XRENDER_SURFACE */
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/jni/cairo-extra/locale.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | /**
30 | * This file has been modified from the original source found in the android
31 | * ndk to provide a minimally working version of localeconv, which is needed
32 | * for cairo. (When Android gets a working implementation of locale.h, this
33 | * hack should be removed.)
34 | * */
35 |
36 | #ifndef _LOCALE_H_
37 | #define _LOCALE_H_
38 |
39 | #include
40 |
41 | __BEGIN_DECLS
42 |
43 | enum {
44 | LC_CTYPE = 0,
45 | LC_NUMERIC = 1,
46 | LC_TIME = 2,
47 | LC_COLLATE = 3,
48 | LC_MONETARY = 4,
49 | LC_MESSAGES = 5,
50 | LC_ALL = 6,
51 | LC_PAPER = 7,
52 | LC_NAME = 8,
53 | LC_ADDRESS = 9,
54 |
55 | LC_TELEPHONE = 10,
56 | LC_MEASUREMENT = 11,
57 | LC_IDENTIFICATION = 12
58 | };
59 |
60 | extern char *setlocale(int category, const char *locale);
61 |
62 | struct lconv {
63 | char* decimal_point;
64 | };
65 |
66 | static struct lconv *localeconv(void) {
67 | static struct lconv hardcoded_lconv = {
68 | "."
69 | };
70 | return &hardcoded_lconv;
71 | }
72 |
73 | __END_DECLS
74 |
75 | #endif /* _LOCALE_H_ */
76 |
--------------------------------------------------------------------------------
/jni/cairo.mk:
--------------------------------------------------------------------------------
1 | LIBCAIRO_SRC = \
2 | cairo/src/cairo-analysis-surface.c \
3 | cairo/src/cairo-arc.c \
4 | cairo/src/cairo-array.c \
5 | cairo/src/cairo-atomic.c \
6 | cairo/src/cairo-base64-stream.c \
7 | cairo/src/cairo-base85-stream.c \
8 | cairo/src/cairo-bentley-ottmann-rectangular.c \
9 | cairo/src/cairo-bentley-ottmann-rectilinear.c \
10 | cairo/src/cairo-bentley-ottmann.c \
11 | cairo/src/cairo-botor-scan-converter.c \
12 | cairo/src/cairo-boxes-intersect.c \
13 | cairo/src/cairo-boxes.c \
14 | cairo/src/cairo.c \
15 | cairo/src/cairo-cache.c \
16 | cairo/src/cairo-cff-subset.c \
17 | cairo/src/cairo-clip-boxes.c \
18 | cairo/src/cairo-clip-polygon.c \
19 | cairo/src/cairo-clip-region.c \
20 | cairo/src/cairo-clip-surface.c \
21 | cairo/src/cairo-clip-tor-scan-converter.c \
22 | cairo/src/cairo-clip.c \
23 | cairo/src/cairo-color.c \
24 | cairo/src/cairo-composite-rectangles.c \
25 | cairo/src/cairo-compositor.c \
26 | cairo/src/cairo-contour.c \
27 | cairo/src/cairo-damage.c \
28 | cairo/src/cairo-debug.c \
29 | cairo/src/cairo-default-context.c \
30 | cairo/src/cairo-deflate-stream.c \
31 | cairo/src/cairo-device.c \
32 | cairo/src/cairo-error.c \
33 | cairo/src/cairo-fallback-compositor.c \
34 | cairo/src/cairo-fixed.c \
35 | cairo/src/cairo-font-face-twin-data.c \
36 | cairo/src/cairo-font-face-twin.c \
37 | cairo/src/cairo-font-face.c \
38 | cairo/src/cairo-font-options.c \
39 | cairo/src/cairo-freed-pool.c \
40 | cairo/src/cairo-freelist.c \
41 | cairo/src/cairo-gstate.c \
42 | cairo/src/cairo-hash.c \
43 | cairo/src/cairo-hull.c \
44 | cairo/src/cairo-image-compositor.c \
45 | cairo/src/cairo-image-info.c \
46 | cairo/src/cairo-image-source.c \
47 | cairo/src/cairo-image-surface.c \
48 | cairo/src/cairo-lzw.c \
49 | cairo/src/cairo-mask-compositor.c \
50 | cairo/src/cairo-matrix.c \
51 | cairo/src/cairo-mesh-pattern-rasterizer.c \
52 | cairo/src/cairo-misc.c \
53 | cairo/src/cairo-mono-scan-converter.c \
54 | cairo/src/cairo-mutex.c \
55 | cairo/src/cairo-no-compositor.c \
56 | cairo/src/cairo-observer.c \
57 | cairo/src/cairo-output-stream.c \
58 | cairo/src/cairo-paginated-surface.c \
59 | cairo/src/cairo-path-bounds.c \
60 | cairo/src/cairo-path-fill.c \
61 | cairo/src/cairo-path-fixed.c \
62 | cairo/src/cairo-path-in-fill.c \
63 | cairo/src/cairo-path-stroke-boxes.c \
64 | cairo/src/cairo-path-stroke-polygon.c \
65 | cairo/src/cairo-path-stroke-tristrip.c \
66 | cairo/src/cairo-path-stroke.c \
67 | cairo/src/cairo-path.c \
68 | cairo/src/cairo-pattern.c \
69 | cairo/src/cairo-pen.c \
70 | cairo/src/cairo-polygon-intersect.c \
71 | cairo/src/cairo-polygon-reduce.c \
72 | cairo/src/cairo-polygon.c \
73 | cairo/src/cairo-raster-source-pattern.c \
74 | cairo/src/cairo-recording-surface.c \
75 | cairo/src/cairo-rectangle.c \
76 | cairo/src/cairo-rectangular-scan-converter.c \
77 | cairo/src/cairo-region.c \
78 | cairo/src/cairo-rtree.c \
79 | cairo/src/cairo-scaled-font-subsets.c \
80 | cairo/src/cairo-scaled-font.c \
81 | cairo/src/cairo-shape-mask-compositor.c \
82 | cairo/src/cairo-slope.c \
83 | cairo/src/cairo-spans-compositor.c \
84 | cairo/src/cairo-spans.c \
85 | cairo/src/cairo-spline.c \
86 | cairo/src/cairo-stroke-dash.c \
87 | cairo/src/cairo-stroke-style.c \
88 | cairo/src/cairo-surface-clipper.c \
89 | cairo/src/cairo-surface-fallback.c \
90 | cairo/src/cairo-surface-observer.c \
91 | cairo/src/cairo-surface-offset.c \
92 | cairo/src/cairo-surface-snapshot.c \
93 | cairo/src/cairo-surface-subsurface.c \
94 | cairo/src/cairo-surface-wrapper.c \
95 | cairo/src/cairo-surface.c \
96 | cairo/src/cairo-tee-surface.c \
97 | cairo/src/cairo-time.c \
98 | cairo/src/cairo-tor-scan-converter.c \
99 | cairo/src/cairo-tor22-scan-converter.c \
100 | cairo/src/cairo-toy-font-face.c \
101 | cairo/src/cairo-traps-compositor.c \
102 | cairo/src/cairo-traps.c \
103 | cairo/src/cairo-tristrip.c \
104 | cairo/src/cairo-truetype-subset.c \
105 | cairo/src/cairo-type1-fallback.c \
106 | cairo/src/cairo-type1-glyph-names.c \
107 | cairo/src/cairo-type1-subset.c \
108 | cairo/src/cairo-type3-glyph-surface.c \
109 | cairo/src/cairo-unicode.c \
110 | cairo/src/cairo-user-font.c \
111 | cairo/src/cairo-version.c \
112 | cairo/src/cairo-wideint.c \
113 |
114 |
115 | LIBCAIRO_CFLAGS:= \
116 | -DPACKAGE_VERSION="\"android-cairo\"" \
117 | -DPACKAGE_BUGREPORT="\"http://github.com/anoek/android-cairo\"" \
118 | -DCAIRO_NO_MUTEX=1 \
119 | -DHAVE_STDINT_H \
120 | -DHAVE_UINT64_T \
121 |
122 |
123 | include $(CLEAR_VARS)
124 |
125 | LOCAL_MODULE := libcairo
126 | LOCAL_CFLAGS := -O2 $(LIBCAIRO_CFLAGS) -Ijni/pixman/pixman -Ijni/cairo/src -Ijni/cairo-extra -Ijni/pixman-extra -Wno-missing-field-initializers -Wno-attributes
127 | LOCAL_LDFLAGS := -lz
128 | LOCAL_SRC_FILES := $(LIBCAIRO_SRC)
129 |
130 | include $(BUILD_STATIC_LIBRARY)
131 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-combine32.c:
--------------------------------------------------------------------------------
1 | /* WARNING: This file is generated by combine.pl from combine.inc.
2 | Please edit one of those files rather than this one. */
3 |
4 | #line 1 "pixman-combine.c.template"
5 | #ifdef HAVE_CONFIG_H
6 | #include
7 | #endif
8 |
9 | #include
10 | #include
11 |
12 | #include "pixman-private.h"
13 |
14 | #include "pixman-combine32.h"
15 |
16 | /*** per channel helper functions ***/
17 |
18 | static void
19 | combine_mask_ca (uint32_t *src, uint32_t *mask)
20 | {
21 | uint32_t a = *mask;
22 |
23 | uint32_t x;
24 | uint16_t xa;
25 |
26 | if (!a)
27 | {
28 | *(src) = 0;
29 | return;
30 | }
31 |
32 | x = *(src);
33 | if (a == ~0)
34 | {
35 | x = x >> A_SHIFT;
36 | x |= x << G_SHIFT;
37 | x |= x << R_SHIFT;
38 | *(mask) = x;
39 | return;
40 | }
41 |
42 | xa = x >> A_SHIFT;
43 | UN8x4_MUL_UN8x4 (x, a);
44 | *(src) = x;
45 |
46 | UN8x4_MUL_UN8 (a, xa);
47 | *(mask) = a;
48 | }
49 |
50 | static void
51 | combine_mask_value_ca (uint32_t *src, const uint32_t *mask)
52 | {
53 | uint32_t a = *mask;
54 | uint32_t x;
55 |
56 | if (!a)
57 | {
58 | *(src) = 0;
59 | return;
60 | }
61 |
62 | if (a == ~0)
63 | return;
64 |
65 | x = *(src);
66 | UN8x4_MUL_UN8x4 (x, a);
67 | *(src) = x;
68 | }
69 |
70 | static void
71 | combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask)
72 | {
73 | uint32_t a = *(mask);
74 | uint32_t x;
75 |
76 | if (!a)
77 | return;
78 |
79 | x = *(src) >> A_SHIFT;
80 | if (x == MASK)
81 | return;
82 |
83 | if (a == ~0)
84 | {
85 | x |= x << G_SHIFT;
86 | x |= x << R_SHIFT;
87 | *(mask) = x;
88 | return;
89 | }
90 |
91 | UN8x4_MUL_UN8 (a, x);
92 | *(mask) = a;
93 | }
94 |
95 | /*
96 | * There are two ways of handling alpha -- either as a single unified value or
97 | * a separate value for each component, hence each macro must have two
98 | * versions. The unified alpha version has a 'U' at the end of the name,
99 | * the component version has a 'C'. Similarly, functions which deal with
100 | * this difference will have two versions using the same convention.
101 | */
102 |
103 | /*
104 | * All of the composing functions
105 | */
106 |
107 | static force_inline uint32_t
108 | combine_mask (const uint32_t *src, const uint32_t *mask, int i)
109 | {
110 | uint32_t s, m;
111 |
112 | if (mask)
113 | {
114 | m = *(mask + i) >> A_SHIFT;
115 |
116 | if (!m)
117 | return 0;
118 | }
119 |
120 | s = *(src + i);
121 |
122 | if (mask)
123 | UN8x4_MUL_UN8 (s, m);
124 |
125 | return s;
126 | }
127 |
128 | static void
129 | combine_clear (pixman_implementation_t *imp,
130 | pixman_op_t op,
131 | uint32_t * dest,
132 | const uint32_t * src,
133 | const uint32_t * mask,
134 | int width)
135 | {
136 | memset (dest, 0, width * sizeof(uint32_t));
137 | }
138 |
139 | static void
140 | combine_dst (pixman_implementation_t *imp,
141 | pixman_op_t op,
142 | uint32_t * dest,
143 | const uint32_t * src,
144 | const uint32_t * mask,
145 | int width)
146 | {
147 | return;
148 | }
149 |
150 | static void
151 | combine_src_u (pixman_implementation_t *imp,
152 | pixman_op_t op,
153 | uint32_t * dest,
154 | const uint32_t * src,
155 | const uint32_t * mask,
156 | int width)
157 | {
158 | int i;
159 |
160 | if (!mask)
161 | memcpy (dest, src, width * sizeof (uint32_t));
162 | else
163 | {
164 | for (i = 0; i < width; ++i)
165 | {
166 | uint32_t s = combine_mask (src, mask, i);
167 |
168 | *(dest + i) = s;
169 | }
170 | }
171 | }
172 |
173 | /* if the Src is opaque, call combine_src_u */
174 | static void
175 | combine_over_u (pixman_implementation_t *imp,
176 | pixman_op_t op,
177 | uint32_t * dest,
178 | const uint32_t * src,
179 | const uint32_t * mask,
180 | int width)
181 | {
182 | int i;
183 |
184 | for (i = 0; i < width; ++i)
185 | {
186 | uint32_t s = combine_mask (src, mask, i);
187 | uint32_t d = *(dest + i);
188 | uint32_t ia = ALPHA_8 (~s);
189 |
190 | UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s);
191 | *(dest + i) = d;
192 | }
193 | }
194 |
195 | /* if the Dst is opaque, this is a noop */
196 | static void
197 | combine_over_reverse_u (pixman_implementation_t *imp,
198 | pixman_op_t op,
199 | uint32_t * dest,
200 | const uint32_t * src,
201 | const uint32_t * mask,
202 | int width)
203 | {
204 | int i;
205 |
206 | for (i = 0; i < width; ++i)
207 | {
208 | uint32_t s = combine_mask (src, mask, i);
209 | uint32_t d = *(dest + i);
210 | uint32_t ia = ALPHA_8 (~*(dest + i));
211 | UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d);
212 | *(dest + i) = s;
213 | }
214 | }
215 |
216 | /* if the Dst is opaque, call combine_src_u */
217 | static void
218 | combine_in_u (pixman_implementation_t *imp,
219 | pixman_op_t op,
220 | uint32_t * dest,
221 | const uint32_t * src,
222 | const uint32_t * mask,
223 | int width)
224 | {
225 | int i;
226 |
227 | for (i = 0; i < width; ++i)
228 | {
229 | uint32_t s = combine_mask (src, mask, i);
230 | uint32_t a = ALPHA_8 (*(dest + i));
231 | UN8x4_MUL_UN8 (s, a);
232 | *(dest + i) = s;
233 | }
234 | }
235 |
236 | /* if the Src is opaque, this is a noop */
237 | static void
238 | combine_in_reverse_u (pixman_implementation_t *imp,
239 | pixman_op_t op,
240 | uint32_t * dest,
241 | const uint32_t * src,
242 | const uint32_t * mask,
243 | int width)
244 | {
245 | int i;
246 |
247 | for (i = 0; i < width; ++i)
248 | {
249 | uint32_t s = combine_mask (src, mask, i);
250 | uint32_t d = *(dest + i);
251 | uint32_t a = ALPHA_8 (s);
252 | UN8x4_MUL_UN8 (d, a);
253 | *(dest + i) = d;
254 | }
255 | }
256 |
257 | /* if the Dst is opaque, call combine_clear */
258 | static void
259 | combine_out_u (pixman_implementation_t *imp,
260 | pixman_op_t op,
261 | uint32_t * dest,
262 | const uint32_t * src,
263 | const uint32_t * mask,
264 | int width)
265 | {
266 | int i;
267 |
268 | for (i = 0; i < width; ++i)
269 | {
270 | uint32_t s = combine_mask (src, mask, i);
271 | uint32_t a = ALPHA_8 (~*(dest + i));
272 | UN8x4_MUL_UN8 (s, a);
273 | *(dest + i) = s;
274 | }
275 | }
276 |
277 | /* if the Src is opaque, call combine_clear */
278 | static void
279 | combine_out_reverse_u (pixman_implementation_t *imp,
280 | pixman_op_t op,
281 | uint32_t * dest,
282 | const uint32_t * src,
283 | const uint32_t * mask,
284 | int width)
285 | {
286 | int i;
287 |
288 | for (i = 0; i < width; ++i)
289 | {
290 | uint32_t s = combine_mask (src, mask, i);
291 | uint32_t d = *(dest + i);
292 | uint32_t a = ALPHA_8 (~s);
293 | UN8x4_MUL_UN8 (d, a);
294 | *(dest + i) = d;
295 | }
296 | }
297 |
298 | /* if the Src is opaque, call combine_in_u */
299 | /* if the Dst is opaque, call combine_over_u */
300 | /* if both the Src and Dst are opaque, call combine_src_u */
301 | static void
302 | combine_atop_u (pixman_implementation_t *imp,
303 | pixman_op_t op,
304 | uint32_t * dest,
305 | const uint32_t * src,
306 | const uint32_t * mask,
307 | int width)
308 | {
309 | int i;
310 |
311 | for (i = 0; i < width; ++i)
312 | {
313 | uint32_t s = combine_mask (src, mask, i);
314 | uint32_t d = *(dest + i);
315 | uint32_t dest_a = ALPHA_8 (d);
316 | uint32_t src_ia = ALPHA_8 (~s);
317 |
318 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia);
319 | *(dest + i) = s;
320 | }
321 | }
322 |
323 | /* if the Src is opaque, call combine_over_reverse_u */
324 | /* if the Dst is opaque, call combine_in_reverse_u */
325 | /* if both the Src and Dst are opaque, call combine_dst_u */
326 | static void
327 | combine_atop_reverse_u (pixman_implementation_t *imp,
328 | pixman_op_t op,
329 | uint32_t * dest,
330 | const uint32_t * src,
331 | const uint32_t * mask,
332 | int width)
333 | {
334 | int i;
335 |
336 | for (i = 0; i < width; ++i)
337 | {
338 | uint32_t s = combine_mask (src, mask, i);
339 | uint32_t d = *(dest + i);
340 | uint32_t src_a = ALPHA_8 (s);
341 | uint32_t dest_ia = ALPHA_8 (~d);
342 |
343 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a);
344 | *(dest + i) = s;
345 | }
346 | }
347 |
348 | /* if the Src is opaque, call combine_over_u */
349 | /* if the Dst is opaque, call combine_over_reverse_u */
350 | /* if both the Src and Dst are opaque, call combine_clear */
351 | static void
352 | combine_xor_u (pixman_implementation_t *imp,
353 | pixman_op_t op,
354 | uint32_t * dest,
355 | const uint32_t * src,
356 | const uint32_t * mask,
357 | int width)
358 | {
359 | int i;
360 |
361 | for (i = 0; i < width; ++i)
362 | {
363 | uint32_t s = combine_mask (src, mask, i);
364 | uint32_t d = *(dest + i);
365 | uint32_t src_ia = ALPHA_8 (~s);
366 | uint32_t dest_ia = ALPHA_8 (~d);
367 |
368 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia);
369 | *(dest + i) = s;
370 | }
371 | }
372 |
373 | static void
374 | combine_add_u (pixman_implementation_t *imp,
375 | pixman_op_t op,
376 | uint32_t * dest,
377 | const uint32_t * src,
378 | const uint32_t * mask,
379 | int width)
380 | {
381 | int i;
382 |
383 | for (i = 0; i < width; ++i)
384 | {
385 | uint32_t s = combine_mask (src, mask, i);
386 | uint32_t d = *(dest + i);
387 | UN8x4_ADD_UN8x4 (d, s);
388 | *(dest + i) = d;
389 | }
390 | }
391 |
392 | /* if the Src is opaque, call combine_add_u */
393 | /* if the Dst is opaque, call combine_add_u */
394 | /* if both the Src and Dst are opaque, call combine_add_u */
395 | static void
396 | combine_saturate_u (pixman_implementation_t *imp,
397 | pixman_op_t op,
398 | uint32_t * dest,
399 | const uint32_t * src,
400 | const uint32_t * mask,
401 | int width)
402 | {
403 | int i;
404 |
405 | for (i = 0; i < width; ++i)
406 | {
407 | uint32_t s = combine_mask (src, mask, i);
408 | uint32_t d = *(dest + i);
409 | uint16_t sa, da;
410 |
411 | sa = s >> A_SHIFT;
412 | da = ~d >> A_SHIFT;
413 | if (sa > da)
414 | {
415 | sa = DIV_UN8 (da, sa);
416 | UN8x4_MUL_UN8 (s, sa);
417 | }
418 | ;
419 | UN8x4_ADD_UN8x4 (d, s);
420 | *(dest + i) = d;
421 | }
422 | }
423 |
424 | /*
425 | * PDF blend modes:
426 | * The following blend modes have been taken from the PDF ISO 32000
427 | * specification, which at this point in time is available from
428 | * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
429 | * The relevant chapters are 11.3.5 and 11.3.6.
430 | * The formula for computing the final pixel color given in 11.3.6 is:
431 | * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
432 | * with B() being the blend function.
433 | * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
434 | *
435 | * These blend modes should match the SVG filter draft specification, as
436 | * it has been designed to mirror ISO 32000. Note that at the current point
437 | * no released draft exists that shows this, as the formulas have not been
438 | * updated yet after the release of ISO 32000.
439 | *
440 | * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
441 | * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
442 | * argument. Note that this implementation operates on premultiplied colors,
443 | * while the PDF specification does not. Therefore the code uses the formula
444 | * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
445 | */
446 |
447 | /*
448 | * Multiply
449 | * B(Dca, ad, Sca, as) = Dca.Sca
450 | */
451 |
452 | static void
453 | combine_multiply_u (pixman_implementation_t *imp,
454 | pixman_op_t op,
455 | uint32_t * dest,
456 | const uint32_t * src,
457 | const uint32_t * mask,
458 | int width)
459 | {
460 | int i;
461 |
462 | for (i = 0; i < width; ++i)
463 | {
464 | uint32_t s = combine_mask (src, mask, i);
465 | uint32_t d = *(dest + i);
466 | uint32_t ss = s;
467 | uint32_t src_ia = ALPHA_8 (~s);
468 | uint32_t dest_ia = ALPHA_8 (~d);
469 |
470 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (ss, dest_ia, d, src_ia);
471 | UN8x4_MUL_UN8x4 (d, s);
472 | UN8x4_ADD_UN8x4 (d, ss);
473 |
474 | *(dest + i) = d;
475 | }
476 | }
477 |
478 | static void
479 | combine_multiply_ca (pixman_implementation_t *imp,
480 | pixman_op_t op,
481 | uint32_t * dest,
482 | const uint32_t * src,
483 | const uint32_t * mask,
484 | int width)
485 | {
486 | int i;
487 |
488 | for (i = 0; i < width; ++i)
489 | {
490 | uint32_t m = *(mask + i);
491 | uint32_t s = *(src + i);
492 | uint32_t d = *(dest + i);
493 | uint32_t r = d;
494 | uint32_t dest_ia = ALPHA_8 (~d);
495 |
496 | combine_mask_value_ca (&s, &m);
497 |
498 | UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia);
499 | UN8x4_MUL_UN8x4 (d, s);
500 | UN8x4_ADD_UN8x4 (r, d);
501 |
502 | *(dest + i) = r;
503 | }
504 | }
505 |
506 | #define PDF_SEPARABLE_BLEND_MODE(name) \
507 | static void \
508 | combine_ ## name ## _u (pixman_implementation_t *imp, \
509 | pixman_op_t op, \
510 | uint32_t * dest, \
511 | const uint32_t * src, \
512 | const uint32_t * mask, \
513 | int width) \
514 | { \
515 | int i; \
516 | for (i = 0; i < width; ++i) { \
517 | uint32_t s = combine_mask (src, mask, i); \
518 | uint32_t d = *(dest + i); \
519 | uint8_t sa = ALPHA_8 (s); \
520 | uint8_t isa = ~sa; \
521 | uint8_t da = ALPHA_8 (d); \
522 | uint8_t ida = ~da; \
523 | uint32_t result; \
524 | \
525 | result = d; \
526 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \
527 | \
528 | *(dest + i) = result + \
529 | (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \
530 | (blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \
531 | (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \
532 | (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa)); \
533 | } \
534 | } \
535 | \
536 | static void \
537 | combine_ ## name ## _ca (pixman_implementation_t *imp, \
538 | pixman_op_t op, \
539 | uint32_t * dest, \
540 | const uint32_t * src, \
541 | const uint32_t * mask, \
542 | int width) \
543 | { \
544 | int i; \
545 | for (i = 0; i < width; ++i) { \
546 | uint32_t m = *(mask + i); \
547 | uint32_t s = *(src + i); \
548 | uint32_t d = *(dest + i); \
549 | uint8_t da = ALPHA_8 (d); \
550 | uint8_t ida = ~da; \
551 | uint32_t result; \
552 | \
553 | combine_mask_value_ca (&s, &m); \
554 | \
555 | result = d; \
556 | UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida); \
557 | \
558 | result += \
559 | (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) + \
560 | (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \
561 | (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \
562 | (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \
563 | \
564 | *(dest + i) = result; \
565 | } \
566 | }
567 |
568 | /*
569 | * Screen
570 | * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
571 | */
572 | static inline uint32_t
573 | blend_screen (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
574 | {
575 | return DIV_ONE_UN8 (sca * da + dca * sa - sca * dca);
576 | }
577 |
578 | PDF_SEPARABLE_BLEND_MODE (screen)
579 |
580 | /*
581 | * Overlay
582 | * B(Dca, Da, Sca, Sa) =
583 | * if 2.Dca < Da
584 | * 2.Sca.Dca
585 | * otherwise
586 | * Sa.Da - 2.(Da - Dca).(Sa - Sca)
587 | */
588 | static inline uint32_t
589 | blend_overlay (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
590 | {
591 | uint32_t rca;
592 |
593 | if (2 * dca < da)
594 | rca = 2 * sca * dca;
595 | else
596 | rca = sa * da - 2 * (da - dca) * (sa - sca);
597 | return DIV_ONE_UN8 (rca);
598 | }
599 |
600 | PDF_SEPARABLE_BLEND_MODE (overlay)
601 |
602 | /*
603 | * Darken
604 | * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
605 | */
606 | static inline uint32_t
607 | blend_darken (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
608 | {
609 | uint32_t s, d;
610 |
611 | s = sca * da;
612 | d = dca * sa;
613 | return DIV_ONE_UN8 (s > d ? d : s);
614 | }
615 |
616 | PDF_SEPARABLE_BLEND_MODE (darken)
617 |
618 | /*
619 | * Lighten
620 | * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
621 | */
622 | static inline uint32_t
623 | blend_lighten (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
624 | {
625 | uint32_t s, d;
626 |
627 | s = sca * da;
628 | d = dca * sa;
629 | return DIV_ONE_UN8 (s > d ? s : d);
630 | }
631 |
632 | PDF_SEPARABLE_BLEND_MODE (lighten)
633 |
634 | /*
635 | * Color dodge
636 | * B(Dca, Da, Sca, Sa) =
637 | * if Dca == 0
638 | * 0
639 | * if Sca == Sa
640 | * Sa.Da
641 | * otherwise
642 | * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
643 | */
644 | static inline uint32_t
645 | blend_color_dodge (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
646 | {
647 | if (sca >= sa)
648 | {
649 | return dca == 0 ? 0 : DIV_ONE_UN8 (sa * da);
650 | }
651 | else
652 | {
653 | uint32_t rca = dca * sa / (sa - sca);
654 | return DIV_ONE_UN8 (sa * MIN (rca, da));
655 | }
656 | }
657 |
658 | PDF_SEPARABLE_BLEND_MODE (color_dodge)
659 |
660 | /*
661 | * Color burn
662 | * B(Dca, Da, Sca, Sa) =
663 | * if Dca == Da
664 | * Sa.Da
665 | * if Sca == 0
666 | * 0
667 | * otherwise
668 | * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
669 | */
670 | static inline uint32_t
671 | blend_color_burn (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
672 | {
673 | if (sca == 0)
674 | {
675 | return dca < da ? 0 : DIV_ONE_UN8 (sa * da);
676 | }
677 | else
678 | {
679 | uint32_t rca = (da - dca) * sa / sca;
680 | return DIV_ONE_UN8 (sa * (MAX (rca, da) - rca));
681 | }
682 | }
683 |
684 | PDF_SEPARABLE_BLEND_MODE (color_burn)
685 |
686 | /*
687 | * Hard light
688 | * B(Dca, Da, Sca, Sa) =
689 | * if 2.Sca < Sa
690 | * 2.Sca.Dca
691 | * otherwise
692 | * Sa.Da - 2.(Da - Dca).(Sa - Sca)
693 | */
694 | static inline uint32_t
695 | blend_hard_light (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
696 | {
697 | if (2 * sca < sa)
698 | return DIV_ONE_UN8 (2 * sca * dca);
699 | else
700 | return DIV_ONE_UN8 (sa * da - 2 * (da - dca) * (sa - sca));
701 | }
702 |
703 | PDF_SEPARABLE_BLEND_MODE (hard_light)
704 |
705 | /*
706 | * Soft light
707 | * B(Dca, Da, Sca, Sa) =
708 | * if (2.Sca <= Sa)
709 | * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
710 | * otherwise if Dca.4 <= Da
711 | * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
712 | * otherwise
713 | * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
714 | */
715 | static inline uint32_t
716 | blend_soft_light (uint32_t dca_org,
717 | uint32_t da_org,
718 | uint32_t sca_org,
719 | uint32_t sa_org)
720 | {
721 | double dca = dca_org * (1.0 / MASK);
722 | double da = da_org * (1.0 / MASK);
723 | double sca = sca_org * (1.0 / MASK);
724 | double sa = sa_org * (1.0 / MASK);
725 | double rca;
726 |
727 | if (2 * sca < sa)
728 | {
729 | if (da == 0)
730 | rca = dca * sa;
731 | else
732 | rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
733 | }
734 | else if (da == 0)
735 | {
736 | rca = 0;
737 | }
738 | else if (4 * dca <= da)
739 | {
740 | rca = dca * sa +
741 | (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
742 | }
743 | else
744 | {
745 | rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
746 | }
747 | return rca * MASK + 0.5;
748 | }
749 |
750 | PDF_SEPARABLE_BLEND_MODE (soft_light)
751 |
752 | /*
753 | * Difference
754 | * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
755 | */
756 | static inline uint32_t
757 | blend_difference (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
758 | {
759 | uint32_t dcasa = dca * sa;
760 | uint32_t scada = sca * da;
761 |
762 | if (scada < dcasa)
763 | return DIV_ONE_UN8 (dcasa - scada);
764 | else
765 | return DIV_ONE_UN8 (scada - dcasa);
766 | }
767 |
768 | PDF_SEPARABLE_BLEND_MODE (difference)
769 |
770 | /*
771 | * Exclusion
772 | * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
773 | */
774 |
775 | /* This can be made faster by writing it directly and not using
776 | * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
777 |
778 | static inline uint32_t
779 | blend_exclusion (uint32_t dca, uint32_t da, uint32_t sca, uint32_t sa)
780 | {
781 | return DIV_ONE_UN8 (sca * da + dca * sa - 2 * dca * sca);
782 | }
783 |
784 | PDF_SEPARABLE_BLEND_MODE (exclusion)
785 |
786 | #undef PDF_SEPARABLE_BLEND_MODE
787 |
788 | /*
789 | * PDF nonseperable blend modes are implemented using the following functions
790 | * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
791 | * and min value of the red, green and blue components.
792 | *
793 | * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
794 | *
795 | * clip_color (C):
796 | * l = LUM (C)
797 | * min = Cmin
798 | * max = Cmax
799 | * if n < 0.0
800 | * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) )
801 | * if x > 1.0
802 | * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
803 | * return C
804 | *
805 | * set_lum (C, l):
806 | * d = l – LUM (C)
807 | * C += d
808 | * return clip_color (C)
809 | *
810 | * SAT (C) = CH_MAX (C) - CH_MIN (C)
811 | *
812 | * set_sat (C, s):
813 | * if Cmax > Cmin
814 | * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
815 | * Cmax = s
816 | * else
817 | * Cmid = Cmax = 0.0
818 | * Cmin = 0.0
819 | * return C
820 | */
821 |
822 | /* For premultiplied colors, we need to know what happens when C is
823 | * multiplied by a real number. LUM and SAT are linear:
824 | *
825 | * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
826 | *
827 | * If we extend clip_color with an extra argument a and change
828 | *
829 | * if x >= 1.0
830 | *
831 | * into
832 | *
833 | * if x >= a
834 | *
835 | * then clip_color is also linear:
836 | *
837 | * r * clip_color (C, a) = clip_color (r_c, ra);
838 | *
839 | * for positive r.
840 | *
841 | * Similarly, we can extend set_lum with an extra argument that is just passed
842 | * on to clip_color:
843 | *
844 | * r * set_lum ( C, l, a)
845 | *
846 | * = r × clip_color ( C + l - LUM (C), a)
847 | *
848 | * = clip_color ( r * C + r × l - r * LUM (C), r * a)
849 | *
850 | * = set_lum ( r * C, r * l, r * a)
851 | *
852 | * Finally, set_sat:
853 | *
854 | * r * set_sat (C, s) = set_sat (x * C, r * s)
855 | *
856 | * The above holds for all non-zero x, because the x'es in the fraction for
857 | * C_mid cancel out. Specifically, it holds for x = r:
858 | *
859 | * r * set_sat (C, s) = set_sat (r_c, rs)
860 | *
861 | */
862 |
863 | /* So, for the non-separable PDF blend modes, we have (using s, d for
864 | * non-premultiplied colors, and S, D for premultiplied:
865 | *
866 | * Color:
867 | *
868 | * a_s * a_d * B(s, d)
869 | * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
870 | * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
871 | *
872 | *
873 | * Luminosity:
874 | *
875 | * a_s * a_d * B(s, d)
876 | * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
877 | * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
878 | *
879 | *
880 | * Saturation:
881 | *
882 | * a_s * a_d * B(s, d)
883 | * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
884 | * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
885 | * a_s * LUM (D), a_s * a_d)
886 | * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
887 | *
888 | * Hue:
889 | *
890 | * a_s * a_d * B(s, d)
891 | * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
892 | * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
893 | *
894 | */
895 |
896 | #define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
897 | #define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
898 | #define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
899 | #define SAT(c) (CH_MAX (c) - CH_MIN (c))
900 |
901 | #define PDF_NON_SEPARABLE_BLEND_MODE(name) \
902 | static void \
903 | combine_ ## name ## _u (pixman_implementation_t *imp, \
904 | pixman_op_t op, \
905 | uint32_t *dest, \
906 | const uint32_t *src, \
907 | const uint32_t *mask, \
908 | int width) \
909 | { \
910 | int i; \
911 | for (i = 0; i < width; ++i) \
912 | { \
913 | uint32_t s = combine_mask (src, mask, i); \
914 | uint32_t d = *(dest + i); \
915 | uint8_t sa = ALPHA_8 (s); \
916 | uint8_t isa = ~sa; \
917 | uint8_t da = ALPHA_8 (d); \
918 | uint8_t ida = ~da; \
919 | uint32_t result; \
920 | uint32_t sc[3], dc[3], c[3]; \
921 | \
922 | result = d; \
923 | UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \
924 | dc[0] = RED_8 (d); \
925 | sc[0] = RED_8 (s); \
926 | dc[1] = GREEN_8 (d); \
927 | sc[1] = GREEN_8 (s); \
928 | dc[2] = BLUE_8 (d); \
929 | sc[2] = BLUE_8 (s); \
930 | blend_ ## name (c, dc, da, sc, sa); \
931 | \
932 | *(dest + i) = result + \
933 | (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \
934 | (DIV_ONE_UN8 (c[0]) << R_SHIFT) + \
935 | (DIV_ONE_UN8 (c[1]) << G_SHIFT) + \
936 | (DIV_ONE_UN8 (c[2])); \
937 | } \
938 | }
939 |
940 | static void
941 | set_lum (uint32_t dest[3], uint32_t src[3], uint32_t sa, uint32_t lum)
942 | {
943 | double a, l, min, max;
944 | double tmp[3];
945 |
946 | a = sa * (1.0 / MASK);
947 |
948 | l = lum * (1.0 / MASK);
949 | tmp[0] = src[0] * (1.0 / MASK);
950 | tmp[1] = src[1] * (1.0 / MASK);
951 | tmp[2] = src[2] * (1.0 / MASK);
952 |
953 | l = l - LUM (tmp);
954 | tmp[0] += l;
955 | tmp[1] += l;
956 | tmp[2] += l;
957 |
958 | /* clip_color */
959 | l = LUM (tmp);
960 | min = CH_MIN (tmp);
961 | max = CH_MAX (tmp);
962 |
963 | if (min < 0)
964 | {
965 | if (l - min == 0.0)
966 | {
967 | tmp[0] = 0;
968 | tmp[1] = 0;
969 | tmp[2] = 0;
970 | }
971 | else
972 | {
973 | tmp[0] = l + (tmp[0] - l) * l / (l - min);
974 | tmp[1] = l + (tmp[1] - l) * l / (l - min);
975 | tmp[2] = l + (tmp[2] - l) * l / (l - min);
976 | }
977 | }
978 | if (max > a)
979 | {
980 | if (max - l == 0.0)
981 | {
982 | tmp[0] = a;
983 | tmp[1] = a;
984 | tmp[2] = a;
985 | }
986 | else
987 | {
988 | tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
989 | tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
990 | tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
991 | }
992 | }
993 |
994 | dest[0] = tmp[0] * MASK + 0.5;
995 | dest[1] = tmp[1] * MASK + 0.5;
996 | dest[2] = tmp[2] * MASK + 0.5;
997 | }
998 |
999 | static void
1000 | set_sat (uint32_t dest[3], uint32_t src[3], uint32_t sat)
1001 | {
1002 | int id[3];
1003 | uint32_t min, max;
1004 |
1005 | if (src[0] > src[1])
1006 | {
1007 | if (src[0] > src[2])
1008 | {
1009 | id[0] = 0;
1010 | if (src[1] > src[2])
1011 | {
1012 | id[1] = 1;
1013 | id[2] = 2;
1014 | }
1015 | else
1016 | {
1017 | id[1] = 2;
1018 | id[2] = 1;
1019 | }
1020 | }
1021 | else
1022 | {
1023 | id[0] = 2;
1024 | id[1] = 0;
1025 | id[2] = 1;
1026 | }
1027 | }
1028 | else
1029 | {
1030 | if (src[0] > src[2])
1031 | {
1032 | id[0] = 1;
1033 | id[1] = 0;
1034 | id[2] = 2;
1035 | }
1036 | else
1037 | {
1038 | id[2] = 0;
1039 | if (src[1] > src[2])
1040 | {
1041 | id[0] = 1;
1042 | id[1] = 2;
1043 | }
1044 | else
1045 | {
1046 | id[0] = 2;
1047 | id[1] = 1;
1048 | }
1049 | }
1050 | }
1051 |
1052 | max = dest[id[0]];
1053 | min = dest[id[2]];
1054 | if (max > min)
1055 | {
1056 | dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
1057 | dest[id[0]] = sat;
1058 | dest[id[2]] = 0;
1059 | }
1060 | else
1061 | {
1062 | dest[0] = dest[1] = dest[2] = 0;
1063 | }
1064 | }
1065 |
1066 | /*
1067 | * Hue:
1068 | * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
1069 | */
1070 | static inline void
1071 | blend_hsl_hue (uint32_t c[3],
1072 | uint32_t dc[3],
1073 | uint32_t da,
1074 | uint32_t sc[3],
1075 | uint32_t sa)
1076 | {
1077 | c[0] = sc[0] * da;
1078 | c[1] = sc[1] * da;
1079 | c[2] = sc[2] * da;
1080 | set_sat (c, c, SAT (dc) * sa);
1081 | set_lum (c, c, sa * da, LUM (dc) * sa);
1082 | }
1083 |
1084 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
1085 |
1086 | /*
1087 | * Saturation:
1088 | * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
1089 | */
1090 | static inline void
1091 | blend_hsl_saturation (uint32_t c[3],
1092 | uint32_t dc[3],
1093 | uint32_t da,
1094 | uint32_t sc[3],
1095 | uint32_t sa)
1096 | {
1097 | c[0] = dc[0] * sa;
1098 | c[1] = dc[1] * sa;
1099 | c[2] = dc[2] * sa;
1100 | set_sat (c, c, SAT (sc) * da);
1101 | set_lum (c, c, sa * da, LUM (dc) * sa);
1102 | }
1103 |
1104 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
1105 |
1106 | /*
1107 | * Color:
1108 | * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
1109 | */
1110 | static inline void
1111 | blend_hsl_color (uint32_t c[3],
1112 | uint32_t dc[3],
1113 | uint32_t da,
1114 | uint32_t sc[3],
1115 | uint32_t sa)
1116 | {
1117 | c[0] = sc[0] * da;
1118 | c[1] = sc[1] * da;
1119 | c[2] = sc[2] * da;
1120 | set_lum (c, c, sa * da, LUM (dc) * sa);
1121 | }
1122 |
1123 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
1124 |
1125 | /*
1126 | * Luminosity:
1127 | * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
1128 | */
1129 | static inline void
1130 | blend_hsl_luminosity (uint32_t c[3],
1131 | uint32_t dc[3],
1132 | uint32_t da,
1133 | uint32_t sc[3],
1134 | uint32_t sa)
1135 | {
1136 | c[0] = dc[0] * sa;
1137 | c[1] = dc[1] * sa;
1138 | c[2] = dc[2] * sa;
1139 | set_lum (c, c, sa * da, LUM (sc) * da);
1140 | }
1141 |
1142 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
1143 |
1144 | #undef SAT
1145 | #undef LUM
1146 | #undef CH_MAX
1147 | #undef CH_MIN
1148 | #undef PDF_NON_SEPARABLE_BLEND_MODE
1149 |
1150 | /* All of the disjoint/conjoint composing functions
1151 | *
1152 | * The four entries in the first column indicate what source contributions
1153 | * come from each of the four areas of the picture -- areas covered by neither
1154 | * A nor B, areas covered only by A, areas covered only by B and finally
1155 | * areas covered by both A and B.
1156 | *
1157 | * Disjoint Conjoint
1158 | * Fa Fb Fa Fb
1159 | * (0,0,0,0) 0 0 0 0
1160 | * (0,A,0,A) 1 0 1 0
1161 | * (0,0,B,B) 0 1 0 1
1162 | * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0)
1163 | * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1
1164 | * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0
1165 | * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1)
1166 | * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0
1167 | * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0)
1168 | * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0)
1169 | * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b)
1170 | * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0)
1171 | *
1172 | * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more
1173 | * information about these operators.
1174 | */
1175 |
1176 | #define COMBINE_A_OUT 1
1177 | #define COMBINE_A_IN 2
1178 | #define COMBINE_B_OUT 4
1179 | #define COMBINE_B_IN 8
1180 |
1181 | #define COMBINE_CLEAR 0
1182 | #define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN)
1183 | #define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN)
1184 | #define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)
1185 | #define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)
1186 | #define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN)
1187 | #define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN)
1188 | #define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT)
1189 |
1190 | /* portion covered by a but not b */
1191 | static uint8_t
1192 | combine_disjoint_out_part (uint8_t a, uint8_t b)
1193 | {
1194 | /* min (1, (1-b) / a) */
1195 |
1196 | b = ~b; /* 1 - b */
1197 | if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
1198 | return MASK; /* 1 */
1199 | return DIV_UN8 (b, a); /* (1-b) / a */
1200 | }
1201 |
1202 | /* portion covered by both a and b */
1203 | static uint8_t
1204 | combine_disjoint_in_part (uint8_t a, uint8_t b)
1205 | {
1206 | /* max (1-(1-b)/a,0) */
1207 | /* = - min ((1-b)/a - 1, 0) */
1208 | /* = 1 - min (1, (1-b)/a) */
1209 |
1210 | b = ~b; /* 1 - b */
1211 | if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
1212 | return 0; /* 1 - 1 */
1213 | return ~DIV_UN8(b, a); /* 1 - (1-b) / a */
1214 | }
1215 |
1216 | /* portion covered by a but not b */
1217 | static uint8_t
1218 | combine_conjoint_out_part (uint8_t a, uint8_t b)
1219 | {
1220 | /* max (1-b/a,0) */
1221 | /* = 1-min(b/a,1) */
1222 |
1223 | /* min (1, (1-b) / a) */
1224 |
1225 | if (b >= a) /* b >= a -> b/a >= 1 */
1226 | return 0x00; /* 0 */
1227 | return ~DIV_UN8(b, a); /* 1 - b/a */
1228 | }
1229 |
1230 | /* portion covered by both a and b */
1231 | static uint8_t
1232 | combine_conjoint_in_part (uint8_t a, uint8_t b)
1233 | {
1234 | /* min (1,b/a) */
1235 |
1236 | if (b >= a) /* b >= a -> b/a >= 1 */
1237 | return MASK; /* 1 */
1238 | return DIV_UN8 (b, a); /* b/a */
1239 | }
1240 |
1241 | #define GET_COMP(v, i) ((uint16_t) (uint8_t) ((v) >> i))
1242 |
1243 | #define ADD(x, y, i, t) \
1244 | ((t) = GET_COMP (x, i) + GET_COMP (y, i), \
1245 | (uint32_t) ((uint8_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
1246 |
1247 | #define GENERIC(x, y, i, ax, ay, t, u, v) \
1248 | ((t) = (MUL_UN8 (GET_COMP (y, i), ay, (u)) + \
1249 | MUL_UN8 (GET_COMP (x, i), ax, (v))), \
1250 | (uint32_t) ((uint8_t) ((t) | \
1251 | (0 - ((t) >> G_SHIFT)))) << (i))
1252 |
1253 | static void
1254 | combine_disjoint_general_u (uint32_t * dest,
1255 | const uint32_t *src,
1256 | const uint32_t *mask,
1257 | int width,
1258 | uint8_t combine)
1259 | {
1260 | int i;
1261 |
1262 | for (i = 0; i < width; ++i)
1263 | {
1264 | uint32_t s = combine_mask (src, mask, i);
1265 | uint32_t d = *(dest + i);
1266 | uint32_t m, n, o, p;
1267 | uint16_t Fa, Fb, t, u, v;
1268 | uint8_t sa = s >> A_SHIFT;
1269 | uint8_t da = d >> A_SHIFT;
1270 |
1271 | switch (combine & COMBINE_A)
1272 | {
1273 | default:
1274 | Fa = 0;
1275 | break;
1276 |
1277 | case COMBINE_A_OUT:
1278 | Fa = combine_disjoint_out_part (sa, da);
1279 | break;
1280 |
1281 | case COMBINE_A_IN:
1282 | Fa = combine_disjoint_in_part (sa, da);
1283 | break;
1284 |
1285 | case COMBINE_A:
1286 | Fa = MASK;
1287 | break;
1288 | }
1289 |
1290 | switch (combine & COMBINE_B)
1291 | {
1292 | default:
1293 | Fb = 0;
1294 | break;
1295 |
1296 | case COMBINE_B_OUT:
1297 | Fb = combine_disjoint_out_part (da, sa);
1298 | break;
1299 |
1300 | case COMBINE_B_IN:
1301 | Fb = combine_disjoint_in_part (da, sa);
1302 | break;
1303 |
1304 | case COMBINE_B:
1305 | Fb = MASK;
1306 | break;
1307 | }
1308 | m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
1309 | n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
1310 | o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
1311 | p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
1312 | s = m | n | o | p;
1313 | *(dest + i) = s;
1314 | }
1315 | }
1316 |
1317 | static void
1318 | combine_disjoint_over_u (pixman_implementation_t *imp,
1319 | pixman_op_t op,
1320 | uint32_t * dest,
1321 | const uint32_t * src,
1322 | const uint32_t * mask,
1323 | int width)
1324 | {
1325 | int i;
1326 |
1327 | for (i = 0; i < width; ++i)
1328 | {
1329 | uint32_t s = combine_mask (src, mask, i);
1330 | uint16_t a = s >> A_SHIFT;
1331 |
1332 | if (s != 0x00)
1333 | {
1334 | uint32_t d = *(dest + i);
1335 | a = combine_disjoint_out_part (d >> A_SHIFT, a);
1336 | UN8x4_MUL_UN8_ADD_UN8x4 (d, a, s);
1337 |
1338 | *(dest + i) = d;
1339 | }
1340 | }
1341 | }
1342 |
1343 | static void
1344 | combine_disjoint_in_u (pixman_implementation_t *imp,
1345 | pixman_op_t op,
1346 | uint32_t * dest,
1347 | const uint32_t * src,
1348 | const uint32_t * mask,
1349 | int width)
1350 | {
1351 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
1352 | }
1353 |
1354 | static void
1355 | combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
1356 | pixman_op_t op,
1357 | uint32_t * dest,
1358 | const uint32_t * src,
1359 | const uint32_t * mask,
1360 | int width)
1361 | {
1362 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
1363 | }
1364 |
1365 | static void
1366 | combine_disjoint_out_u (pixman_implementation_t *imp,
1367 | pixman_op_t op,
1368 | uint32_t * dest,
1369 | const uint32_t * src,
1370 | const uint32_t * mask,
1371 | int width)
1372 | {
1373 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
1374 | }
1375 |
1376 | static void
1377 | combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
1378 | pixman_op_t op,
1379 | uint32_t * dest,
1380 | const uint32_t * src,
1381 | const uint32_t * mask,
1382 | int width)
1383 | {
1384 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
1385 | }
1386 |
1387 | static void
1388 | combine_disjoint_atop_u (pixman_implementation_t *imp,
1389 | pixman_op_t op,
1390 | uint32_t * dest,
1391 | const uint32_t * src,
1392 | const uint32_t * mask,
1393 | int width)
1394 | {
1395 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
1396 | }
1397 |
1398 | static void
1399 | combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
1400 | pixman_op_t op,
1401 | uint32_t * dest,
1402 | const uint32_t * src,
1403 | const uint32_t * mask,
1404 | int width)
1405 | {
1406 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
1407 | }
1408 |
1409 | static void
1410 | combine_disjoint_xor_u (pixman_implementation_t *imp,
1411 | pixman_op_t op,
1412 | uint32_t * dest,
1413 | const uint32_t * src,
1414 | const uint32_t * mask,
1415 | int width)
1416 | {
1417 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
1418 | }
1419 |
1420 | static void
1421 | combine_conjoint_general_u (uint32_t * dest,
1422 | const uint32_t *src,
1423 | const uint32_t *mask,
1424 | int width,
1425 | uint8_t combine)
1426 | {
1427 | int i;
1428 |
1429 | for (i = 0; i < width; ++i)
1430 | {
1431 | uint32_t s = combine_mask (src, mask, i);
1432 | uint32_t d = *(dest + i);
1433 | uint32_t m, n, o, p;
1434 | uint16_t Fa, Fb, t, u, v;
1435 | uint8_t sa = s >> A_SHIFT;
1436 | uint8_t da = d >> A_SHIFT;
1437 |
1438 | switch (combine & COMBINE_A)
1439 | {
1440 | default:
1441 | Fa = 0;
1442 | break;
1443 |
1444 | case COMBINE_A_OUT:
1445 | Fa = combine_conjoint_out_part (sa, da);
1446 | break;
1447 |
1448 | case COMBINE_A_IN:
1449 | Fa = combine_conjoint_in_part (sa, da);
1450 | break;
1451 |
1452 | case COMBINE_A:
1453 | Fa = MASK;
1454 | break;
1455 | }
1456 |
1457 | switch (combine & COMBINE_B)
1458 | {
1459 | default:
1460 | Fb = 0;
1461 | break;
1462 |
1463 | case COMBINE_B_OUT:
1464 | Fb = combine_conjoint_out_part (da, sa);
1465 | break;
1466 |
1467 | case COMBINE_B_IN:
1468 | Fb = combine_conjoint_in_part (da, sa);
1469 | break;
1470 |
1471 | case COMBINE_B:
1472 | Fb = MASK;
1473 | break;
1474 | }
1475 |
1476 | m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
1477 | n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
1478 | o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
1479 | p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
1480 |
1481 | s = m | n | o | p;
1482 |
1483 | *(dest + i) = s;
1484 | }
1485 | }
1486 |
1487 | static void
1488 | combine_conjoint_over_u (pixman_implementation_t *imp,
1489 | pixman_op_t op,
1490 | uint32_t * dest,
1491 | const uint32_t * src,
1492 | const uint32_t * mask,
1493 | int width)
1494 | {
1495 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
1496 | }
1497 |
1498 | static void
1499 | combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
1500 | pixman_op_t op,
1501 | uint32_t * dest,
1502 | const uint32_t * src,
1503 | const uint32_t * mask,
1504 | int width)
1505 | {
1506 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
1507 | }
1508 |
1509 | static void
1510 | combine_conjoint_in_u (pixman_implementation_t *imp,
1511 | pixman_op_t op,
1512 | uint32_t * dest,
1513 | const uint32_t * src,
1514 | const uint32_t * mask,
1515 | int width)
1516 | {
1517 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
1518 | }
1519 |
1520 | static void
1521 | combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
1522 | pixman_op_t op,
1523 | uint32_t * dest,
1524 | const uint32_t * src,
1525 | const uint32_t * mask,
1526 | int width)
1527 | {
1528 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
1529 | }
1530 |
1531 | static void
1532 | combine_conjoint_out_u (pixman_implementation_t *imp,
1533 | pixman_op_t op,
1534 | uint32_t * dest,
1535 | const uint32_t * src,
1536 | const uint32_t * mask,
1537 | int width)
1538 | {
1539 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
1540 | }
1541 |
1542 | static void
1543 | combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
1544 | pixman_op_t op,
1545 | uint32_t * dest,
1546 | const uint32_t * src,
1547 | const uint32_t * mask,
1548 | int width)
1549 | {
1550 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
1551 | }
1552 |
1553 | static void
1554 | combine_conjoint_atop_u (pixman_implementation_t *imp,
1555 | pixman_op_t op,
1556 | uint32_t * dest,
1557 | const uint32_t * src,
1558 | const uint32_t * mask,
1559 | int width)
1560 | {
1561 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
1562 | }
1563 |
1564 | static void
1565 | combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
1566 | pixman_op_t op,
1567 | uint32_t * dest,
1568 | const uint32_t * src,
1569 | const uint32_t * mask,
1570 | int width)
1571 | {
1572 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
1573 | }
1574 |
1575 | static void
1576 | combine_conjoint_xor_u (pixman_implementation_t *imp,
1577 | pixman_op_t op,
1578 | uint32_t * dest,
1579 | const uint32_t * src,
1580 | const uint32_t * mask,
1581 | int width)
1582 | {
1583 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
1584 | }
1585 |
1586 | /************************************************************************/
1587 | /*********************** Per Channel functions **************************/
1588 | /************************************************************************/
1589 |
1590 | static void
1591 | combine_clear_ca (pixman_implementation_t *imp,
1592 | pixman_op_t op,
1593 | uint32_t * dest,
1594 | const uint32_t * src,
1595 | const uint32_t * mask,
1596 | int width)
1597 | {
1598 | memset (dest, 0, width * sizeof(uint32_t));
1599 | }
1600 |
1601 | static void
1602 | combine_src_ca (pixman_implementation_t *imp,
1603 | pixman_op_t op,
1604 | uint32_t * dest,
1605 | const uint32_t * src,
1606 | const uint32_t * mask,
1607 | int width)
1608 | {
1609 | int i;
1610 |
1611 | for (i = 0; i < width; ++i)
1612 | {
1613 | uint32_t s = *(src + i);
1614 | uint32_t m = *(mask + i);
1615 |
1616 | combine_mask_value_ca (&s, &m);
1617 |
1618 | *(dest + i) = s;
1619 | }
1620 | }
1621 |
1622 | static void
1623 | combine_over_ca (pixman_implementation_t *imp,
1624 | pixman_op_t op,
1625 | uint32_t * dest,
1626 | const uint32_t * src,
1627 | const uint32_t * mask,
1628 | int width)
1629 | {
1630 | int i;
1631 |
1632 | for (i = 0; i < width; ++i)
1633 | {
1634 | uint32_t s = *(src + i);
1635 | uint32_t m = *(mask + i);
1636 | uint32_t a;
1637 |
1638 | combine_mask_ca (&s, &m);
1639 |
1640 | a = ~m;
1641 | if (a)
1642 | {
1643 | uint32_t d = *(dest + i);
1644 | UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s);
1645 | s = d;
1646 | }
1647 |
1648 | *(dest + i) = s;
1649 | }
1650 | }
1651 |
1652 | static void
1653 | combine_over_reverse_ca (pixman_implementation_t *imp,
1654 | pixman_op_t op,
1655 | uint32_t * dest,
1656 | const uint32_t * src,
1657 | const uint32_t * mask,
1658 | int width)
1659 | {
1660 | int i;
1661 |
1662 | for (i = 0; i < width; ++i)
1663 | {
1664 | uint32_t d = *(dest + i);
1665 | uint32_t a = ~d >> A_SHIFT;
1666 |
1667 | if (a)
1668 | {
1669 | uint32_t s = *(src + i);
1670 | uint32_t m = *(mask + i);
1671 |
1672 | UN8x4_MUL_UN8x4 (s, m);
1673 | UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d);
1674 |
1675 | *(dest + i) = s;
1676 | }
1677 | }
1678 | }
1679 |
1680 | static void
1681 | combine_in_ca (pixman_implementation_t *imp,
1682 | pixman_op_t op,
1683 | uint32_t * dest,
1684 | const uint32_t * src,
1685 | const uint32_t * mask,
1686 | int width)
1687 | {
1688 | int i;
1689 |
1690 | for (i = 0; i < width; ++i)
1691 | {
1692 | uint32_t d = *(dest + i);
1693 | uint16_t a = d >> A_SHIFT;
1694 | uint32_t s = 0;
1695 |
1696 | if (a)
1697 | {
1698 | uint32_t m = *(mask + i);
1699 |
1700 | s = *(src + i);
1701 | combine_mask_value_ca (&s, &m);
1702 |
1703 | if (a != MASK)
1704 | UN8x4_MUL_UN8 (s, a);
1705 | }
1706 |
1707 | *(dest + i) = s;
1708 | }
1709 | }
1710 |
1711 | static void
1712 | combine_in_reverse_ca (pixman_implementation_t *imp,
1713 | pixman_op_t op,
1714 | uint32_t * dest,
1715 | const uint32_t * src,
1716 | const uint32_t * mask,
1717 | int width)
1718 | {
1719 | int i;
1720 |
1721 | for (i = 0; i < width; ++i)
1722 | {
1723 | uint32_t s = *(src + i);
1724 | uint32_t m = *(mask + i);
1725 | uint32_t a;
1726 |
1727 | combine_mask_alpha_ca (&s, &m);
1728 |
1729 | a = m;
1730 | if (a != ~0)
1731 | {
1732 | uint32_t d = 0;
1733 |
1734 | if (a)
1735 | {
1736 | d = *(dest + i);
1737 | UN8x4_MUL_UN8x4 (d, a);
1738 | }
1739 |
1740 | *(dest + i) = d;
1741 | }
1742 | }
1743 | }
1744 |
1745 | static void
1746 | combine_out_ca (pixman_implementation_t *imp,
1747 | pixman_op_t op,
1748 | uint32_t * dest,
1749 | const uint32_t * src,
1750 | const uint32_t * mask,
1751 | int width)
1752 | {
1753 | int i;
1754 |
1755 | for (i = 0; i < width; ++i)
1756 | {
1757 | uint32_t d = *(dest + i);
1758 | uint16_t a = ~d >> A_SHIFT;
1759 | uint32_t s = 0;
1760 |
1761 | if (a)
1762 | {
1763 | uint32_t m = *(mask + i);
1764 |
1765 | s = *(src + i);
1766 | combine_mask_value_ca (&s, &m);
1767 |
1768 | if (a != MASK)
1769 | UN8x4_MUL_UN8 (s, a);
1770 | }
1771 |
1772 | *(dest + i) = s;
1773 | }
1774 | }
1775 |
1776 | static void
1777 | combine_out_reverse_ca (pixman_implementation_t *imp,
1778 | pixman_op_t op,
1779 | uint32_t * dest,
1780 | const uint32_t * src,
1781 | const uint32_t * mask,
1782 | int width)
1783 | {
1784 | int i;
1785 |
1786 | for (i = 0; i < width; ++i)
1787 | {
1788 | uint32_t s = *(src + i);
1789 | uint32_t m = *(mask + i);
1790 | uint32_t a;
1791 |
1792 | combine_mask_alpha_ca (&s, &m);
1793 |
1794 | a = ~m;
1795 | if (a != ~0)
1796 | {
1797 | uint32_t d = 0;
1798 |
1799 | if (a)
1800 | {
1801 | d = *(dest + i);
1802 | UN8x4_MUL_UN8x4 (d, a);
1803 | }
1804 |
1805 | *(dest + i) = d;
1806 | }
1807 | }
1808 | }
1809 |
1810 | static void
1811 | combine_atop_ca (pixman_implementation_t *imp,
1812 | pixman_op_t op,
1813 | uint32_t * dest,
1814 | const uint32_t * src,
1815 | const uint32_t * mask,
1816 | int width)
1817 | {
1818 | int i;
1819 |
1820 | for (i = 0; i < width; ++i)
1821 | {
1822 | uint32_t d = *(dest + i);
1823 | uint32_t s = *(src + i);
1824 | uint32_t m = *(mask + i);
1825 | uint32_t ad;
1826 | uint16_t as = d >> A_SHIFT;
1827 |
1828 | combine_mask_ca (&s, &m);
1829 |
1830 | ad = ~m;
1831 |
1832 | UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1833 |
1834 | *(dest + i) = d;
1835 | }
1836 | }
1837 |
1838 | static void
1839 | combine_atop_reverse_ca (pixman_implementation_t *imp,
1840 | pixman_op_t op,
1841 | uint32_t * dest,
1842 | const uint32_t * src,
1843 | const uint32_t * mask,
1844 | int width)
1845 | {
1846 | int i;
1847 |
1848 | for (i = 0; i < width; ++i)
1849 | {
1850 | uint32_t d = *(dest + i);
1851 | uint32_t s = *(src + i);
1852 | uint32_t m = *(mask + i);
1853 | uint32_t ad;
1854 | uint16_t as = ~d >> A_SHIFT;
1855 |
1856 | combine_mask_ca (&s, &m);
1857 |
1858 | ad = m;
1859 |
1860 | UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1861 |
1862 | *(dest + i) = d;
1863 | }
1864 | }
1865 |
1866 | static void
1867 | combine_xor_ca (pixman_implementation_t *imp,
1868 | pixman_op_t op,
1869 | uint32_t * dest,
1870 | const uint32_t * src,
1871 | const uint32_t * mask,
1872 | int width)
1873 | {
1874 | int i;
1875 |
1876 | for (i = 0; i < width; ++i)
1877 | {
1878 | uint32_t d = *(dest + i);
1879 | uint32_t s = *(src + i);
1880 | uint32_t m = *(mask + i);
1881 | uint32_t ad;
1882 | uint16_t as = ~d >> A_SHIFT;
1883 |
1884 | combine_mask_ca (&s, &m);
1885 |
1886 | ad = ~m;
1887 |
1888 | UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as);
1889 |
1890 | *(dest + i) = d;
1891 | }
1892 | }
1893 |
1894 | static void
1895 | combine_add_ca (pixman_implementation_t *imp,
1896 | pixman_op_t op,
1897 | uint32_t * dest,
1898 | const uint32_t * src,
1899 | const uint32_t * mask,
1900 | int width)
1901 | {
1902 | int i;
1903 |
1904 | for (i = 0; i < width; ++i)
1905 | {
1906 | uint32_t s = *(src + i);
1907 | uint32_t m = *(mask + i);
1908 | uint32_t d = *(dest + i);
1909 |
1910 | combine_mask_value_ca (&s, &m);
1911 |
1912 | UN8x4_ADD_UN8x4 (d, s);
1913 |
1914 | *(dest + i) = d;
1915 | }
1916 | }
1917 |
1918 | static void
1919 | combine_saturate_ca (pixman_implementation_t *imp,
1920 | pixman_op_t op,
1921 | uint32_t * dest,
1922 | const uint32_t * src,
1923 | const uint32_t * mask,
1924 | int width)
1925 | {
1926 | int i;
1927 |
1928 | for (i = 0; i < width; ++i)
1929 | {
1930 | uint32_t s, d;
1931 | uint16_t sa, sr, sg, sb, da;
1932 | uint16_t t, u, v;
1933 | uint32_t m, n, o, p;
1934 |
1935 | d = *(dest + i);
1936 | s = *(src + i);
1937 | m = *(mask + i);
1938 |
1939 | combine_mask_ca (&s, &m);
1940 |
1941 | sa = (m >> A_SHIFT);
1942 | sr = (m >> R_SHIFT) & MASK;
1943 | sg = (m >> G_SHIFT) & MASK;
1944 | sb = m & MASK;
1945 | da = ~d >> A_SHIFT;
1946 |
1947 | if (sb <= da)
1948 | m = ADD (s, d, 0, t);
1949 | else
1950 | m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v);
1951 |
1952 | if (sg <= da)
1953 | n = ADD (s, d, G_SHIFT, t);
1954 | else
1955 | n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v);
1956 |
1957 | if (sr <= da)
1958 | o = ADD (s, d, R_SHIFT, t);
1959 | else
1960 | o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v);
1961 |
1962 | if (sa <= da)
1963 | p = ADD (s, d, A_SHIFT, t);
1964 | else
1965 | p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v);
1966 |
1967 | *(dest + i) = m | n | o | p;
1968 | }
1969 | }
1970 |
1971 | static void
1972 | combine_disjoint_general_ca (uint32_t * dest,
1973 | const uint32_t *src,
1974 | const uint32_t *mask,
1975 | int width,
1976 | uint8_t combine)
1977 | {
1978 | int i;
1979 |
1980 | for (i = 0; i < width; ++i)
1981 | {
1982 | uint32_t s, d;
1983 | uint32_t m, n, o, p;
1984 | uint32_t Fa, Fb;
1985 | uint16_t t, u, v;
1986 | uint32_t sa;
1987 | uint8_t da;
1988 |
1989 | s = *(src + i);
1990 | m = *(mask + i);
1991 | d = *(dest + i);
1992 | da = d >> A_SHIFT;
1993 |
1994 | combine_mask_ca (&s, &m);
1995 |
1996 | sa = m;
1997 |
1998 | switch (combine & COMBINE_A)
1999 | {
2000 | default:
2001 | Fa = 0;
2002 | break;
2003 |
2004 | case COMBINE_A_OUT:
2005 | m = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> 0), da);
2006 | n = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
2007 | o = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
2008 | p = (uint32_t)combine_disjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
2009 | Fa = m | n | o | p;
2010 | break;
2011 |
2012 | case COMBINE_A_IN:
2013 | m = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> 0), da);
2014 | n = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
2015 | o = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
2016 | p = (uint32_t)combine_disjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
2017 | Fa = m | n | o | p;
2018 | break;
2019 |
2020 | case COMBINE_A:
2021 | Fa = ~0;
2022 | break;
2023 | }
2024 |
2025 | switch (combine & COMBINE_B)
2026 | {
2027 | default:
2028 | Fb = 0;
2029 | break;
2030 |
2031 | case COMBINE_B_OUT:
2032 | m = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> 0));
2033 | n = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
2034 | o = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
2035 | p = (uint32_t)combine_disjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
2036 | Fb = m | n | o | p;
2037 | break;
2038 |
2039 | case COMBINE_B_IN:
2040 | m = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> 0));
2041 | n = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
2042 | o = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
2043 | p = (uint32_t)combine_disjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
2044 | Fb = m | n | o | p;
2045 | break;
2046 |
2047 | case COMBINE_B:
2048 | Fb = ~0;
2049 | break;
2050 | }
2051 | m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
2052 | n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
2053 | o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
2054 | p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
2055 |
2056 | s = m | n | o | p;
2057 |
2058 | *(dest + i) = s;
2059 | }
2060 | }
2061 |
2062 | static void
2063 | combine_disjoint_over_ca (pixman_implementation_t *imp,
2064 | pixman_op_t op,
2065 | uint32_t * dest,
2066 | const uint32_t * src,
2067 | const uint32_t * mask,
2068 | int width)
2069 | {
2070 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
2071 | }
2072 |
2073 | static void
2074 | combine_disjoint_in_ca (pixman_implementation_t *imp,
2075 | pixman_op_t op,
2076 | uint32_t * dest,
2077 | const uint32_t * src,
2078 | const uint32_t * mask,
2079 | int width)
2080 | {
2081 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
2082 | }
2083 |
2084 | static void
2085 | combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
2086 | pixman_op_t op,
2087 | uint32_t * dest,
2088 | const uint32_t * src,
2089 | const uint32_t * mask,
2090 | int width)
2091 | {
2092 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
2093 | }
2094 |
2095 | static void
2096 | combine_disjoint_out_ca (pixman_implementation_t *imp,
2097 | pixman_op_t op,
2098 | uint32_t * dest,
2099 | const uint32_t * src,
2100 | const uint32_t * mask,
2101 | int width)
2102 | {
2103 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
2104 | }
2105 |
2106 | static void
2107 | combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
2108 | pixman_op_t op,
2109 | uint32_t * dest,
2110 | const uint32_t * src,
2111 | const uint32_t * mask,
2112 | int width)
2113 | {
2114 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
2115 | }
2116 |
2117 | static void
2118 | combine_disjoint_atop_ca (pixman_implementation_t *imp,
2119 | pixman_op_t op,
2120 | uint32_t * dest,
2121 | const uint32_t * src,
2122 | const uint32_t * mask,
2123 | int width)
2124 | {
2125 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
2126 | }
2127 |
2128 | static void
2129 | combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
2130 | pixman_op_t op,
2131 | uint32_t * dest,
2132 | const uint32_t * src,
2133 | const uint32_t * mask,
2134 | int width)
2135 | {
2136 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
2137 | }
2138 |
2139 | static void
2140 | combine_disjoint_xor_ca (pixman_implementation_t *imp,
2141 | pixman_op_t op,
2142 | uint32_t * dest,
2143 | const uint32_t * src,
2144 | const uint32_t * mask,
2145 | int width)
2146 | {
2147 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
2148 | }
2149 |
2150 | static void
2151 | combine_conjoint_general_ca (uint32_t * dest,
2152 | const uint32_t *src,
2153 | const uint32_t *mask,
2154 | int width,
2155 | uint8_t combine)
2156 | {
2157 | int i;
2158 |
2159 | for (i = 0; i < width; ++i)
2160 | {
2161 | uint32_t s, d;
2162 | uint32_t m, n, o, p;
2163 | uint32_t Fa, Fb;
2164 | uint16_t t, u, v;
2165 | uint32_t sa;
2166 | uint8_t da;
2167 |
2168 | s = *(src + i);
2169 | m = *(mask + i);
2170 | d = *(dest + i);
2171 | da = d >> A_SHIFT;
2172 |
2173 | combine_mask_ca (&s, &m);
2174 |
2175 | sa = m;
2176 |
2177 | switch (combine & COMBINE_A)
2178 | {
2179 | default:
2180 | Fa = 0;
2181 | break;
2182 |
2183 | case COMBINE_A_OUT:
2184 | m = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> 0), da);
2185 | n = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
2186 | o = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
2187 | p = (uint32_t)combine_conjoint_out_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
2188 | Fa = m | n | o | p;
2189 | break;
2190 |
2191 | case COMBINE_A_IN:
2192 | m = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> 0), da);
2193 | n = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> G_SHIFT), da) << G_SHIFT;
2194 | o = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> R_SHIFT), da) << R_SHIFT;
2195 | p = (uint32_t)combine_conjoint_in_part ((uint8_t) (sa >> A_SHIFT), da) << A_SHIFT;
2196 | Fa = m | n | o | p;
2197 | break;
2198 |
2199 | case COMBINE_A:
2200 | Fa = ~0;
2201 | break;
2202 | }
2203 |
2204 | switch (combine & COMBINE_B)
2205 | {
2206 | default:
2207 | Fb = 0;
2208 | break;
2209 |
2210 | case COMBINE_B_OUT:
2211 | m = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> 0));
2212 | n = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
2213 | o = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
2214 | p = (uint32_t)combine_conjoint_out_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
2215 | Fb = m | n | o | p;
2216 | break;
2217 |
2218 | case COMBINE_B_IN:
2219 | m = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> 0));
2220 | n = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> G_SHIFT)) << G_SHIFT;
2221 | o = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> R_SHIFT)) << R_SHIFT;
2222 | p = (uint32_t)combine_conjoint_in_part (da, (uint8_t) (sa >> A_SHIFT)) << A_SHIFT;
2223 | Fb = m | n | o | p;
2224 | break;
2225 |
2226 | case COMBINE_B:
2227 | Fb = ~0;
2228 | break;
2229 | }
2230 | m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
2231 | n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
2232 | o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
2233 | p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
2234 |
2235 | s = m | n | o | p;
2236 |
2237 | *(dest + i) = s;
2238 | }
2239 | }
2240 |
2241 | static void
2242 | combine_conjoint_over_ca (pixman_implementation_t *imp,
2243 | pixman_op_t op,
2244 | uint32_t * dest,
2245 | const uint32_t * src,
2246 | const uint32_t * mask,
2247 | int width)
2248 | {
2249 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
2250 | }
2251 |
2252 | static void
2253 | combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
2254 | pixman_op_t op,
2255 | uint32_t * dest,
2256 | const uint32_t * src,
2257 | const uint32_t * mask,
2258 | int width)
2259 | {
2260 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
2261 | }
2262 |
2263 | static void
2264 | combine_conjoint_in_ca (pixman_implementation_t *imp,
2265 | pixman_op_t op,
2266 | uint32_t * dest,
2267 | const uint32_t * src,
2268 | const uint32_t * mask,
2269 | int width)
2270 | {
2271 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
2272 | }
2273 |
2274 | static void
2275 | combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
2276 | pixman_op_t op,
2277 | uint32_t * dest,
2278 | const uint32_t * src,
2279 | const uint32_t * mask,
2280 | int width)
2281 | {
2282 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
2283 | }
2284 |
2285 | static void
2286 | combine_conjoint_out_ca (pixman_implementation_t *imp,
2287 | pixman_op_t op,
2288 | uint32_t * dest,
2289 | const uint32_t * src,
2290 | const uint32_t * mask,
2291 | int width)
2292 | {
2293 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
2294 | }
2295 |
2296 | static void
2297 | combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
2298 | pixman_op_t op,
2299 | uint32_t * dest,
2300 | const uint32_t * src,
2301 | const uint32_t * mask,
2302 | int width)
2303 | {
2304 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
2305 | }
2306 |
2307 | static void
2308 | combine_conjoint_atop_ca (pixman_implementation_t *imp,
2309 | pixman_op_t op,
2310 | uint32_t * dest,
2311 | const uint32_t * src,
2312 | const uint32_t * mask,
2313 | int width)
2314 | {
2315 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
2316 | }
2317 |
2318 | static void
2319 | combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
2320 | pixman_op_t op,
2321 | uint32_t * dest,
2322 | const uint32_t * src,
2323 | const uint32_t * mask,
2324 | int width)
2325 | {
2326 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
2327 | }
2328 |
2329 | static void
2330 | combine_conjoint_xor_ca (pixman_implementation_t *imp,
2331 | pixman_op_t op,
2332 | uint32_t * dest,
2333 | const uint32_t * src,
2334 | const uint32_t * mask,
2335 | int width)
2336 | {
2337 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
2338 | }
2339 |
2340 | void
2341 | _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp)
2342 | {
2343 | /* Unified alpha */
2344 | imp->combine_32[PIXMAN_OP_CLEAR] = combine_clear;
2345 | imp->combine_32[PIXMAN_OP_SRC] = combine_src_u;
2346 | imp->combine_32[PIXMAN_OP_DST] = combine_dst;
2347 | imp->combine_32[PIXMAN_OP_OVER] = combine_over_u;
2348 | imp->combine_32[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u;
2349 | imp->combine_32[PIXMAN_OP_IN] = combine_in_u;
2350 | imp->combine_32[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u;
2351 | imp->combine_32[PIXMAN_OP_OUT] = combine_out_u;
2352 | imp->combine_32[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u;
2353 | imp->combine_32[PIXMAN_OP_ATOP] = combine_atop_u;
2354 | imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
2355 | imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u;
2356 | imp->combine_32[PIXMAN_OP_ADD] = combine_add_u;
2357 | imp->combine_32[PIXMAN_OP_SATURATE] = combine_saturate_u;
2358 |
2359 | /* Disjoint, unified */
2360 | imp->combine_32[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear;
2361 | imp->combine_32[PIXMAN_OP_DISJOINT_SRC] = combine_src_u;
2362 | imp->combine_32[PIXMAN_OP_DISJOINT_DST] = combine_dst;
2363 | imp->combine_32[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u;
2364 | imp->combine_32[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u;
2365 | imp->combine_32[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u;
2366 | imp->combine_32[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u;
2367 | imp->combine_32[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u;
2368 | imp->combine_32[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u;
2369 | imp->combine_32[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u;
2370 | imp->combine_32[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u;
2371 | imp->combine_32[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u;
2372 |
2373 | /* Conjoint, unified */
2374 | imp->combine_32[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear;
2375 | imp->combine_32[PIXMAN_OP_CONJOINT_SRC] = combine_src_u;
2376 | imp->combine_32[PIXMAN_OP_CONJOINT_DST] = combine_dst;
2377 | imp->combine_32[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u;
2378 | imp->combine_32[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u;
2379 | imp->combine_32[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u;
2380 | imp->combine_32[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u;
2381 | imp->combine_32[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u;
2382 | imp->combine_32[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u;
2383 | imp->combine_32[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u;
2384 | imp->combine_32[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u;
2385 | imp->combine_32[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u;
2386 |
2387 | imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
2388 | imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u;
2389 | imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u;
2390 | imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u;
2391 | imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
2392 | imp->combine_32[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u;
2393 | imp->combine_32[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u;
2394 | imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
2395 | imp->combine_32[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u;
2396 | imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
2397 | imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
2398 | imp->combine_32[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u;
2399 | imp->combine_32[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u;
2400 | imp->combine_32[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u;
2401 | imp->combine_32[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u;
2402 |
2403 | /* Component alpha combiners */
2404 | imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
2405 | imp->combine_32_ca[PIXMAN_OP_SRC] = combine_src_ca;
2406 | /* dest */
2407 | imp->combine_32_ca[PIXMAN_OP_OVER] = combine_over_ca;
2408 | imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca;
2409 | imp->combine_32_ca[PIXMAN_OP_IN] = combine_in_ca;
2410 | imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca;
2411 | imp->combine_32_ca[PIXMAN_OP_OUT] = combine_out_ca;
2412 | imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca;
2413 | imp->combine_32_ca[PIXMAN_OP_ATOP] = combine_atop_ca;
2414 | imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
2415 | imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca;
2416 | imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca;
2417 | imp->combine_32_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca;
2418 |
2419 | /* Disjoint CA */
2420 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca;
2421 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca;
2422 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst;
2423 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca;
2424 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca;
2425 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca;
2426 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca;
2427 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca;
2428 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca;
2429 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca;
2430 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca;
2431 | imp->combine_32_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca;
2432 |
2433 | /* Conjoint CA */
2434 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca;
2435 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca;
2436 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst;
2437 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca;
2438 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca;
2439 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca;
2440 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca;
2441 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca;
2442 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca;
2443 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca;
2444 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca;
2445 | imp->combine_32_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca;
2446 |
2447 | imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
2448 | imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
2449 | imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
2450 | imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
2451 | imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
2452 | imp->combine_32_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca;
2453 | imp->combine_32_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca;
2454 | imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
2455 | imp->combine_32_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca;
2456 | imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
2457 | imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
2458 |
2459 | /* It is not clear that these make sense, so make them noops for now */
2460 | imp->combine_32_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
2461 | imp->combine_32_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
2462 | imp->combine_32_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
2463 | imp->combine_32_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
2464 | }
2465 |
2466 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-combine32.h:
--------------------------------------------------------------------------------
1 | /* WARNING: This file is generated by combine.pl from combine.inc.
2 | Please edit one of those files rather than this one. */
3 |
4 | #line 1 "pixman-combine.c.template"
5 |
6 | #define COMPONENT_SIZE 8
7 | #define MASK 0xff
8 | #define ONE_HALF 0x80
9 |
10 | #define A_SHIFT 8 * 3
11 | #define R_SHIFT 8 * 2
12 | #define G_SHIFT 8
13 | #define A_MASK 0xff000000
14 | #define R_MASK 0xff0000
15 | #define G_MASK 0xff00
16 |
17 | #define RB_MASK 0xff00ff
18 | #define AG_MASK 0xff00ff00
19 | #define RB_ONE_HALF 0x800080
20 | #define RB_MASK_PLUS_ONE 0x10000100
21 |
22 | #define ALPHA_8(x) ((x) >> A_SHIFT)
23 | #define RED_8(x) (((x) >> R_SHIFT) & MASK)
24 | #define GREEN_8(x) (((x) >> G_SHIFT) & MASK)
25 | #define BLUE_8(x) ((x) & MASK)
26 |
27 | /*
28 | * Helper macros.
29 | */
30 |
31 | #define MUL_UN8(a, b, t) \
32 | ((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
33 |
34 | #define DIV_UN8(a, b) \
35 | (((uint16_t) (a) * MASK + ((b) / 2)) / (b))
36 |
37 | #define ADD_UN8(x, y, t) \
38 | ((t) = (x) + (y), \
39 | (uint32_t) (uint8_t) ((t) | (0 - ((t) >> G_SHIFT))))
40 |
41 | #define DIV_ONE_UN8(x) \
42 | (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
43 |
44 | /*
45 | * The methods below use some tricks to be able to do two color
46 | * components at the same time.
47 | */
48 |
49 | /*
50 | * x_rb = (x_rb * a) / 255
51 | */
52 | #define UN8_rb_MUL_UN8(x, a, t) \
53 | do \
54 | { \
55 | t = ((x) & RB_MASK) * (a); \
56 | t += RB_ONE_HALF; \
57 | x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
58 | x &= RB_MASK; \
59 | } while (0)
60 |
61 | /*
62 | * x_rb = min (x_rb + y_rb, 255)
63 | */
64 | #define UN8_rb_ADD_UN8_rb(x, y, t) \
65 | do \
66 | { \
67 | t = ((x) + (y)); \
68 | t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
69 | x = (t & RB_MASK); \
70 | } while (0)
71 |
72 | /*
73 | * x_rb = (x_rb * a_rb) / 255
74 | */
75 | #define UN8_rb_MUL_UN8_rb(x, a, t) \
76 | do \
77 | { \
78 | t = (x & MASK) * (a & MASK); \
79 | t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
80 | t += RB_ONE_HALF; \
81 | t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
82 | x = t & RB_MASK; \
83 | } while (0)
84 |
85 | /*
86 | * x_c = (x_c * a) / 255
87 | */
88 | #define UN8x4_MUL_UN8(x, a) \
89 | do \
90 | { \
91 | uint32_t r1__, r2__, t__; \
92 | \
93 | r1__ = (x); \
94 | UN8_rb_MUL_UN8 (r1__, (a), t__); \
95 | \
96 | r2__ = (x) >> G_SHIFT; \
97 | UN8_rb_MUL_UN8 (r2__, (a), t__); \
98 | \
99 | (x) = r1__ | (r2__ << G_SHIFT); \
100 | } while (0)
101 |
102 | /*
103 | * x_c = (x_c * a) / 255 + y_c
104 | */
105 | #define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) \
106 | do \
107 | { \
108 | uint32_t r1__, r2__, r3__, t__; \
109 | \
110 | r1__ = (x); \
111 | r2__ = (y) & RB_MASK; \
112 | UN8_rb_MUL_UN8 (r1__, (a), t__); \
113 | UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
114 | \
115 | r2__ = (x) >> G_SHIFT; \
116 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
117 | UN8_rb_MUL_UN8 (r2__, (a), t__); \
118 | UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
119 | \
120 | (x) = r1__ | (r2__ << G_SHIFT); \
121 | } while (0)
122 |
123 | /*
124 | * x_c = (x_c * a + y_c * b) / 255
125 | */
126 | #define UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8(x, a, y, b) \
127 | do \
128 | { \
129 | uint32_t r1__, r2__, r3__, t__; \
130 | \
131 | r1__ = (x); \
132 | r2__ = (y); \
133 | UN8_rb_MUL_UN8 (r1__, (a), t__); \
134 | UN8_rb_MUL_UN8 (r2__, (b), t__); \
135 | UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
136 | \
137 | r2__ = ((x) >> G_SHIFT); \
138 | r3__ = ((y) >> G_SHIFT); \
139 | UN8_rb_MUL_UN8 (r2__, (a), t__); \
140 | UN8_rb_MUL_UN8 (r3__, (b), t__); \
141 | UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
142 | \
143 | (x) = r1__ | (r2__ << G_SHIFT); \
144 | } while (0)
145 |
146 | /*
147 | * x_c = (x_c * a_c) / 255
148 | */
149 | #define UN8x4_MUL_UN8x4(x, a) \
150 | do \
151 | { \
152 | uint32_t r1__, r2__, r3__, t__; \
153 | \
154 | r1__ = (x); \
155 | r2__ = (a); \
156 | UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
157 | \
158 | r2__ = (x) >> G_SHIFT; \
159 | r3__ = (a) >> G_SHIFT; \
160 | UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
161 | \
162 | (x) = r1__ | (r2__ << G_SHIFT); \
163 | } while (0)
164 |
165 | /*
166 | * x_c = (x_c * a_c) / 255 + y_c
167 | */
168 | #define UN8x4_MUL_UN8x4_ADD_UN8x4(x, a, y) \
169 | do \
170 | { \
171 | uint32_t r1__, r2__, r3__, t__; \
172 | \
173 | r1__ = (x); \
174 | r2__ = (a); \
175 | UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
176 | r2__ = (y) & RB_MASK; \
177 | UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
178 | \
179 | r2__ = ((x) >> G_SHIFT); \
180 | r3__ = ((a) >> G_SHIFT); \
181 | UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
182 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
183 | UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
184 | \
185 | (x) = r1__ | (r2__ << G_SHIFT); \
186 | } while (0)
187 |
188 | /*
189 | * x_c = (x_c * a_c + y_c * b) / 255
190 | */
191 | #define UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8(x, a, y, b) \
192 | do \
193 | { \
194 | uint32_t r1__, r2__, r3__, t__; \
195 | \
196 | r1__ = (x); \
197 | r2__ = (a); \
198 | UN8_rb_MUL_UN8_rb (r1__, r2__, t__); \
199 | r2__ = (y); \
200 | UN8_rb_MUL_UN8 (r2__, (b), t__); \
201 | UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
202 | \
203 | r2__ = (x) >> G_SHIFT; \
204 | r3__ = (a) >> G_SHIFT; \
205 | UN8_rb_MUL_UN8_rb (r2__, r3__, t__); \
206 | r3__ = (y) >> G_SHIFT; \
207 | UN8_rb_MUL_UN8 (r3__, (b), t__); \
208 | UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
209 | \
210 | x = r1__ | (r2__ << G_SHIFT); \
211 | } while (0)
212 |
213 | /*
214 | x_c = min(x_c + y_c, 255)
215 | */
216 | #define UN8x4_ADD_UN8x4(x, y) \
217 | do \
218 | { \
219 | uint32_t r1__, r2__, r3__, t__; \
220 | \
221 | r1__ = (x) & RB_MASK; \
222 | r2__ = (y) & RB_MASK; \
223 | UN8_rb_ADD_UN8_rb (r1__, r2__, t__); \
224 | \
225 | r2__ = ((x) >> G_SHIFT) & RB_MASK; \
226 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
227 | UN8_rb_ADD_UN8_rb (r2__, r3__, t__); \
228 | \
229 | x = r1__ | (r2__ << G_SHIFT); \
230 | } while (0)
231 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-combine64.c:
--------------------------------------------------------------------------------
1 | /* WARNING: This file is generated by combine.pl from combine.inc.
2 | Please edit one of those files rather than this one. */
3 |
4 | #line 1 "pixman-combine.c.template"
5 | #ifdef HAVE_CONFIG_H
6 | #include
7 | #endif
8 |
9 | #include
10 | #include
11 |
12 | #include "pixman-private.h"
13 |
14 | #include "pixman-combine64.h"
15 |
16 | /*** per channel helper functions ***/
17 |
18 | static void
19 | combine_mask_ca (uint64_t *src, uint64_t *mask)
20 | {
21 | uint64_t a = *mask;
22 |
23 | uint64_t x;
24 | uint32_t xa;
25 |
26 | if (!a)
27 | {
28 | *(src) = 0;
29 | return;
30 | }
31 |
32 | x = *(src);
33 | if (a == ~0)
34 | {
35 | x = x >> A_SHIFT;
36 | x |= x << G_SHIFT;
37 | x |= x << R_SHIFT;
38 | *(mask) = x;
39 | return;
40 | }
41 |
42 | xa = x >> A_SHIFT;
43 | UN16x4_MUL_UN16x4 (x, a);
44 | *(src) = x;
45 |
46 | UN16x4_MUL_UN16 (a, xa);
47 | *(mask) = a;
48 | }
49 |
50 | static void
51 | combine_mask_value_ca (uint64_t *src, const uint64_t *mask)
52 | {
53 | uint64_t a = *mask;
54 | uint64_t x;
55 |
56 | if (!a)
57 | {
58 | *(src) = 0;
59 | return;
60 | }
61 |
62 | if (a == ~0)
63 | return;
64 |
65 | x = *(src);
66 | UN16x4_MUL_UN16x4 (x, a);
67 | *(src) = x;
68 | }
69 |
70 | static void
71 | combine_mask_alpha_ca (const uint64_t *src, uint64_t *mask)
72 | {
73 | uint64_t a = *(mask);
74 | uint64_t x;
75 |
76 | if (!a)
77 | return;
78 |
79 | x = *(src) >> A_SHIFT;
80 | if (x == MASK)
81 | return;
82 |
83 | if (a == ~0)
84 | {
85 | x |= x << G_SHIFT;
86 | x |= x << R_SHIFT;
87 | *(mask) = x;
88 | return;
89 | }
90 |
91 | UN16x4_MUL_UN16 (a, x);
92 | *(mask) = a;
93 | }
94 |
95 | /*
96 | * There are two ways of handling alpha -- either as a single unified value or
97 | * a separate value for each component, hence each macro must have two
98 | * versions. The unified alpha version has a 'U' at the end of the name,
99 | * the component version has a 'C'. Similarly, functions which deal with
100 | * this difference will have two versions using the same convention.
101 | */
102 |
103 | /*
104 | * All of the composing functions
105 | */
106 |
107 | static force_inline uint64_t
108 | combine_mask (const uint64_t *src, const uint64_t *mask, int i)
109 | {
110 | uint64_t s, m;
111 |
112 | if (mask)
113 | {
114 | m = *(mask + i) >> A_SHIFT;
115 |
116 | if (!m)
117 | return 0;
118 | }
119 |
120 | s = *(src + i);
121 |
122 | if (mask)
123 | UN16x4_MUL_UN16 (s, m);
124 |
125 | return s;
126 | }
127 |
128 | static void
129 | combine_clear (pixman_implementation_t *imp,
130 | pixman_op_t op,
131 | uint64_t * dest,
132 | const uint64_t * src,
133 | const uint64_t * mask,
134 | int width)
135 | {
136 | memset (dest, 0, width * sizeof(uint64_t));
137 | }
138 |
139 | static void
140 | combine_dst (pixman_implementation_t *imp,
141 | pixman_op_t op,
142 | uint64_t * dest,
143 | const uint64_t * src,
144 | const uint64_t * mask,
145 | int width)
146 | {
147 | return;
148 | }
149 |
150 | static void
151 | combine_src_u (pixman_implementation_t *imp,
152 | pixman_op_t op,
153 | uint64_t * dest,
154 | const uint64_t * src,
155 | const uint64_t * mask,
156 | int width)
157 | {
158 | int i;
159 |
160 | if (!mask)
161 | memcpy (dest, src, width * sizeof (uint64_t));
162 | else
163 | {
164 | for (i = 0; i < width; ++i)
165 | {
166 | uint64_t s = combine_mask (src, mask, i);
167 |
168 | *(dest + i) = s;
169 | }
170 | }
171 | }
172 |
173 | /* if the Src is opaque, call combine_src_u */
174 | static void
175 | combine_over_u (pixman_implementation_t *imp,
176 | pixman_op_t op,
177 | uint64_t * dest,
178 | const uint64_t * src,
179 | const uint64_t * mask,
180 | int width)
181 | {
182 | int i;
183 |
184 | for (i = 0; i < width; ++i)
185 | {
186 | uint64_t s = combine_mask (src, mask, i);
187 | uint64_t d = *(dest + i);
188 | uint64_t ia = ALPHA_16 (~s);
189 |
190 | UN16x4_MUL_UN16_ADD_UN16x4 (d, ia, s);
191 | *(dest + i) = d;
192 | }
193 | }
194 |
195 | /* if the Dst is opaque, this is a noop */
196 | static void
197 | combine_over_reverse_u (pixman_implementation_t *imp,
198 | pixman_op_t op,
199 | uint64_t * dest,
200 | const uint64_t * src,
201 | const uint64_t * mask,
202 | int width)
203 | {
204 | int i;
205 |
206 | for (i = 0; i < width; ++i)
207 | {
208 | uint64_t s = combine_mask (src, mask, i);
209 | uint64_t d = *(dest + i);
210 | uint64_t ia = ALPHA_16 (~*(dest + i));
211 | UN16x4_MUL_UN16_ADD_UN16x4 (s, ia, d);
212 | *(dest + i) = s;
213 | }
214 | }
215 |
216 | /* if the Dst is opaque, call combine_src_u */
217 | static void
218 | combine_in_u (pixman_implementation_t *imp,
219 | pixman_op_t op,
220 | uint64_t * dest,
221 | const uint64_t * src,
222 | const uint64_t * mask,
223 | int width)
224 | {
225 | int i;
226 |
227 | for (i = 0; i < width; ++i)
228 | {
229 | uint64_t s = combine_mask (src, mask, i);
230 | uint64_t a = ALPHA_16 (*(dest + i));
231 | UN16x4_MUL_UN16 (s, a);
232 | *(dest + i) = s;
233 | }
234 | }
235 |
236 | /* if the Src is opaque, this is a noop */
237 | static void
238 | combine_in_reverse_u (pixman_implementation_t *imp,
239 | pixman_op_t op,
240 | uint64_t * dest,
241 | const uint64_t * src,
242 | const uint64_t * mask,
243 | int width)
244 | {
245 | int i;
246 |
247 | for (i = 0; i < width; ++i)
248 | {
249 | uint64_t s = combine_mask (src, mask, i);
250 | uint64_t d = *(dest + i);
251 | uint64_t a = ALPHA_16 (s);
252 | UN16x4_MUL_UN16 (d, a);
253 | *(dest + i) = d;
254 | }
255 | }
256 |
257 | /* if the Dst is opaque, call combine_clear */
258 | static void
259 | combine_out_u (pixman_implementation_t *imp,
260 | pixman_op_t op,
261 | uint64_t * dest,
262 | const uint64_t * src,
263 | const uint64_t * mask,
264 | int width)
265 | {
266 | int i;
267 |
268 | for (i = 0; i < width; ++i)
269 | {
270 | uint64_t s = combine_mask (src, mask, i);
271 | uint64_t a = ALPHA_16 (~*(dest + i));
272 | UN16x4_MUL_UN16 (s, a);
273 | *(dest + i) = s;
274 | }
275 | }
276 |
277 | /* if the Src is opaque, call combine_clear */
278 | static void
279 | combine_out_reverse_u (pixman_implementation_t *imp,
280 | pixman_op_t op,
281 | uint64_t * dest,
282 | const uint64_t * src,
283 | const uint64_t * mask,
284 | int width)
285 | {
286 | int i;
287 |
288 | for (i = 0; i < width; ++i)
289 | {
290 | uint64_t s = combine_mask (src, mask, i);
291 | uint64_t d = *(dest + i);
292 | uint64_t a = ALPHA_16 (~s);
293 | UN16x4_MUL_UN16 (d, a);
294 | *(dest + i) = d;
295 | }
296 | }
297 |
298 | /* if the Src is opaque, call combine_in_u */
299 | /* if the Dst is opaque, call combine_over_u */
300 | /* if both the Src and Dst are opaque, call combine_src_u */
301 | static void
302 | combine_atop_u (pixman_implementation_t *imp,
303 | pixman_op_t op,
304 | uint64_t * dest,
305 | const uint64_t * src,
306 | const uint64_t * mask,
307 | int width)
308 | {
309 | int i;
310 |
311 | for (i = 0; i < width; ++i)
312 | {
313 | uint64_t s = combine_mask (src, mask, i);
314 | uint64_t d = *(dest + i);
315 | uint64_t dest_a = ALPHA_16 (d);
316 | uint64_t src_ia = ALPHA_16 (~s);
317 |
318 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (s, dest_a, d, src_ia);
319 | *(dest + i) = s;
320 | }
321 | }
322 |
323 | /* if the Src is opaque, call combine_over_reverse_u */
324 | /* if the Dst is opaque, call combine_in_reverse_u */
325 | /* if both the Src and Dst are opaque, call combine_dst_u */
326 | static void
327 | combine_atop_reverse_u (pixman_implementation_t *imp,
328 | pixman_op_t op,
329 | uint64_t * dest,
330 | const uint64_t * src,
331 | const uint64_t * mask,
332 | int width)
333 | {
334 | int i;
335 |
336 | for (i = 0; i < width; ++i)
337 | {
338 | uint64_t s = combine_mask (src, mask, i);
339 | uint64_t d = *(dest + i);
340 | uint64_t src_a = ALPHA_16 (s);
341 | uint64_t dest_ia = ALPHA_16 (~d);
342 |
343 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (s, dest_ia, d, src_a);
344 | *(dest + i) = s;
345 | }
346 | }
347 |
348 | /* if the Src is opaque, call combine_over_u */
349 | /* if the Dst is opaque, call combine_over_reverse_u */
350 | /* if both the Src and Dst are opaque, call combine_clear */
351 | static void
352 | combine_xor_u (pixman_implementation_t *imp,
353 | pixman_op_t op,
354 | uint64_t * dest,
355 | const uint64_t * src,
356 | const uint64_t * mask,
357 | int width)
358 | {
359 | int i;
360 |
361 | for (i = 0; i < width; ++i)
362 | {
363 | uint64_t s = combine_mask (src, mask, i);
364 | uint64_t d = *(dest + i);
365 | uint64_t src_ia = ALPHA_16 (~s);
366 | uint64_t dest_ia = ALPHA_16 (~d);
367 |
368 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (s, dest_ia, d, src_ia);
369 | *(dest + i) = s;
370 | }
371 | }
372 |
373 | static void
374 | combine_add_u (pixman_implementation_t *imp,
375 | pixman_op_t op,
376 | uint64_t * dest,
377 | const uint64_t * src,
378 | const uint64_t * mask,
379 | int width)
380 | {
381 | int i;
382 |
383 | for (i = 0; i < width; ++i)
384 | {
385 | uint64_t s = combine_mask (src, mask, i);
386 | uint64_t d = *(dest + i);
387 | UN16x4_ADD_UN16x4 (d, s);
388 | *(dest + i) = d;
389 | }
390 | }
391 |
392 | /* if the Src is opaque, call combine_add_u */
393 | /* if the Dst is opaque, call combine_add_u */
394 | /* if both the Src and Dst are opaque, call combine_add_u */
395 | static void
396 | combine_saturate_u (pixman_implementation_t *imp,
397 | pixman_op_t op,
398 | uint64_t * dest,
399 | const uint64_t * src,
400 | const uint64_t * mask,
401 | int width)
402 | {
403 | int i;
404 |
405 | for (i = 0; i < width; ++i)
406 | {
407 | uint64_t s = combine_mask (src, mask, i);
408 | uint64_t d = *(dest + i);
409 | uint32_t sa, da;
410 |
411 | sa = s >> A_SHIFT;
412 | da = ~d >> A_SHIFT;
413 | if (sa > da)
414 | {
415 | sa = DIV_UN16 (da, sa);
416 | UN16x4_MUL_UN16 (s, sa);
417 | }
418 | ;
419 | UN16x4_ADD_UN16x4 (d, s);
420 | *(dest + i) = d;
421 | }
422 | }
423 |
424 | /*
425 | * PDF blend modes:
426 | * The following blend modes have been taken from the PDF ISO 32000
427 | * specification, which at this point in time is available from
428 | * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
429 | * The relevant chapters are 11.3.5 and 11.3.6.
430 | * The formula for computing the final pixel color given in 11.3.6 is:
431 | * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
432 | * with B() being the blend function.
433 | * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
434 | *
435 | * These blend modes should match the SVG filter draft specification, as
436 | * it has been designed to mirror ISO 32000. Note that at the current point
437 | * no released draft exists that shows this, as the formulas have not been
438 | * updated yet after the release of ISO 32000.
439 | *
440 | * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and
441 | * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an
442 | * argument. Note that this implementation operates on premultiplied colors,
443 | * while the PDF specification does not. Therefore the code uses the formula
444 | * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
445 | */
446 |
447 | /*
448 | * Multiply
449 | * B(Dca, ad, Sca, as) = Dca.Sca
450 | */
451 |
452 | static void
453 | combine_multiply_u (pixman_implementation_t *imp,
454 | pixman_op_t op,
455 | uint64_t * dest,
456 | const uint64_t * src,
457 | const uint64_t * mask,
458 | int width)
459 | {
460 | int i;
461 |
462 | for (i = 0; i < width; ++i)
463 | {
464 | uint64_t s = combine_mask (src, mask, i);
465 | uint64_t d = *(dest + i);
466 | uint64_t ss = s;
467 | uint64_t src_ia = ALPHA_16 (~s);
468 | uint64_t dest_ia = ALPHA_16 (~d);
469 |
470 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (ss, dest_ia, d, src_ia);
471 | UN16x4_MUL_UN16x4 (d, s);
472 | UN16x4_ADD_UN16x4 (d, ss);
473 |
474 | *(dest + i) = d;
475 | }
476 | }
477 |
478 | static void
479 | combine_multiply_ca (pixman_implementation_t *imp,
480 | pixman_op_t op,
481 | uint64_t * dest,
482 | const uint64_t * src,
483 | const uint64_t * mask,
484 | int width)
485 | {
486 | int i;
487 |
488 | for (i = 0; i < width; ++i)
489 | {
490 | uint64_t m = *(mask + i);
491 | uint64_t s = *(src + i);
492 | uint64_t d = *(dest + i);
493 | uint64_t r = d;
494 | uint64_t dest_ia = ALPHA_16 (~d);
495 |
496 | combine_mask_value_ca (&s, &m);
497 |
498 | UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (r, ~m, s, dest_ia);
499 | UN16x4_MUL_UN16x4 (d, s);
500 | UN16x4_ADD_UN16x4 (r, d);
501 |
502 | *(dest + i) = r;
503 | }
504 | }
505 |
506 | #define PDF_SEPARABLE_BLEND_MODE(name) \
507 | static void \
508 | combine_ ## name ## _u (pixman_implementation_t *imp, \
509 | pixman_op_t op, \
510 | uint64_t * dest, \
511 | const uint64_t * src, \
512 | const uint64_t * mask, \
513 | int width) \
514 | { \
515 | int i; \
516 | for (i = 0; i < width; ++i) { \
517 | uint64_t s = combine_mask (src, mask, i); \
518 | uint64_t d = *(dest + i); \
519 | uint16_t sa = ALPHA_16 (s); \
520 | uint16_t isa = ~sa; \
521 | uint16_t da = ALPHA_16 (d); \
522 | uint16_t ida = ~da; \
523 | uint64_t result; \
524 | \
525 | result = d; \
526 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (result, isa, s, ida); \
527 | \
528 | *(dest + i) = result + \
529 | (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \
530 | (blend_ ## name (RED_16 (d), da, RED_16 (s), sa) << R_SHIFT) + \
531 | (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), sa) << G_SHIFT) + \
532 | (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), sa)); \
533 | } \
534 | } \
535 | \
536 | static void \
537 | combine_ ## name ## _ca (pixman_implementation_t *imp, \
538 | pixman_op_t op, \
539 | uint64_t * dest, \
540 | const uint64_t * src, \
541 | const uint64_t * mask, \
542 | int width) \
543 | { \
544 | int i; \
545 | for (i = 0; i < width; ++i) { \
546 | uint64_t m = *(mask + i); \
547 | uint64_t s = *(src + i); \
548 | uint64_t d = *(dest + i); \
549 | uint16_t da = ALPHA_16 (d); \
550 | uint16_t ida = ~da; \
551 | uint64_t result; \
552 | \
553 | combine_mask_value_ca (&s, &m); \
554 | \
555 | result = d; \
556 | UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (result, ~m, s, ida); \
557 | \
558 | result += \
559 | (DIV_ONE_UN16 (ALPHA_16 (m) * (uint64_t)da) << A_SHIFT) + \
560 | (blend_ ## name (RED_16 (d), da, RED_16 (s), RED_16 (m)) << R_SHIFT) + \
561 | (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), GREEN_16 (m)) << G_SHIFT) + \
562 | (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), BLUE_16 (m))); \
563 | \
564 | *(dest + i) = result; \
565 | } \
566 | }
567 |
568 | /*
569 | * Screen
570 | * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
571 | */
572 | static inline uint64_t
573 | blend_screen (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
574 | {
575 | return DIV_ONE_UN16 (sca * da + dca * sa - sca * dca);
576 | }
577 |
578 | PDF_SEPARABLE_BLEND_MODE (screen)
579 |
580 | /*
581 | * Overlay
582 | * B(Dca, Da, Sca, Sa) =
583 | * if 2.Dca < Da
584 | * 2.Sca.Dca
585 | * otherwise
586 | * Sa.Da - 2.(Da - Dca).(Sa - Sca)
587 | */
588 | static inline uint64_t
589 | blend_overlay (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
590 | {
591 | uint64_t rca;
592 |
593 | if (2 * dca < da)
594 | rca = 2 * sca * dca;
595 | else
596 | rca = sa * da - 2 * (da - dca) * (sa - sca);
597 | return DIV_ONE_UN16 (rca);
598 | }
599 |
600 | PDF_SEPARABLE_BLEND_MODE (overlay)
601 |
602 | /*
603 | * Darken
604 | * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa)
605 | */
606 | static inline uint64_t
607 | blend_darken (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
608 | {
609 | uint64_t s, d;
610 |
611 | s = sca * da;
612 | d = dca * sa;
613 | return DIV_ONE_UN16 (s > d ? d : s);
614 | }
615 |
616 | PDF_SEPARABLE_BLEND_MODE (darken)
617 |
618 | /*
619 | * Lighten
620 | * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa)
621 | */
622 | static inline uint64_t
623 | blend_lighten (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
624 | {
625 | uint64_t s, d;
626 |
627 | s = sca * da;
628 | d = dca * sa;
629 | return DIV_ONE_UN16 (s > d ? s : d);
630 | }
631 |
632 | PDF_SEPARABLE_BLEND_MODE (lighten)
633 |
634 | /*
635 | * Color dodge
636 | * B(Dca, Da, Sca, Sa) =
637 | * if Dca == 0
638 | * 0
639 | * if Sca == Sa
640 | * Sa.Da
641 | * otherwise
642 | * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa))
643 | */
644 | static inline uint64_t
645 | blend_color_dodge (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
646 | {
647 | if (sca >= sa)
648 | {
649 | return dca == 0 ? 0 : DIV_ONE_UN16 (sa * da);
650 | }
651 | else
652 | {
653 | uint64_t rca = dca * sa / (sa - sca);
654 | return DIV_ONE_UN16 (sa * MIN (rca, da));
655 | }
656 | }
657 |
658 | PDF_SEPARABLE_BLEND_MODE (color_dodge)
659 |
660 | /*
661 | * Color burn
662 | * B(Dca, Da, Sca, Sa) =
663 | * if Dca == Da
664 | * Sa.Da
665 | * if Sca == 0
666 | * 0
667 | * otherwise
668 | * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
669 | */
670 | static inline uint64_t
671 | blend_color_burn (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
672 | {
673 | if (sca == 0)
674 | {
675 | return dca < da ? 0 : DIV_ONE_UN16 (sa * da);
676 | }
677 | else
678 | {
679 | uint64_t rca = (da - dca) * sa / sca;
680 | return DIV_ONE_UN16 (sa * (MAX (rca, da) - rca));
681 | }
682 | }
683 |
684 | PDF_SEPARABLE_BLEND_MODE (color_burn)
685 |
686 | /*
687 | * Hard light
688 | * B(Dca, Da, Sca, Sa) =
689 | * if 2.Sca < Sa
690 | * 2.Sca.Dca
691 | * otherwise
692 | * Sa.Da - 2.(Da - Dca).(Sa - Sca)
693 | */
694 | static inline uint64_t
695 | blend_hard_light (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
696 | {
697 | if (2 * sca < sa)
698 | return DIV_ONE_UN16 (2 * sca * dca);
699 | else
700 | return DIV_ONE_UN16 (sa * da - 2 * (da - dca) * (sa - sca));
701 | }
702 |
703 | PDF_SEPARABLE_BLEND_MODE (hard_light)
704 |
705 | /*
706 | * Soft light
707 | * B(Dca, Da, Sca, Sa) =
708 | * if (2.Sca <= Sa)
709 | * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
710 | * otherwise if Dca.4 <= Da
711 | * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
712 | * otherwise
713 | * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
714 | */
715 | static inline uint64_t
716 | blend_soft_light (uint64_t dca_org,
717 | uint64_t da_org,
718 | uint64_t sca_org,
719 | uint64_t sa_org)
720 | {
721 | double dca = dca_org * (1.0 / MASK);
722 | double da = da_org * (1.0 / MASK);
723 | double sca = sca_org * (1.0 / MASK);
724 | double sa = sa_org * (1.0 / MASK);
725 | double rca;
726 |
727 | if (2 * sca < sa)
728 | {
729 | if (da == 0)
730 | rca = dca * sa;
731 | else
732 | rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
733 | }
734 | else if (da == 0)
735 | {
736 | rca = 0;
737 | }
738 | else if (4 * dca <= da)
739 | {
740 | rca = dca * sa +
741 | (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
742 | }
743 | else
744 | {
745 | rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
746 | }
747 | return rca * MASK + 0.5;
748 | }
749 |
750 | PDF_SEPARABLE_BLEND_MODE (soft_light)
751 |
752 | /*
753 | * Difference
754 | * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da)
755 | */
756 | static inline uint64_t
757 | blend_difference (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
758 | {
759 | uint64_t dcasa = dca * sa;
760 | uint64_t scada = sca * da;
761 |
762 | if (scada < dcasa)
763 | return DIV_ONE_UN16 (dcasa - scada);
764 | else
765 | return DIV_ONE_UN16 (scada - dcasa);
766 | }
767 |
768 | PDF_SEPARABLE_BLEND_MODE (difference)
769 |
770 | /*
771 | * Exclusion
772 | * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
773 | */
774 |
775 | /* This can be made faster by writing it directly and not using
776 | * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */
777 |
778 | static inline uint64_t
779 | blend_exclusion (uint64_t dca, uint64_t da, uint64_t sca, uint64_t sa)
780 | {
781 | return DIV_ONE_UN16 (sca * da + dca * sa - 2 * dca * sca);
782 | }
783 |
784 | PDF_SEPARABLE_BLEND_MODE (exclusion)
785 |
786 | #undef PDF_SEPARABLE_BLEND_MODE
787 |
788 | /*
789 | * PDF nonseperable blend modes are implemented using the following functions
790 | * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid
791 | * and min value of the red, green and blue components.
792 | *
793 | * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
794 | *
795 | * clip_color (C):
796 | * l = LUM (C)
797 | * min = Cmin
798 | * max = Cmax
799 | * if n < 0.0
800 | * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) )
801 | * if x > 1.0
802 | * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
803 | * return C
804 | *
805 | * set_lum (C, l):
806 | * d = l – LUM (C)
807 | * C += d
808 | * return clip_color (C)
809 | *
810 | * SAT (C) = CH_MAX (C) - CH_MIN (C)
811 | *
812 | * set_sat (C, s):
813 | * if Cmax > Cmin
814 | * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
815 | * Cmax = s
816 | * else
817 | * Cmid = Cmax = 0.0
818 | * Cmin = 0.0
819 | * return C
820 | */
821 |
822 | /* For premultiplied colors, we need to know what happens when C is
823 | * multiplied by a real number. LUM and SAT are linear:
824 | *
825 | * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C)
826 | *
827 | * If we extend clip_color with an extra argument a and change
828 | *
829 | * if x >= 1.0
830 | *
831 | * into
832 | *
833 | * if x >= a
834 | *
835 | * then clip_color is also linear:
836 | *
837 | * r * clip_color (C, a) = clip_color (r_c, ra);
838 | *
839 | * for positive r.
840 | *
841 | * Similarly, we can extend set_lum with an extra argument that is just passed
842 | * on to clip_color:
843 | *
844 | * r * set_lum ( C, l, a)
845 | *
846 | * = r × clip_color ( C + l - LUM (C), a)
847 | *
848 | * = clip_color ( r * C + r × l - r * LUM (C), r * a)
849 | *
850 | * = set_lum ( r * C, r * l, r * a)
851 | *
852 | * Finally, set_sat:
853 | *
854 | * r * set_sat (C, s) = set_sat (x * C, r * s)
855 | *
856 | * The above holds for all non-zero x, because the x'es in the fraction for
857 | * C_mid cancel out. Specifically, it holds for x = r:
858 | *
859 | * r * set_sat (C, s) = set_sat (r_c, rs)
860 | *
861 | */
862 |
863 | /* So, for the non-separable PDF blend modes, we have (using s, d for
864 | * non-premultiplied colors, and S, D for premultiplied:
865 | *
866 | * Color:
867 | *
868 | * a_s * a_d * B(s, d)
869 | * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1)
870 | * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d)
871 | *
872 | *
873 | * Luminosity:
874 | *
875 | * a_s * a_d * B(s, d)
876 | * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1)
877 | * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d)
878 | *
879 | *
880 | * Saturation:
881 | *
882 | * a_s * a_d * B(s, d)
883 | * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1)
884 | * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)),
885 | * a_s * LUM (D), a_s * a_d)
886 | * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d))
887 | *
888 | * Hue:
889 | *
890 | * a_s * a_d * B(s, d)
891 | * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1)
892 | * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d)
893 | *
894 | */
895 |
896 | #define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
897 | #define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
898 | #define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
899 | #define SAT(c) (CH_MAX (c) - CH_MIN (c))
900 |
901 | #define PDF_NON_SEPARABLE_BLEND_MODE(name) \
902 | static void \
903 | combine_ ## name ## _u (pixman_implementation_t *imp, \
904 | pixman_op_t op, \
905 | uint64_t *dest, \
906 | const uint64_t *src, \
907 | const uint64_t *mask, \
908 | int width) \
909 | { \
910 | int i; \
911 | for (i = 0; i < width; ++i) \
912 | { \
913 | uint64_t s = combine_mask (src, mask, i); \
914 | uint64_t d = *(dest + i); \
915 | uint16_t sa = ALPHA_16 (s); \
916 | uint16_t isa = ~sa; \
917 | uint16_t da = ALPHA_16 (d); \
918 | uint16_t ida = ~da; \
919 | uint64_t result; \
920 | uint64_t sc[3], dc[3], c[3]; \
921 | \
922 | result = d; \
923 | UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (result, isa, s, ida); \
924 | dc[0] = RED_16 (d); \
925 | sc[0] = RED_16 (s); \
926 | dc[1] = GREEN_16 (d); \
927 | sc[1] = GREEN_16 (s); \
928 | dc[2] = BLUE_16 (d); \
929 | sc[2] = BLUE_16 (s); \
930 | blend_ ## name (c, dc, da, sc, sa); \
931 | \
932 | *(dest + i) = result + \
933 | (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \
934 | (DIV_ONE_UN16 (c[0]) << R_SHIFT) + \
935 | (DIV_ONE_UN16 (c[1]) << G_SHIFT) + \
936 | (DIV_ONE_UN16 (c[2])); \
937 | } \
938 | }
939 |
940 | static void
941 | set_lum (uint64_t dest[3], uint64_t src[3], uint64_t sa, uint64_t lum)
942 | {
943 | double a, l, min, max;
944 | double tmp[3];
945 |
946 | a = sa * (1.0 / MASK);
947 |
948 | l = lum * (1.0 / MASK);
949 | tmp[0] = src[0] * (1.0 / MASK);
950 | tmp[1] = src[1] * (1.0 / MASK);
951 | tmp[2] = src[2] * (1.0 / MASK);
952 |
953 | l = l - LUM (tmp);
954 | tmp[0] += l;
955 | tmp[1] += l;
956 | tmp[2] += l;
957 |
958 | /* clip_color */
959 | l = LUM (tmp);
960 | min = CH_MIN (tmp);
961 | max = CH_MAX (tmp);
962 |
963 | if (min < 0)
964 | {
965 | if (l - min == 0.0)
966 | {
967 | tmp[0] = 0;
968 | tmp[1] = 0;
969 | tmp[2] = 0;
970 | }
971 | else
972 | {
973 | tmp[0] = l + (tmp[0] - l) * l / (l - min);
974 | tmp[1] = l + (tmp[1] - l) * l / (l - min);
975 | tmp[2] = l + (tmp[2] - l) * l / (l - min);
976 | }
977 | }
978 | if (max > a)
979 | {
980 | if (max - l == 0.0)
981 | {
982 | tmp[0] = a;
983 | tmp[1] = a;
984 | tmp[2] = a;
985 | }
986 | else
987 | {
988 | tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
989 | tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
990 | tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
991 | }
992 | }
993 |
994 | dest[0] = tmp[0] * MASK + 0.5;
995 | dest[1] = tmp[1] * MASK + 0.5;
996 | dest[2] = tmp[2] * MASK + 0.5;
997 | }
998 |
999 | static void
1000 | set_sat (uint64_t dest[3], uint64_t src[3], uint64_t sat)
1001 | {
1002 | int id[3];
1003 | uint64_t min, max;
1004 |
1005 | if (src[0] > src[1])
1006 | {
1007 | if (src[0] > src[2])
1008 | {
1009 | id[0] = 0;
1010 | if (src[1] > src[2])
1011 | {
1012 | id[1] = 1;
1013 | id[2] = 2;
1014 | }
1015 | else
1016 | {
1017 | id[1] = 2;
1018 | id[2] = 1;
1019 | }
1020 | }
1021 | else
1022 | {
1023 | id[0] = 2;
1024 | id[1] = 0;
1025 | id[2] = 1;
1026 | }
1027 | }
1028 | else
1029 | {
1030 | if (src[0] > src[2])
1031 | {
1032 | id[0] = 1;
1033 | id[1] = 0;
1034 | id[2] = 2;
1035 | }
1036 | else
1037 | {
1038 | id[2] = 0;
1039 | if (src[1] > src[2])
1040 | {
1041 | id[0] = 1;
1042 | id[1] = 2;
1043 | }
1044 | else
1045 | {
1046 | id[0] = 2;
1047 | id[1] = 1;
1048 | }
1049 | }
1050 | }
1051 |
1052 | max = dest[id[0]];
1053 | min = dest[id[2]];
1054 | if (max > min)
1055 | {
1056 | dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
1057 | dest[id[0]] = sat;
1058 | dest[id[2]] = 0;
1059 | }
1060 | else
1061 | {
1062 | dest[0] = dest[1] = dest[2] = 0;
1063 | }
1064 | }
1065 |
1066 | /*
1067 | * Hue:
1068 | * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb))
1069 | */
1070 | static inline void
1071 | blend_hsl_hue (uint64_t c[3],
1072 | uint64_t dc[3],
1073 | uint64_t da,
1074 | uint64_t sc[3],
1075 | uint64_t sa)
1076 | {
1077 | c[0] = sc[0] * da;
1078 | c[1] = sc[1] * da;
1079 | c[2] = sc[2] * da;
1080 | set_sat (c, c, SAT (dc) * sa);
1081 | set_lum (c, c, sa * da, LUM (dc) * sa);
1082 | }
1083 |
1084 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue)
1085 |
1086 | /*
1087 | * Saturation:
1088 | * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb))
1089 | */
1090 | static inline void
1091 | blend_hsl_saturation (uint64_t c[3],
1092 | uint64_t dc[3],
1093 | uint64_t da,
1094 | uint64_t sc[3],
1095 | uint64_t sa)
1096 | {
1097 | c[0] = dc[0] * sa;
1098 | c[1] = dc[1] * sa;
1099 | c[2] = dc[2] * sa;
1100 | set_sat (c, c, SAT (sc) * da);
1101 | set_lum (c, c, sa * da, LUM (dc) * sa);
1102 | }
1103 |
1104 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation)
1105 |
1106 | /*
1107 | * Color:
1108 | * B(Cb, Cs) = set_lum (Cs, LUM (Cb))
1109 | */
1110 | static inline void
1111 | blend_hsl_color (uint64_t c[3],
1112 | uint64_t dc[3],
1113 | uint64_t da,
1114 | uint64_t sc[3],
1115 | uint64_t sa)
1116 | {
1117 | c[0] = sc[0] * da;
1118 | c[1] = sc[1] * da;
1119 | c[2] = sc[2] * da;
1120 | set_lum (c, c, sa * da, LUM (dc) * sa);
1121 | }
1122 |
1123 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_color)
1124 |
1125 | /*
1126 | * Luminosity:
1127 | * B(Cb, Cs) = set_lum (Cb, LUM (Cs))
1128 | */
1129 | static inline void
1130 | blend_hsl_luminosity (uint64_t c[3],
1131 | uint64_t dc[3],
1132 | uint64_t da,
1133 | uint64_t sc[3],
1134 | uint64_t sa)
1135 | {
1136 | c[0] = dc[0] * sa;
1137 | c[1] = dc[1] * sa;
1138 | c[2] = dc[2] * sa;
1139 | set_lum (c, c, sa * da, LUM (sc) * da);
1140 | }
1141 |
1142 | PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity)
1143 |
1144 | #undef SAT
1145 | #undef LUM
1146 | #undef CH_MAX
1147 | #undef CH_MIN
1148 | #undef PDF_NON_SEPARABLE_BLEND_MODE
1149 |
1150 | /* All of the disjoint/conjoint composing functions
1151 | *
1152 | * The four entries in the first column indicate what source contributions
1153 | * come from each of the four areas of the picture -- areas covered by neither
1154 | * A nor B, areas covered only by A, areas covered only by B and finally
1155 | * areas covered by both A and B.
1156 | *
1157 | * Disjoint Conjoint
1158 | * Fa Fb Fa Fb
1159 | * (0,0,0,0) 0 0 0 0
1160 | * (0,A,0,A) 1 0 1 0
1161 | * (0,0,B,B) 0 1 0 1
1162 | * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0)
1163 | * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1
1164 | * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0
1165 | * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1)
1166 | * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0
1167 | * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0)
1168 | * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0)
1169 | * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b)
1170 | * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0)
1171 | *
1172 | * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more
1173 | * information about these operators.
1174 | */
1175 |
1176 | #define COMBINE_A_OUT 1
1177 | #define COMBINE_A_IN 2
1178 | #define COMBINE_B_OUT 4
1179 | #define COMBINE_B_IN 8
1180 |
1181 | #define COMBINE_CLEAR 0
1182 | #define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN)
1183 | #define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN)
1184 | #define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)
1185 | #define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)
1186 | #define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN)
1187 | #define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN)
1188 | #define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT)
1189 |
1190 | /* portion covered by a but not b */
1191 | static uint16_t
1192 | combine_disjoint_out_part (uint16_t a, uint16_t b)
1193 | {
1194 | /* min (1, (1-b) / a) */
1195 |
1196 | b = ~b; /* 1 - b */
1197 | if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
1198 | return MASK; /* 1 */
1199 | return DIV_UN16 (b, a); /* (1-b) / a */
1200 | }
1201 |
1202 | /* portion covered by both a and b */
1203 | static uint16_t
1204 | combine_disjoint_in_part (uint16_t a, uint16_t b)
1205 | {
1206 | /* max (1-(1-b)/a,0) */
1207 | /* = - min ((1-b)/a - 1, 0) */
1208 | /* = 1 - min (1, (1-b)/a) */
1209 |
1210 | b = ~b; /* 1 - b */
1211 | if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */
1212 | return 0; /* 1 - 1 */
1213 | return ~DIV_UN16(b, a); /* 1 - (1-b) / a */
1214 | }
1215 |
1216 | /* portion covered by a but not b */
1217 | static uint16_t
1218 | combine_conjoint_out_part (uint16_t a, uint16_t b)
1219 | {
1220 | /* max (1-b/a,0) */
1221 | /* = 1-min(b/a,1) */
1222 |
1223 | /* min (1, (1-b) / a) */
1224 |
1225 | if (b >= a) /* b >= a -> b/a >= 1 */
1226 | return 0x00; /* 0 */
1227 | return ~DIV_UN16(b, a); /* 1 - b/a */
1228 | }
1229 |
1230 | /* portion covered by both a and b */
1231 | static uint16_t
1232 | combine_conjoint_in_part (uint16_t a, uint16_t b)
1233 | {
1234 | /* min (1,b/a) */
1235 |
1236 | if (b >= a) /* b >= a -> b/a >= 1 */
1237 | return MASK; /* 1 */
1238 | return DIV_UN16 (b, a); /* b/a */
1239 | }
1240 |
1241 | #define GET_COMP(v, i) ((uint32_t) (uint16_t) ((v) >> i))
1242 |
1243 | #define ADD(x, y, i, t) \
1244 | ((t) = GET_COMP (x, i) + GET_COMP (y, i), \
1245 | (uint64_t) ((uint16_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
1246 |
1247 | #define GENERIC(x, y, i, ax, ay, t, u, v) \
1248 | ((t) = (MUL_UN16 (GET_COMP (y, i), ay, (u)) + \
1249 | MUL_UN16 (GET_COMP (x, i), ax, (v))), \
1250 | (uint64_t) ((uint16_t) ((t) | \
1251 | (0 - ((t) >> G_SHIFT)))) << (i))
1252 |
1253 | static void
1254 | combine_disjoint_general_u (uint64_t * dest,
1255 | const uint64_t *src,
1256 | const uint64_t *mask,
1257 | int width,
1258 | uint16_t combine)
1259 | {
1260 | int i;
1261 |
1262 | for (i = 0; i < width; ++i)
1263 | {
1264 | uint64_t s = combine_mask (src, mask, i);
1265 | uint64_t d = *(dest + i);
1266 | uint64_t m, n, o, p;
1267 | uint32_t Fa, Fb, t, u, v;
1268 | uint16_t sa = s >> A_SHIFT;
1269 | uint16_t da = d >> A_SHIFT;
1270 |
1271 | switch (combine & COMBINE_A)
1272 | {
1273 | default:
1274 | Fa = 0;
1275 | break;
1276 |
1277 | case COMBINE_A_OUT:
1278 | Fa = combine_disjoint_out_part (sa, da);
1279 | break;
1280 |
1281 | case COMBINE_A_IN:
1282 | Fa = combine_disjoint_in_part (sa, da);
1283 | break;
1284 |
1285 | case COMBINE_A:
1286 | Fa = MASK;
1287 | break;
1288 | }
1289 |
1290 | switch (combine & COMBINE_B)
1291 | {
1292 | default:
1293 | Fb = 0;
1294 | break;
1295 |
1296 | case COMBINE_B_OUT:
1297 | Fb = combine_disjoint_out_part (da, sa);
1298 | break;
1299 |
1300 | case COMBINE_B_IN:
1301 | Fb = combine_disjoint_in_part (da, sa);
1302 | break;
1303 |
1304 | case COMBINE_B:
1305 | Fb = MASK;
1306 | break;
1307 | }
1308 | m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
1309 | n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
1310 | o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
1311 | p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
1312 | s = m | n | o | p;
1313 | *(dest + i) = s;
1314 | }
1315 | }
1316 |
1317 | static void
1318 | combine_disjoint_over_u (pixman_implementation_t *imp,
1319 | pixman_op_t op,
1320 | uint64_t * dest,
1321 | const uint64_t * src,
1322 | const uint64_t * mask,
1323 | int width)
1324 | {
1325 | int i;
1326 |
1327 | for (i = 0; i < width; ++i)
1328 | {
1329 | uint64_t s = combine_mask (src, mask, i);
1330 | uint32_t a = s >> A_SHIFT;
1331 |
1332 | if (s != 0x00)
1333 | {
1334 | uint64_t d = *(dest + i);
1335 | a = combine_disjoint_out_part (d >> A_SHIFT, a);
1336 | UN16x4_MUL_UN16_ADD_UN16x4 (d, a, s);
1337 |
1338 | *(dest + i) = d;
1339 | }
1340 | }
1341 | }
1342 |
1343 | static void
1344 | combine_disjoint_in_u (pixman_implementation_t *imp,
1345 | pixman_op_t op,
1346 | uint64_t * dest,
1347 | const uint64_t * src,
1348 | const uint64_t * mask,
1349 | int width)
1350 | {
1351 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
1352 | }
1353 |
1354 | static void
1355 | combine_disjoint_in_reverse_u (pixman_implementation_t *imp,
1356 | pixman_op_t op,
1357 | uint64_t * dest,
1358 | const uint64_t * src,
1359 | const uint64_t * mask,
1360 | int width)
1361 | {
1362 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
1363 | }
1364 |
1365 | static void
1366 | combine_disjoint_out_u (pixman_implementation_t *imp,
1367 | pixman_op_t op,
1368 | uint64_t * dest,
1369 | const uint64_t * src,
1370 | const uint64_t * mask,
1371 | int width)
1372 | {
1373 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
1374 | }
1375 |
1376 | static void
1377 | combine_disjoint_out_reverse_u (pixman_implementation_t *imp,
1378 | pixman_op_t op,
1379 | uint64_t * dest,
1380 | const uint64_t * src,
1381 | const uint64_t * mask,
1382 | int width)
1383 | {
1384 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
1385 | }
1386 |
1387 | static void
1388 | combine_disjoint_atop_u (pixman_implementation_t *imp,
1389 | pixman_op_t op,
1390 | uint64_t * dest,
1391 | const uint64_t * src,
1392 | const uint64_t * mask,
1393 | int width)
1394 | {
1395 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
1396 | }
1397 |
1398 | static void
1399 | combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,
1400 | pixman_op_t op,
1401 | uint64_t * dest,
1402 | const uint64_t * src,
1403 | const uint64_t * mask,
1404 | int width)
1405 | {
1406 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
1407 | }
1408 |
1409 | static void
1410 | combine_disjoint_xor_u (pixman_implementation_t *imp,
1411 | pixman_op_t op,
1412 | uint64_t * dest,
1413 | const uint64_t * src,
1414 | const uint64_t * mask,
1415 | int width)
1416 | {
1417 | combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);
1418 | }
1419 |
1420 | static void
1421 | combine_conjoint_general_u (uint64_t * dest,
1422 | const uint64_t *src,
1423 | const uint64_t *mask,
1424 | int width,
1425 | uint16_t combine)
1426 | {
1427 | int i;
1428 |
1429 | for (i = 0; i < width; ++i)
1430 | {
1431 | uint64_t s = combine_mask (src, mask, i);
1432 | uint64_t d = *(dest + i);
1433 | uint64_t m, n, o, p;
1434 | uint32_t Fa, Fb, t, u, v;
1435 | uint16_t sa = s >> A_SHIFT;
1436 | uint16_t da = d >> A_SHIFT;
1437 |
1438 | switch (combine & COMBINE_A)
1439 | {
1440 | default:
1441 | Fa = 0;
1442 | break;
1443 |
1444 | case COMBINE_A_OUT:
1445 | Fa = combine_conjoint_out_part (sa, da);
1446 | break;
1447 |
1448 | case COMBINE_A_IN:
1449 | Fa = combine_conjoint_in_part (sa, da);
1450 | break;
1451 |
1452 | case COMBINE_A:
1453 | Fa = MASK;
1454 | break;
1455 | }
1456 |
1457 | switch (combine & COMBINE_B)
1458 | {
1459 | default:
1460 | Fb = 0;
1461 | break;
1462 |
1463 | case COMBINE_B_OUT:
1464 | Fb = combine_conjoint_out_part (da, sa);
1465 | break;
1466 |
1467 | case COMBINE_B_IN:
1468 | Fb = combine_conjoint_in_part (da, sa);
1469 | break;
1470 |
1471 | case COMBINE_B:
1472 | Fb = MASK;
1473 | break;
1474 | }
1475 |
1476 | m = GENERIC (s, d, 0, Fa, Fb, t, u, v);
1477 | n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v);
1478 | o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v);
1479 | p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v);
1480 |
1481 | s = m | n | o | p;
1482 |
1483 | *(dest + i) = s;
1484 | }
1485 | }
1486 |
1487 | static void
1488 | combine_conjoint_over_u (pixman_implementation_t *imp,
1489 | pixman_op_t op,
1490 | uint64_t * dest,
1491 | const uint64_t * src,
1492 | const uint64_t * mask,
1493 | int width)
1494 | {
1495 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);
1496 | }
1497 |
1498 | static void
1499 | combine_conjoint_over_reverse_u (pixman_implementation_t *imp,
1500 | pixman_op_t op,
1501 | uint64_t * dest,
1502 | const uint64_t * src,
1503 | const uint64_t * mask,
1504 | int width)
1505 | {
1506 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);
1507 | }
1508 |
1509 | static void
1510 | combine_conjoint_in_u (pixman_implementation_t *imp,
1511 | pixman_op_t op,
1512 | uint64_t * dest,
1513 | const uint64_t * src,
1514 | const uint64_t * mask,
1515 | int width)
1516 | {
1517 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);
1518 | }
1519 |
1520 | static void
1521 | combine_conjoint_in_reverse_u (pixman_implementation_t *imp,
1522 | pixman_op_t op,
1523 | uint64_t * dest,
1524 | const uint64_t * src,
1525 | const uint64_t * mask,
1526 | int width)
1527 | {
1528 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);
1529 | }
1530 |
1531 | static void
1532 | combine_conjoint_out_u (pixman_implementation_t *imp,
1533 | pixman_op_t op,
1534 | uint64_t * dest,
1535 | const uint64_t * src,
1536 | const uint64_t * mask,
1537 | int width)
1538 | {
1539 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);
1540 | }
1541 |
1542 | static void
1543 | combine_conjoint_out_reverse_u (pixman_implementation_t *imp,
1544 | pixman_op_t op,
1545 | uint64_t * dest,
1546 | const uint64_t * src,
1547 | const uint64_t * mask,
1548 | int width)
1549 | {
1550 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);
1551 | }
1552 |
1553 | static void
1554 | combine_conjoint_atop_u (pixman_implementation_t *imp,
1555 | pixman_op_t op,
1556 | uint64_t * dest,
1557 | const uint64_t * src,
1558 | const uint64_t * mask,
1559 | int width)
1560 | {
1561 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);
1562 | }
1563 |
1564 | static void
1565 | combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,
1566 | pixman_op_t op,
1567 | uint64_t * dest,
1568 | const uint64_t * src,
1569 | const uint64_t * mask,
1570 | int width)
1571 | {
1572 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);
1573 | }
1574 |
1575 | static void
1576 | combine_conjoint_xor_u (pixman_implementation_t *imp,
1577 | pixman_op_t op,
1578 | uint64_t * dest,
1579 | const uint64_t * src,
1580 | const uint64_t * mask,
1581 | int width)
1582 | {
1583 | combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);
1584 | }
1585 |
1586 | /************************************************************************/
1587 | /*********************** Per Channel functions **************************/
1588 | /************************************************************************/
1589 |
1590 | static void
1591 | combine_clear_ca (pixman_implementation_t *imp,
1592 | pixman_op_t op,
1593 | uint64_t * dest,
1594 | const uint64_t * src,
1595 | const uint64_t * mask,
1596 | int width)
1597 | {
1598 | memset (dest, 0, width * sizeof(uint64_t));
1599 | }
1600 |
1601 | static void
1602 | combine_src_ca (pixman_implementation_t *imp,
1603 | pixman_op_t op,
1604 | uint64_t * dest,
1605 | const uint64_t * src,
1606 | const uint64_t * mask,
1607 | int width)
1608 | {
1609 | int i;
1610 |
1611 | for (i = 0; i < width; ++i)
1612 | {
1613 | uint64_t s = *(src + i);
1614 | uint64_t m = *(mask + i);
1615 |
1616 | combine_mask_value_ca (&s, &m);
1617 |
1618 | *(dest + i) = s;
1619 | }
1620 | }
1621 |
1622 | static void
1623 | combine_over_ca (pixman_implementation_t *imp,
1624 | pixman_op_t op,
1625 | uint64_t * dest,
1626 | const uint64_t * src,
1627 | const uint64_t * mask,
1628 | int width)
1629 | {
1630 | int i;
1631 |
1632 | for (i = 0; i < width; ++i)
1633 | {
1634 | uint64_t s = *(src + i);
1635 | uint64_t m = *(mask + i);
1636 | uint64_t a;
1637 |
1638 | combine_mask_ca (&s, &m);
1639 |
1640 | a = ~m;
1641 | if (a)
1642 | {
1643 | uint64_t d = *(dest + i);
1644 | UN16x4_MUL_UN16x4_ADD_UN16x4 (d, a, s);
1645 | s = d;
1646 | }
1647 |
1648 | *(dest + i) = s;
1649 | }
1650 | }
1651 |
1652 | static void
1653 | combine_over_reverse_ca (pixman_implementation_t *imp,
1654 | pixman_op_t op,
1655 | uint64_t * dest,
1656 | const uint64_t * src,
1657 | const uint64_t * mask,
1658 | int width)
1659 | {
1660 | int i;
1661 |
1662 | for (i = 0; i < width; ++i)
1663 | {
1664 | uint64_t d = *(dest + i);
1665 | uint64_t a = ~d >> A_SHIFT;
1666 |
1667 | if (a)
1668 | {
1669 | uint64_t s = *(src + i);
1670 | uint64_t m = *(mask + i);
1671 |
1672 | UN16x4_MUL_UN16x4 (s, m);
1673 | UN16x4_MUL_UN16_ADD_UN16x4 (s, a, d);
1674 |
1675 | *(dest + i) = s;
1676 | }
1677 | }
1678 | }
1679 |
1680 | static void
1681 | combine_in_ca (pixman_implementation_t *imp,
1682 | pixman_op_t op,
1683 | uint64_t * dest,
1684 | const uint64_t * src,
1685 | const uint64_t * mask,
1686 | int width)
1687 | {
1688 | int i;
1689 |
1690 | for (i = 0; i < width; ++i)
1691 | {
1692 | uint64_t d = *(dest + i);
1693 | uint32_t a = d >> A_SHIFT;
1694 | uint64_t s = 0;
1695 |
1696 | if (a)
1697 | {
1698 | uint64_t m = *(mask + i);
1699 |
1700 | s = *(src + i);
1701 | combine_mask_value_ca (&s, &m);
1702 |
1703 | if (a != MASK)
1704 | UN16x4_MUL_UN16 (s, a);
1705 | }
1706 |
1707 | *(dest + i) = s;
1708 | }
1709 | }
1710 |
1711 | static void
1712 | combine_in_reverse_ca (pixman_implementation_t *imp,
1713 | pixman_op_t op,
1714 | uint64_t * dest,
1715 | const uint64_t * src,
1716 | const uint64_t * mask,
1717 | int width)
1718 | {
1719 | int i;
1720 |
1721 | for (i = 0; i < width; ++i)
1722 | {
1723 | uint64_t s = *(src + i);
1724 | uint64_t m = *(mask + i);
1725 | uint64_t a;
1726 |
1727 | combine_mask_alpha_ca (&s, &m);
1728 |
1729 | a = m;
1730 | if (a != ~0)
1731 | {
1732 | uint64_t d = 0;
1733 |
1734 | if (a)
1735 | {
1736 | d = *(dest + i);
1737 | UN16x4_MUL_UN16x4 (d, a);
1738 | }
1739 |
1740 | *(dest + i) = d;
1741 | }
1742 | }
1743 | }
1744 |
1745 | static void
1746 | combine_out_ca (pixman_implementation_t *imp,
1747 | pixman_op_t op,
1748 | uint64_t * dest,
1749 | const uint64_t * src,
1750 | const uint64_t * mask,
1751 | int width)
1752 | {
1753 | int i;
1754 |
1755 | for (i = 0; i < width; ++i)
1756 | {
1757 | uint64_t d = *(dest + i);
1758 | uint32_t a = ~d >> A_SHIFT;
1759 | uint64_t s = 0;
1760 |
1761 | if (a)
1762 | {
1763 | uint64_t m = *(mask + i);
1764 |
1765 | s = *(src + i);
1766 | combine_mask_value_ca (&s, &m);
1767 |
1768 | if (a != MASK)
1769 | UN16x4_MUL_UN16 (s, a);
1770 | }
1771 |
1772 | *(dest + i) = s;
1773 | }
1774 | }
1775 |
1776 | static void
1777 | combine_out_reverse_ca (pixman_implementation_t *imp,
1778 | pixman_op_t op,
1779 | uint64_t * dest,
1780 | const uint64_t * src,
1781 | const uint64_t * mask,
1782 | int width)
1783 | {
1784 | int i;
1785 |
1786 | for (i = 0; i < width; ++i)
1787 | {
1788 | uint64_t s = *(src + i);
1789 | uint64_t m = *(mask + i);
1790 | uint64_t a;
1791 |
1792 | combine_mask_alpha_ca (&s, &m);
1793 |
1794 | a = ~m;
1795 | if (a != ~0)
1796 | {
1797 | uint64_t d = 0;
1798 |
1799 | if (a)
1800 | {
1801 | d = *(dest + i);
1802 | UN16x4_MUL_UN16x4 (d, a);
1803 | }
1804 |
1805 | *(dest + i) = d;
1806 | }
1807 | }
1808 | }
1809 |
1810 | static void
1811 | combine_atop_ca (pixman_implementation_t *imp,
1812 | pixman_op_t op,
1813 | uint64_t * dest,
1814 | const uint64_t * src,
1815 | const uint64_t * mask,
1816 | int width)
1817 | {
1818 | int i;
1819 |
1820 | for (i = 0; i < width; ++i)
1821 | {
1822 | uint64_t d = *(dest + i);
1823 | uint64_t s = *(src + i);
1824 | uint64_t m = *(mask + i);
1825 | uint64_t ad;
1826 | uint32_t as = d >> A_SHIFT;
1827 |
1828 | combine_mask_ca (&s, &m);
1829 |
1830 | ad = ~m;
1831 |
1832 | UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (d, ad, s, as);
1833 |
1834 | *(dest + i) = d;
1835 | }
1836 | }
1837 |
1838 | static void
1839 | combine_atop_reverse_ca (pixman_implementation_t *imp,
1840 | pixman_op_t op,
1841 | uint64_t * dest,
1842 | const uint64_t * src,
1843 | const uint64_t * mask,
1844 | int width)
1845 | {
1846 | int i;
1847 |
1848 | for (i = 0; i < width; ++i)
1849 | {
1850 | uint64_t d = *(dest + i);
1851 | uint64_t s = *(src + i);
1852 | uint64_t m = *(mask + i);
1853 | uint64_t ad;
1854 | uint32_t as = ~d >> A_SHIFT;
1855 |
1856 | combine_mask_ca (&s, &m);
1857 |
1858 | ad = m;
1859 |
1860 | UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (d, ad, s, as);
1861 |
1862 | *(dest + i) = d;
1863 | }
1864 | }
1865 |
1866 | static void
1867 | combine_xor_ca (pixman_implementation_t *imp,
1868 | pixman_op_t op,
1869 | uint64_t * dest,
1870 | const uint64_t * src,
1871 | const uint64_t * mask,
1872 | int width)
1873 | {
1874 | int i;
1875 |
1876 | for (i = 0; i < width; ++i)
1877 | {
1878 | uint64_t d = *(dest + i);
1879 | uint64_t s = *(src + i);
1880 | uint64_t m = *(mask + i);
1881 | uint64_t ad;
1882 | uint32_t as = ~d >> A_SHIFT;
1883 |
1884 | combine_mask_ca (&s, &m);
1885 |
1886 | ad = ~m;
1887 |
1888 | UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (d, ad, s, as);
1889 |
1890 | *(dest + i) = d;
1891 | }
1892 | }
1893 |
1894 | static void
1895 | combine_add_ca (pixman_implementation_t *imp,
1896 | pixman_op_t op,
1897 | uint64_t * dest,
1898 | const uint64_t * src,
1899 | const uint64_t * mask,
1900 | int width)
1901 | {
1902 | int i;
1903 |
1904 | for (i = 0; i < width; ++i)
1905 | {
1906 | uint64_t s = *(src + i);
1907 | uint64_t m = *(mask + i);
1908 | uint64_t d = *(dest + i);
1909 |
1910 | combine_mask_value_ca (&s, &m);
1911 |
1912 | UN16x4_ADD_UN16x4 (d, s);
1913 |
1914 | *(dest + i) = d;
1915 | }
1916 | }
1917 |
1918 | static void
1919 | combine_saturate_ca (pixman_implementation_t *imp,
1920 | pixman_op_t op,
1921 | uint64_t * dest,
1922 | const uint64_t * src,
1923 | const uint64_t * mask,
1924 | int width)
1925 | {
1926 | int i;
1927 |
1928 | for (i = 0; i < width; ++i)
1929 | {
1930 | uint64_t s, d;
1931 | uint32_t sa, sr, sg, sb, da;
1932 | uint32_t t, u, v;
1933 | uint64_t m, n, o, p;
1934 |
1935 | d = *(dest + i);
1936 | s = *(src + i);
1937 | m = *(mask + i);
1938 |
1939 | combine_mask_ca (&s, &m);
1940 |
1941 | sa = (m >> A_SHIFT);
1942 | sr = (m >> R_SHIFT) & MASK;
1943 | sg = (m >> G_SHIFT) & MASK;
1944 | sb = m & MASK;
1945 | da = ~d >> A_SHIFT;
1946 |
1947 | if (sb <= da)
1948 | m = ADD (s, d, 0, t);
1949 | else
1950 | m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v);
1951 |
1952 | if (sg <= da)
1953 | n = ADD (s, d, G_SHIFT, t);
1954 | else
1955 | n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v);
1956 |
1957 | if (sr <= da)
1958 | o = ADD (s, d, R_SHIFT, t);
1959 | else
1960 | o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v);
1961 |
1962 | if (sa <= da)
1963 | p = ADD (s, d, A_SHIFT, t);
1964 | else
1965 | p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v);
1966 |
1967 | *(dest + i) = m | n | o | p;
1968 | }
1969 | }
1970 |
1971 | static void
1972 | combine_disjoint_general_ca (uint64_t * dest,
1973 | const uint64_t *src,
1974 | const uint64_t *mask,
1975 | int width,
1976 | uint16_t combine)
1977 | {
1978 | int i;
1979 |
1980 | for (i = 0; i < width; ++i)
1981 | {
1982 | uint64_t s, d;
1983 | uint64_t m, n, o, p;
1984 | uint64_t Fa, Fb;
1985 | uint32_t t, u, v;
1986 | uint64_t sa;
1987 | uint16_t da;
1988 |
1989 | s = *(src + i);
1990 | m = *(mask + i);
1991 | d = *(dest + i);
1992 | da = d >> A_SHIFT;
1993 |
1994 | combine_mask_ca (&s, &m);
1995 |
1996 | sa = m;
1997 |
1998 | switch (combine & COMBINE_A)
1999 | {
2000 | default:
2001 | Fa = 0;
2002 | break;
2003 |
2004 | case COMBINE_A_OUT:
2005 | m = (uint64_t)combine_disjoint_out_part ((uint16_t) (sa >> 0), da);
2006 | n = (uint64_t)combine_disjoint_out_part ((uint16_t) (sa >> G_SHIFT), da) << G_SHIFT;
2007 | o = (uint64_t)combine_disjoint_out_part ((uint16_t) (sa >> R_SHIFT), da) << R_SHIFT;
2008 | p = (uint64_t)combine_disjoint_out_part ((uint16_t) (sa >> A_SHIFT), da) << A_SHIFT;
2009 | Fa = m | n | o | p;
2010 | break;
2011 |
2012 | case COMBINE_A_IN:
2013 | m = (uint64_t)combine_disjoint_in_part ((uint16_t) (sa >> 0), da);
2014 | n = (uint64_t)combine_disjoint_in_part ((uint16_t) (sa >> G_SHIFT), da) << G_SHIFT;
2015 | o = (uint64_t)combine_disjoint_in_part ((uint16_t) (sa >> R_SHIFT), da) << R_SHIFT;
2016 | p = (uint64_t)combine_disjoint_in_part ((uint16_t) (sa >> A_SHIFT), da) << A_SHIFT;
2017 | Fa = m | n | o | p;
2018 | break;
2019 |
2020 | case COMBINE_A:
2021 | Fa = ~0;
2022 | break;
2023 | }
2024 |
2025 | switch (combine & COMBINE_B)
2026 | {
2027 | default:
2028 | Fb = 0;
2029 | break;
2030 |
2031 | case COMBINE_B_OUT:
2032 | m = (uint64_t)combine_disjoint_out_part (da, (uint16_t) (sa >> 0));
2033 | n = (uint64_t)combine_disjoint_out_part (da, (uint16_t) (sa >> G_SHIFT)) << G_SHIFT;
2034 | o = (uint64_t)combine_disjoint_out_part (da, (uint16_t) (sa >> R_SHIFT)) << R_SHIFT;
2035 | p = (uint64_t)combine_disjoint_out_part (da, (uint16_t) (sa >> A_SHIFT)) << A_SHIFT;
2036 | Fb = m | n | o | p;
2037 | break;
2038 |
2039 | case COMBINE_B_IN:
2040 | m = (uint64_t)combine_disjoint_in_part (da, (uint16_t) (sa >> 0));
2041 | n = (uint64_t)combine_disjoint_in_part (da, (uint16_t) (sa >> G_SHIFT)) << G_SHIFT;
2042 | o = (uint64_t)combine_disjoint_in_part (da, (uint16_t) (sa >> R_SHIFT)) << R_SHIFT;
2043 | p = (uint64_t)combine_disjoint_in_part (da, (uint16_t) (sa >> A_SHIFT)) << A_SHIFT;
2044 | Fb = m | n | o | p;
2045 | break;
2046 |
2047 | case COMBINE_B:
2048 | Fb = ~0;
2049 | break;
2050 | }
2051 | m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
2052 | n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
2053 | o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
2054 | p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
2055 |
2056 | s = m | n | o | p;
2057 |
2058 | *(dest + i) = s;
2059 | }
2060 | }
2061 |
2062 | static void
2063 | combine_disjoint_over_ca (pixman_implementation_t *imp,
2064 | pixman_op_t op,
2065 | uint64_t * dest,
2066 | const uint64_t * src,
2067 | const uint64_t * mask,
2068 | int width)
2069 | {
2070 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
2071 | }
2072 |
2073 | static void
2074 | combine_disjoint_in_ca (pixman_implementation_t *imp,
2075 | pixman_op_t op,
2076 | uint64_t * dest,
2077 | const uint64_t * src,
2078 | const uint64_t * mask,
2079 | int width)
2080 | {
2081 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
2082 | }
2083 |
2084 | static void
2085 | combine_disjoint_in_reverse_ca (pixman_implementation_t *imp,
2086 | pixman_op_t op,
2087 | uint64_t * dest,
2088 | const uint64_t * src,
2089 | const uint64_t * mask,
2090 | int width)
2091 | {
2092 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
2093 | }
2094 |
2095 | static void
2096 | combine_disjoint_out_ca (pixman_implementation_t *imp,
2097 | pixman_op_t op,
2098 | uint64_t * dest,
2099 | const uint64_t * src,
2100 | const uint64_t * mask,
2101 | int width)
2102 | {
2103 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
2104 | }
2105 |
2106 | static void
2107 | combine_disjoint_out_reverse_ca (pixman_implementation_t *imp,
2108 | pixman_op_t op,
2109 | uint64_t * dest,
2110 | const uint64_t * src,
2111 | const uint64_t * mask,
2112 | int width)
2113 | {
2114 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
2115 | }
2116 |
2117 | static void
2118 | combine_disjoint_atop_ca (pixman_implementation_t *imp,
2119 | pixman_op_t op,
2120 | uint64_t * dest,
2121 | const uint64_t * src,
2122 | const uint64_t * mask,
2123 | int width)
2124 | {
2125 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
2126 | }
2127 |
2128 | static void
2129 | combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp,
2130 | pixman_op_t op,
2131 | uint64_t * dest,
2132 | const uint64_t * src,
2133 | const uint64_t * mask,
2134 | int width)
2135 | {
2136 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
2137 | }
2138 |
2139 | static void
2140 | combine_disjoint_xor_ca (pixman_implementation_t *imp,
2141 | pixman_op_t op,
2142 | uint64_t * dest,
2143 | const uint64_t * src,
2144 | const uint64_t * mask,
2145 | int width)
2146 | {
2147 | combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
2148 | }
2149 |
2150 | static void
2151 | combine_conjoint_general_ca (uint64_t * dest,
2152 | const uint64_t *src,
2153 | const uint64_t *mask,
2154 | int width,
2155 | uint16_t combine)
2156 | {
2157 | int i;
2158 |
2159 | for (i = 0; i < width; ++i)
2160 | {
2161 | uint64_t s, d;
2162 | uint64_t m, n, o, p;
2163 | uint64_t Fa, Fb;
2164 | uint32_t t, u, v;
2165 | uint64_t sa;
2166 | uint16_t da;
2167 |
2168 | s = *(src + i);
2169 | m = *(mask + i);
2170 | d = *(dest + i);
2171 | da = d >> A_SHIFT;
2172 |
2173 | combine_mask_ca (&s, &m);
2174 |
2175 | sa = m;
2176 |
2177 | switch (combine & COMBINE_A)
2178 | {
2179 | default:
2180 | Fa = 0;
2181 | break;
2182 |
2183 | case COMBINE_A_OUT:
2184 | m = (uint64_t)combine_conjoint_out_part ((uint16_t) (sa >> 0), da);
2185 | n = (uint64_t)combine_conjoint_out_part ((uint16_t) (sa >> G_SHIFT), da) << G_SHIFT;
2186 | o = (uint64_t)combine_conjoint_out_part ((uint16_t) (sa >> R_SHIFT), da) << R_SHIFT;
2187 | p = (uint64_t)combine_conjoint_out_part ((uint16_t) (sa >> A_SHIFT), da) << A_SHIFT;
2188 | Fa = m | n | o | p;
2189 | break;
2190 |
2191 | case COMBINE_A_IN:
2192 | m = (uint64_t)combine_conjoint_in_part ((uint16_t) (sa >> 0), da);
2193 | n = (uint64_t)combine_conjoint_in_part ((uint16_t) (sa >> G_SHIFT), da) << G_SHIFT;
2194 | o = (uint64_t)combine_conjoint_in_part ((uint16_t) (sa >> R_SHIFT), da) << R_SHIFT;
2195 | p = (uint64_t)combine_conjoint_in_part ((uint16_t) (sa >> A_SHIFT), da) << A_SHIFT;
2196 | Fa = m | n | o | p;
2197 | break;
2198 |
2199 | case COMBINE_A:
2200 | Fa = ~0;
2201 | break;
2202 | }
2203 |
2204 | switch (combine & COMBINE_B)
2205 | {
2206 | default:
2207 | Fb = 0;
2208 | break;
2209 |
2210 | case COMBINE_B_OUT:
2211 | m = (uint64_t)combine_conjoint_out_part (da, (uint16_t) (sa >> 0));
2212 | n = (uint64_t)combine_conjoint_out_part (da, (uint16_t) (sa >> G_SHIFT)) << G_SHIFT;
2213 | o = (uint64_t)combine_conjoint_out_part (da, (uint16_t) (sa >> R_SHIFT)) << R_SHIFT;
2214 | p = (uint64_t)combine_conjoint_out_part (da, (uint16_t) (sa >> A_SHIFT)) << A_SHIFT;
2215 | Fb = m | n | o | p;
2216 | break;
2217 |
2218 | case COMBINE_B_IN:
2219 | m = (uint64_t)combine_conjoint_in_part (da, (uint16_t) (sa >> 0));
2220 | n = (uint64_t)combine_conjoint_in_part (da, (uint16_t) (sa >> G_SHIFT)) << G_SHIFT;
2221 | o = (uint64_t)combine_conjoint_in_part (da, (uint16_t) (sa >> R_SHIFT)) << R_SHIFT;
2222 | p = (uint64_t)combine_conjoint_in_part (da, (uint16_t) (sa >> A_SHIFT)) << A_SHIFT;
2223 | Fb = m | n | o | p;
2224 | break;
2225 |
2226 | case COMBINE_B:
2227 | Fb = ~0;
2228 | break;
2229 | }
2230 | m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v);
2231 | n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v);
2232 | o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v);
2233 | p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v);
2234 |
2235 | s = m | n | o | p;
2236 |
2237 | *(dest + i) = s;
2238 | }
2239 | }
2240 |
2241 | static void
2242 | combine_conjoint_over_ca (pixman_implementation_t *imp,
2243 | pixman_op_t op,
2244 | uint64_t * dest,
2245 | const uint64_t * src,
2246 | const uint64_t * mask,
2247 | int width)
2248 | {
2249 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER);
2250 | }
2251 |
2252 | static void
2253 | combine_conjoint_over_reverse_ca (pixman_implementation_t *imp,
2254 | pixman_op_t op,
2255 | uint64_t * dest,
2256 | const uint64_t * src,
2257 | const uint64_t * mask,
2258 | int width)
2259 | {
2260 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER);
2261 | }
2262 |
2263 | static void
2264 | combine_conjoint_in_ca (pixman_implementation_t *imp,
2265 | pixman_op_t op,
2266 | uint64_t * dest,
2267 | const uint64_t * src,
2268 | const uint64_t * mask,
2269 | int width)
2270 | {
2271 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN);
2272 | }
2273 |
2274 | static void
2275 | combine_conjoint_in_reverse_ca (pixman_implementation_t *imp,
2276 | pixman_op_t op,
2277 | uint64_t * dest,
2278 | const uint64_t * src,
2279 | const uint64_t * mask,
2280 | int width)
2281 | {
2282 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN);
2283 | }
2284 |
2285 | static void
2286 | combine_conjoint_out_ca (pixman_implementation_t *imp,
2287 | pixman_op_t op,
2288 | uint64_t * dest,
2289 | const uint64_t * src,
2290 | const uint64_t * mask,
2291 | int width)
2292 | {
2293 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT);
2294 | }
2295 |
2296 | static void
2297 | combine_conjoint_out_reverse_ca (pixman_implementation_t *imp,
2298 | pixman_op_t op,
2299 | uint64_t * dest,
2300 | const uint64_t * src,
2301 | const uint64_t * mask,
2302 | int width)
2303 | {
2304 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT);
2305 | }
2306 |
2307 | static void
2308 | combine_conjoint_atop_ca (pixman_implementation_t *imp,
2309 | pixman_op_t op,
2310 | uint64_t * dest,
2311 | const uint64_t * src,
2312 | const uint64_t * mask,
2313 | int width)
2314 | {
2315 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP);
2316 | }
2317 |
2318 | static void
2319 | combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp,
2320 | pixman_op_t op,
2321 | uint64_t * dest,
2322 | const uint64_t * src,
2323 | const uint64_t * mask,
2324 | int width)
2325 | {
2326 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP);
2327 | }
2328 |
2329 | static void
2330 | combine_conjoint_xor_ca (pixman_implementation_t *imp,
2331 | pixman_op_t op,
2332 | uint64_t * dest,
2333 | const uint64_t * src,
2334 | const uint64_t * mask,
2335 | int width)
2336 | {
2337 | combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR);
2338 | }
2339 |
2340 | void
2341 | _pixman_setup_combiner_functions_64 (pixman_implementation_t *imp)
2342 | {
2343 | /* Unified alpha */
2344 | imp->combine_64[PIXMAN_OP_CLEAR] = combine_clear;
2345 | imp->combine_64[PIXMAN_OP_SRC] = combine_src_u;
2346 | imp->combine_64[PIXMAN_OP_DST] = combine_dst;
2347 | imp->combine_64[PIXMAN_OP_OVER] = combine_over_u;
2348 | imp->combine_64[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u;
2349 | imp->combine_64[PIXMAN_OP_IN] = combine_in_u;
2350 | imp->combine_64[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u;
2351 | imp->combine_64[PIXMAN_OP_OUT] = combine_out_u;
2352 | imp->combine_64[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u;
2353 | imp->combine_64[PIXMAN_OP_ATOP] = combine_atop_u;
2354 | imp->combine_64[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u;
2355 | imp->combine_64[PIXMAN_OP_XOR] = combine_xor_u;
2356 | imp->combine_64[PIXMAN_OP_ADD] = combine_add_u;
2357 | imp->combine_64[PIXMAN_OP_SATURATE] = combine_saturate_u;
2358 |
2359 | /* Disjoint, unified */
2360 | imp->combine_64[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear;
2361 | imp->combine_64[PIXMAN_OP_DISJOINT_SRC] = combine_src_u;
2362 | imp->combine_64[PIXMAN_OP_DISJOINT_DST] = combine_dst;
2363 | imp->combine_64[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u;
2364 | imp->combine_64[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u;
2365 | imp->combine_64[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u;
2366 | imp->combine_64[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u;
2367 | imp->combine_64[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u;
2368 | imp->combine_64[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u;
2369 | imp->combine_64[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u;
2370 | imp->combine_64[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u;
2371 | imp->combine_64[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u;
2372 |
2373 | /* Conjoint, unified */
2374 | imp->combine_64[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear;
2375 | imp->combine_64[PIXMAN_OP_CONJOINT_SRC] = combine_src_u;
2376 | imp->combine_64[PIXMAN_OP_CONJOINT_DST] = combine_dst;
2377 | imp->combine_64[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u;
2378 | imp->combine_64[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u;
2379 | imp->combine_64[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u;
2380 | imp->combine_64[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u;
2381 | imp->combine_64[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u;
2382 | imp->combine_64[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u;
2383 | imp->combine_64[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u;
2384 | imp->combine_64[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u;
2385 | imp->combine_64[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u;
2386 |
2387 | imp->combine_64[PIXMAN_OP_MULTIPLY] = combine_multiply_u;
2388 | imp->combine_64[PIXMAN_OP_SCREEN] = combine_screen_u;
2389 | imp->combine_64[PIXMAN_OP_OVERLAY] = combine_overlay_u;
2390 | imp->combine_64[PIXMAN_OP_DARKEN] = combine_darken_u;
2391 | imp->combine_64[PIXMAN_OP_LIGHTEN] = combine_lighten_u;
2392 | imp->combine_64[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u;
2393 | imp->combine_64[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u;
2394 | imp->combine_64[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u;
2395 | imp->combine_64[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u;
2396 | imp->combine_64[PIXMAN_OP_DIFFERENCE] = combine_difference_u;
2397 | imp->combine_64[PIXMAN_OP_EXCLUSION] = combine_exclusion_u;
2398 | imp->combine_64[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u;
2399 | imp->combine_64[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u;
2400 | imp->combine_64[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u;
2401 | imp->combine_64[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u;
2402 |
2403 | /* Component alpha combiners */
2404 | imp->combine_64_ca[PIXMAN_OP_CLEAR] = combine_clear_ca;
2405 | imp->combine_64_ca[PIXMAN_OP_SRC] = combine_src_ca;
2406 | /* dest */
2407 | imp->combine_64_ca[PIXMAN_OP_OVER] = combine_over_ca;
2408 | imp->combine_64_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca;
2409 | imp->combine_64_ca[PIXMAN_OP_IN] = combine_in_ca;
2410 | imp->combine_64_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca;
2411 | imp->combine_64_ca[PIXMAN_OP_OUT] = combine_out_ca;
2412 | imp->combine_64_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca;
2413 | imp->combine_64_ca[PIXMAN_OP_ATOP] = combine_atop_ca;
2414 | imp->combine_64_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca;
2415 | imp->combine_64_ca[PIXMAN_OP_XOR] = combine_xor_ca;
2416 | imp->combine_64_ca[PIXMAN_OP_ADD] = combine_add_ca;
2417 | imp->combine_64_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca;
2418 |
2419 | /* Disjoint CA */
2420 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca;
2421 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca;
2422 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst;
2423 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca;
2424 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca;
2425 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca;
2426 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca;
2427 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca;
2428 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca;
2429 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca;
2430 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca;
2431 | imp->combine_64_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca;
2432 |
2433 | /* Conjoint CA */
2434 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca;
2435 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca;
2436 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst;
2437 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca;
2438 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca;
2439 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca;
2440 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca;
2441 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca;
2442 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca;
2443 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca;
2444 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca;
2445 | imp->combine_64_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca;
2446 |
2447 | imp->combine_64_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca;
2448 | imp->combine_64_ca[PIXMAN_OP_SCREEN] = combine_screen_ca;
2449 | imp->combine_64_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca;
2450 | imp->combine_64_ca[PIXMAN_OP_DARKEN] = combine_darken_ca;
2451 | imp->combine_64_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca;
2452 | imp->combine_64_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca;
2453 | imp->combine_64_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca;
2454 | imp->combine_64_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca;
2455 | imp->combine_64_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca;
2456 | imp->combine_64_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca;
2457 | imp->combine_64_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca;
2458 |
2459 | /* It is not clear that these make sense, so make them noops for now */
2460 | imp->combine_64_ca[PIXMAN_OP_HSL_HUE] = combine_dst;
2461 | imp->combine_64_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst;
2462 | imp->combine_64_ca[PIXMAN_OP_HSL_COLOR] = combine_dst;
2463 | imp->combine_64_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst;
2464 | }
2465 |
2466 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-combine64.h:
--------------------------------------------------------------------------------
1 | /* WARNING: This file is generated by combine.pl from combine.inc.
2 | Please edit one of those files rather than this one. */
3 |
4 | #line 1 "pixman-combine.c.template"
5 |
6 | #define COMPONENT_SIZE 16
7 | #define MASK 0xffffULL
8 | #define ONE_HALF 0x8000ULL
9 |
10 | #define A_SHIFT 16 * 3
11 | #define R_SHIFT 16 * 2
12 | #define G_SHIFT 16
13 | #define A_MASK 0xffff000000000000ULL
14 | #define R_MASK 0xffff00000000ULL
15 | #define G_MASK 0xffff0000ULL
16 |
17 | #define RB_MASK 0xffff0000ffffULL
18 | #define AG_MASK 0xffff0000ffff0000ULL
19 | #define RB_ONE_HALF 0x800000008000ULL
20 | #define RB_MASK_PLUS_ONE 0x10000000010000ULL
21 |
22 | #define ALPHA_16(x) ((x) >> A_SHIFT)
23 | #define RED_16(x) (((x) >> R_SHIFT) & MASK)
24 | #define GREEN_16(x) (((x) >> G_SHIFT) & MASK)
25 | #define BLUE_16(x) ((x) & MASK)
26 |
27 | /*
28 | * Helper macros.
29 | */
30 |
31 | #define MUL_UN16(a, b, t) \
32 | ((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT ))
33 |
34 | #define DIV_UN16(a, b) \
35 | (((uint32_t) (a) * MASK + ((b) / 2)) / (b))
36 |
37 | #define ADD_UN16(x, y, t) \
38 | ((t) = (x) + (y), \
39 | (uint64_t) (uint16_t) ((t) | (0 - ((t) >> G_SHIFT))))
40 |
41 | #define DIV_ONE_UN16(x) \
42 | (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
43 |
44 | /*
45 | * The methods below use some tricks to be able to do two color
46 | * components at the same time.
47 | */
48 |
49 | /*
50 | * x_rb = (x_rb * a) / 255
51 | */
52 | #define UN16_rb_MUL_UN16(x, a, t) \
53 | do \
54 | { \
55 | t = ((x) & RB_MASK) * (a); \
56 | t += RB_ONE_HALF; \
57 | x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
58 | x &= RB_MASK; \
59 | } while (0)
60 |
61 | /*
62 | * x_rb = min (x_rb + y_rb, 255)
63 | */
64 | #define UN16_rb_ADD_UN16_rb(x, y, t) \
65 | do \
66 | { \
67 | t = ((x) + (y)); \
68 | t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
69 | x = (t & RB_MASK); \
70 | } while (0)
71 |
72 | /*
73 | * x_rb = (x_rb * a_rb) / 255
74 | */
75 | #define UN16_rb_MUL_UN16_rb(x, a, t) \
76 | do \
77 | { \
78 | t = (x & MASK) * (a & MASK); \
79 | t |= (x & R_MASK) * ((a >> R_SHIFT) & MASK); \
80 | t += RB_ONE_HALF; \
81 | t = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
82 | x = t & RB_MASK; \
83 | } while (0)
84 |
85 | /*
86 | * x_c = (x_c * a) / 255
87 | */
88 | #define UN16x4_MUL_UN16(x, a) \
89 | do \
90 | { \
91 | uint64_t r1__, r2__, t__; \
92 | \
93 | r1__ = (x); \
94 | UN16_rb_MUL_UN16 (r1__, (a), t__); \
95 | \
96 | r2__ = (x) >> G_SHIFT; \
97 | UN16_rb_MUL_UN16 (r2__, (a), t__); \
98 | \
99 | (x) = r1__ | (r2__ << G_SHIFT); \
100 | } while (0)
101 |
102 | /*
103 | * x_c = (x_c * a) / 255 + y_c
104 | */
105 | #define UN16x4_MUL_UN16_ADD_UN16x4(x, a, y) \
106 | do \
107 | { \
108 | uint64_t r1__, r2__, r3__, t__; \
109 | \
110 | r1__ = (x); \
111 | r2__ = (y) & RB_MASK; \
112 | UN16_rb_MUL_UN16 (r1__, (a), t__); \
113 | UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
114 | \
115 | r2__ = (x) >> G_SHIFT; \
116 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
117 | UN16_rb_MUL_UN16 (r2__, (a), t__); \
118 | UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
119 | \
120 | (x) = r1__ | (r2__ << G_SHIFT); \
121 | } while (0)
122 |
123 | /*
124 | * x_c = (x_c * a + y_c * b) / 255
125 | */
126 | #define UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16(x, a, y, b) \
127 | do \
128 | { \
129 | uint64_t r1__, r2__, r3__, t__; \
130 | \
131 | r1__ = (x); \
132 | r2__ = (y); \
133 | UN16_rb_MUL_UN16 (r1__, (a), t__); \
134 | UN16_rb_MUL_UN16 (r2__, (b), t__); \
135 | UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
136 | \
137 | r2__ = ((x) >> G_SHIFT); \
138 | r3__ = ((y) >> G_SHIFT); \
139 | UN16_rb_MUL_UN16 (r2__, (a), t__); \
140 | UN16_rb_MUL_UN16 (r3__, (b), t__); \
141 | UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
142 | \
143 | (x) = r1__ | (r2__ << G_SHIFT); \
144 | } while (0)
145 |
146 | /*
147 | * x_c = (x_c * a_c) / 255
148 | */
149 | #define UN16x4_MUL_UN16x4(x, a) \
150 | do \
151 | { \
152 | uint64_t r1__, r2__, r3__, t__; \
153 | \
154 | r1__ = (x); \
155 | r2__ = (a); \
156 | UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
157 | \
158 | r2__ = (x) >> G_SHIFT; \
159 | r3__ = (a) >> G_SHIFT; \
160 | UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
161 | \
162 | (x) = r1__ | (r2__ << G_SHIFT); \
163 | } while (0)
164 |
165 | /*
166 | * x_c = (x_c * a_c) / 255 + y_c
167 | */
168 | #define UN16x4_MUL_UN16x4_ADD_UN16x4(x, a, y) \
169 | do \
170 | { \
171 | uint64_t r1__, r2__, r3__, t__; \
172 | \
173 | r1__ = (x); \
174 | r2__ = (a); \
175 | UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
176 | r2__ = (y) & RB_MASK; \
177 | UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
178 | \
179 | r2__ = ((x) >> G_SHIFT); \
180 | r3__ = ((a) >> G_SHIFT); \
181 | UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
182 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
183 | UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
184 | \
185 | (x) = r1__ | (r2__ << G_SHIFT); \
186 | } while (0)
187 |
188 | /*
189 | * x_c = (x_c * a_c + y_c * b) / 255
190 | */
191 | #define UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16(x, a, y, b) \
192 | do \
193 | { \
194 | uint64_t r1__, r2__, r3__, t__; \
195 | \
196 | r1__ = (x); \
197 | r2__ = (a); \
198 | UN16_rb_MUL_UN16_rb (r1__, r2__, t__); \
199 | r2__ = (y); \
200 | UN16_rb_MUL_UN16 (r2__, (b), t__); \
201 | UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
202 | \
203 | r2__ = (x) >> G_SHIFT; \
204 | r3__ = (a) >> G_SHIFT; \
205 | UN16_rb_MUL_UN16_rb (r2__, r3__, t__); \
206 | r3__ = (y) >> G_SHIFT; \
207 | UN16_rb_MUL_UN16 (r3__, (b), t__); \
208 | UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
209 | \
210 | x = r1__ | (r2__ << G_SHIFT); \
211 | } while (0)
212 |
213 | /*
214 | x_c = min(x_c + y_c, 255)
215 | */
216 | #define UN16x4_ADD_UN16x4(x, y) \
217 | do \
218 | { \
219 | uint64_t r1__, r2__, r3__, t__; \
220 | \
221 | r1__ = (x) & RB_MASK; \
222 | r2__ = (y) & RB_MASK; \
223 | UN16_rb_ADD_UN16_rb (r1__, r2__, t__); \
224 | \
225 | r2__ = ((x) >> G_SHIFT) & RB_MASK; \
226 | r3__ = ((y) >> G_SHIFT) & RB_MASK; \
227 | UN16_rb_ADD_UN16_rb (r2__, r3__, t__); \
228 | \
229 | x = r1__ | (r2__ << G_SHIFT); \
230 | } while (0)
231 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-elf-fix.h:
--------------------------------------------------------------------------------
1 | #ifndef __ASSEMBLER__
2 |
3 | /* The pixman-cpu.c file uses the Elf32_auxv_t data structure, but the elf.h
4 | * file that Google provides is missing the definition, so here it is. */
5 | #ifndef PIXMAN_ELF_FIX_H
6 | #define PIXMAN_ELF_FIX_H
7 |
8 | typedef struct {
9 | int a_type;
10 |
11 | union {
12 | long int a_val;
13 | void *a_ptr;
14 | void (*a_fcn)(void);
15 | } a_un;
16 |
17 | } Elf32_auxv_t;
18 |
19 | #endif /* PIXMAN_ELF_FIX_H */
20 |
21 | #endif /* __ASSEMBLER__ */
22 |
--------------------------------------------------------------------------------
/jni/pixman-extra/pixman-version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2008 Red Hat, Inc.
3 | *
4 | * Permission is hereby granted, free of charge, to any person
5 | * obtaining a copy of this software and associated documentation
6 | * files (the "Software"), to deal in the Software without
7 | * restriction, including without limitation the rights to use, copy,
8 | * modify, merge, publish, distribute, sublicense, and/or sell copies
9 | * of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be
13 | * included in all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | *
24 | * Author: Carl D. Worth
25 | */
26 |
27 | #ifndef PIXMAN_VERSION_H__
28 | #define PIXMAN_VERSION_H__
29 |
30 | #ifndef PIXMAN_H__
31 | # error pixman-version.h should only be included by pixman.h
32 | #endif
33 |
34 | #define PIXMAN_VERSION_MAJOR 0
35 | #define PIXMAN_VERSION_MINOR 26
36 | #define PIXMAN_VERSION_MICRO 2
37 |
38 | #define PIXMAN_VERSION_STRING "0.26.2"
39 |
40 | #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \
41 | ((major) * 10000) \
42 | + ((minor) * 100) \
43 | + ((micro) * 1))
44 |
45 | #define PIXMAN_VERSION PIXMAN_VERSION_ENCODE( \
46 | PIXMAN_VERSION_MAJOR, \
47 | PIXMAN_VERSION_MINOR, \
48 | PIXMAN_VERSION_MICRO)
49 |
50 | #endif /* PIXMAN_VERSION_H__ */
51 |
--------------------------------------------------------------------------------
/jni/pixman.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | LIBPIXMAN_SRC= \
4 | pixman/pixman/pixman-access.c \
5 | pixman/pixman/pixman-access-accessors.c \
6 | pixman/pixman/pixman-cpu.c \
7 | pixman/pixman/pixman-gradient-walker.c \
8 | pixman/pixman/pixman-region16.c \
9 | pixman/pixman/pixman-region32.c \
10 | pixman/pixman/pixman-image.c \
11 | pixman/pixman/pixman-implementation.c \
12 | pixman/pixman/pixman-general.c \
13 | pixman/pixman/pixman.c \
14 | pixman/pixman/pixman-fast-path.c \
15 | pixman/pixman/pixman-solid-fill.c \
16 | pixman/pixman/pixman-conical-gradient.c \
17 | pixman/pixman/pixman-linear-gradient.c \
18 | pixman/pixman/pixman-radial-gradient.c \
19 | pixman/pixman/pixman-bits-image.c \
20 | pixman/pixman/pixman-utils.c \
21 | pixman/pixman/pixman-edge.c \
22 | pixman/pixman/pixman-edge-accessors.c \
23 | pixman/pixman/pixman-trap.c \
24 | pixman/pixman/pixman-timer.c \
25 | pixman/pixman/pixman-matrix.c \
26 | pixman/pixman/pixman-noop.c \
27 | pixman/pixman/pixman-arm-simd.c \
28 | pixman/pixman/pixman-arm-simd-asm.S \
29 | pixman/pixman/pixman-arm-neon.c \
30 | pixman/pixman/pixman-arm-neon-asm.S \
31 | pixman/pixman/pixman-arm-neon-asm-bilinear.S \
32 | pixman-extra/pixman-combine32.c \
33 | pixman-extra/pixman-combine64.c \
34 |
35 |
36 |
37 | LIBPIXMAN_CFLAGS:=-D_USE_MATH_DEFINES -DPIXMAN_NO_TLS -DPACKAGE="android-cairo" -DUSE_ARM_NEON -DUSE_ARM_SIMD -include "limits.h"
38 |
39 | include $(CLEAR_VARS)
40 |
41 | LOCAL_MODULE := libpixman
42 | LOCAL_CFLAGS := -O2 $(LIBPIXMAN_CFLAGS) \
43 | -Ijni/pixman/pixman -Ijni/pixman-extra \
44 | -include "pixman-elf-fix.h" \
45 | -Wno-missing-field-initializers
46 | LOCAL_LDFLAGS :=
47 | LOCAL_SRC_FILES := $(LIBPIXMAN_SRC)
48 | LOCAL_STATIC_LIBRARIES := cpufeatures
49 |
50 | include $(BUILD_STATIC_LIBRARY)
51 |
--------------------------------------------------------------------------------