├── .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 | ![From pure-ndk](https://github.com/anoek/android-cairo/raw/master/examples/pure-ndk/screenshot.png) 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 | --------------------------------------------------------------------------------