app_server: Implement more composition modes
* Use agg::comp_op classes to blend pixels. * Subpixel path not implemented. * Needed by WebKit. * Implements #10274. Change-Id: I07b0002196fd0a05fc100bd9f6d703c33cadc85b Reviewed-on: https://review.haiku-os.org/c/haiku/+/2932 Reviewed-by: X512 <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
@@ -111,3 +111,204 @@
|
|||||||
|
|
||||||
\since BeOS R3
|
\since BeOS R3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_SOURCE_OVER
|
||||||
|
|
||||||
|
Draws source over destination preserving transparency. Same as
|
||||||
|
\c B_ALPHA_COMPOSITE.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE_OVER.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_SOURCE_IN
|
||||||
|
|
||||||
|
Draws source only where destination is not transparent.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE_IN.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_SOURCE_OUT
|
||||||
|
|
||||||
|
Draws source only where destination is transparent.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE_OUT.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_SOURCE_ATOP
|
||||||
|
|
||||||
|
Draws source only where destination is not transparent. Colors from both
|
||||||
|
are used in the result.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE_ATOP.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DESTINATION_OVER
|
||||||
|
|
||||||
|
Draws source where destination is transparent, making it appear as if it
|
||||||
|
is drawn behind.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION_OVER.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DESTINATION_IN
|
||||||
|
|
||||||
|
Blends source alpha channel with destination.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION_IN.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DESTINATION_OUT
|
||||||
|
|
||||||
|
Blends inverse of source alpha channel with destination. Result appears as
|
||||||
|
if source was cut out of destination.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION_OUT.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DESTINATION_ATOP
|
||||||
|
|
||||||
|
Draws source only where it is not transparent. Destination is blended on
|
||||||
|
top of it. Colors from both are used in the result.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION_ATOP.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_XOR
|
||||||
|
|
||||||
|
Result is transparent only where both source and destination are transparent
|
||||||
|
or opaque.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_XOR.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_CLEAR
|
||||||
|
|
||||||
|
Erases destination to full transparency, regardless of source alpha value.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_CLEAR.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DIFFERENCE
|
||||||
|
|
||||||
|
Subtracts both inputs in a way that always yields positive result.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DIFFERENCE.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_LIGHTEN
|
||||||
|
|
||||||
|
Retains lighter pixels of both inputs.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_LIGHTEN.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\var alpha_function B_ALPHA_COMPOSITE_DARKEN
|
||||||
|
|
||||||
|
Retains darker pixels of both inputs.
|
||||||
|
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_SOURCE.png "Source"
|
||||||
|
->
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DESTINATION.png "Destination"
|
||||||
|
=
|
||||||
|
\image{inline} html B_ALPHA_COMPOSITE_DARKEN.png "Result"
|
||||||
|
|
||||||
|
\since Haiku R1
|
||||||
|
*/
|
||||||
|
|||||||
@@ -2124,9 +2124,11 @@ SetViewColor(Parent()->ViewColor());
|
|||||||
\param alphaFunc Set to one of the following:
|
\param alphaFunc Set to one of the following:
|
||||||
- \c B_ALPHA_OVERLAY Used for drawing a image with transparency over an opaque
|
- \c B_ALPHA_OVERLAY Used for drawing a image with transparency over an opaque
|
||||||
background.
|
background.
|
||||||
- \c B_ALPHA_COMPOSITE Used to composite two or more transparent images
|
- \c B_ALPHA_COMPOSITE_* Used to composite two or more transparent images
|
||||||
together offscreen to produce a new image drawn using
|
together offscreen to produce a new image drawn using
|
||||||
\c B_ALPHA_OVERLAY mode.
|
\c B_ALPHA_OVERLAY mode.
|
||||||
|
\note Modes other than \c B_ALPHA_OVERLAY and \c B_ALPHA_COMPOSITE work
|
||||||
|
only with \c B_PIXEL_ALPHA.
|
||||||
|
|
||||||
\since BeOS R5
|
\since BeOS R5
|
||||||
*/
|
*/
|
||||||
|
|||||||
|
After Width: | Height: | Size: 83 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 205 B |
|
After Width: | Height: | Size: 234 B |
|
After Width: | Height: | Size: 268 B |
|
After Width: | Height: | Size: 268 B |
|
After Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 237 B |
|
After Width: | Height: | Size: 274 B |
@@ -298,7 +298,20 @@ enum source_alpha {
|
|||||||
|
|
||||||
enum alpha_function {
|
enum alpha_function {
|
||||||
B_ALPHA_OVERLAY = 0,
|
B_ALPHA_OVERLAY = 0,
|
||||||
B_ALPHA_COMPOSITE
|
B_ALPHA_COMPOSITE,
|
||||||
|
B_ALPHA_COMPOSITE_SOURCE_OVER = B_ALPHA_COMPOSITE,
|
||||||
|
B_ALPHA_COMPOSITE_SOURCE_IN,
|
||||||
|
B_ALPHA_COMPOSITE_SOURCE_OUT,
|
||||||
|
B_ALPHA_COMPOSITE_SOURCE_ATOP,
|
||||||
|
B_ALPHA_COMPOSITE_DESTINATION_OVER,
|
||||||
|
B_ALPHA_COMPOSITE_DESTINATION_IN,
|
||||||
|
B_ALPHA_COMPOSITE_DESTINATION_OUT,
|
||||||
|
B_ALPHA_COMPOSITE_DESTINATION_ATOP,
|
||||||
|
B_ALPHA_COMPOSITE_XOR,
|
||||||
|
B_ALPHA_COMPOSITE_CLEAR,
|
||||||
|
B_ALPHA_COMPOSITE_DIFFERENCE,
|
||||||
|
B_ALPHA_COMPOSITE_LIGHTEN,
|
||||||
|
B_ALPHA_COMPOSITE_DARKEN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020, Kacper Kasper <[email protected]>
|
||||||
|
* All rights reserved. Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Copyright 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AGG_COMP_OP_ADAPTER_H
|
||||||
|
#define AGG_COMP_OP_ADAPTER_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <agg_pixfmt_rgba.h>
|
||||||
|
|
||||||
|
#include "PatternHandler.h"
|
||||||
|
|
||||||
|
|
||||||
|
template<typename CompOp, typename RenBuf>
|
||||||
|
struct AggCompOpAdapter {
|
||||||
|
typedef typename CompOp::color_type color_type;
|
||||||
|
typedef typename CompOp::color_type::value_type value_type;
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_pixel(int x, int y,
|
||||||
|
const color_type& c,
|
||||||
|
uint8 cover, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
value_type* p = buffer->row_ptr(y) + x * sizeof(color_type);
|
||||||
|
rgb_color color = pattern->ColorAt(x, y);
|
||||||
|
CompOp::blend_pix(p,
|
||||||
|
color.red, color.green, color.blue, color.alpha, cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_hline(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
uint8 cover, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
value_type* p = buffer->row_ptr(y) + x * sizeof(color_type);
|
||||||
|
do {
|
||||||
|
rgb_color color = pattern->ColorAt(x, y);
|
||||||
|
CompOp::blend_pix(p,
|
||||||
|
color.red, color.green, color.blue, color.alpha, cover);
|
||||||
|
x++;
|
||||||
|
p += sizeof(color_type) / sizeof(value_type);
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_solid_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const uint8* covers, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
value_type* p = buffer->row_ptr(y) + x * sizeof(color_type);
|
||||||
|
do {
|
||||||
|
rgb_color color = pattern->ColorAt(x, y);
|
||||||
|
CompOp::blend_pix(p,
|
||||||
|
color.red, color.green, color.blue, color.alpha, *covers);
|
||||||
|
covers++;
|
||||||
|
p += sizeof(color_type) / sizeof(value_type);
|
||||||
|
x++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_solid_hspan_subpix(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const uint8* covers, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"B_ALPHA_COMPOSITE_* subpixel drawing not implemented\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_solid_vspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type& c,
|
||||||
|
const uint8* covers, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
value_type* p = buffer->row_ptr(y) + x * sizeof(color_type);
|
||||||
|
do {
|
||||||
|
rgb_color color = pattern->ColorAt(x, y);
|
||||||
|
CompOp::blend_pix(p,
|
||||||
|
color.red, color.green, color.blue, color.alpha, *covers);
|
||||||
|
covers++;
|
||||||
|
p += buffer->stride();
|
||||||
|
y++;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blend_color_hspan(int x, int y,
|
||||||
|
unsigned len,
|
||||||
|
const color_type* colors,
|
||||||
|
const uint8* covers,
|
||||||
|
uint8 cover, RenBuf* buffer,
|
||||||
|
const PatternHandler* pattern)
|
||||||
|
{
|
||||||
|
value_type* p = buffer->row_ptr(y) + x * sizeof(color_type);
|
||||||
|
do {
|
||||||
|
CompOp::blend_pix(p,
|
||||||
|
colors->r, colors->g, colors->b, colors->a,
|
||||||
|
covers ? *covers++ : cover);
|
||||||
|
p += sizeof(color_type) / sizeof(value_type);
|
||||||
|
++colors;
|
||||||
|
} while(--len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // AGG_COMP_OP_ADAPTER_H
|
||||||
@@ -328,6 +328,30 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
|
|||||||
fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
|
fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
|
||||||
fBlendColorHSpan = blend_color_hspan_alpha_pc;
|
fBlendColorHSpan = blend_color_hspan_alpha_pc;
|
||||||
}
|
}
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_SOURCE_IN) {
|
||||||
|
SetAggCompOpAdapter<alpha_src_in>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_SOURCE_OUT) {
|
||||||
|
SetAggCompOpAdapter<alpha_src_out>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_SOURCE_ATOP) {
|
||||||
|
SetAggCompOpAdapter<alpha_src_atop>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DESTINATION_OVER) {
|
||||||
|
SetAggCompOpAdapter<alpha_dst_over>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DESTINATION_IN) {
|
||||||
|
SetAggCompOpAdapter<alpha_dst_in>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DESTINATION_OUT) {
|
||||||
|
SetAggCompOpAdapter<alpha_dst_out>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DESTINATION_ATOP) {
|
||||||
|
SetAggCompOpAdapter<alpha_dst_atop>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_XOR) {
|
||||||
|
SetAggCompOpAdapter<alpha_xor>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_CLEAR) {
|
||||||
|
SetAggCompOpAdapter<alpha_clear>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DIFFERENCE) {
|
||||||
|
SetAggCompOpAdapter<alpha_difference>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_LIGHTEN) {
|
||||||
|
SetAggCompOpAdapter<alpha_lighten>();
|
||||||
|
} else if (alphaFncMode == B_ALPHA_COMPOSITE_DARKEN) {
|
||||||
|
SetAggCompOpAdapter<alpha_darken>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -17,9 +17,12 @@
|
|||||||
#include <agg_basics.h>
|
#include <agg_basics.h>
|
||||||
#include <agg_color_rgba.h>
|
#include <agg_color_rgba.h>
|
||||||
#include <agg_rendering_buffer.h>
|
#include <agg_rendering_buffer.h>
|
||||||
|
#include <agg_pixfmt_rgba.h>
|
||||||
|
|
||||||
#include <GraphicsDefs.h>
|
#include <GraphicsDefs.h>
|
||||||
|
|
||||||
|
#include "AggCompOpAdapter.h"
|
||||||
|
|
||||||
class PatternHandler;
|
class PatternHandler;
|
||||||
|
|
||||||
class PixelFormat {
|
class PixelFormat {
|
||||||
@@ -28,6 +31,34 @@ class PixelFormat {
|
|||||||
typedef agg::rendering_buffer agg_buffer;
|
typedef agg::rendering_buffer agg_buffer;
|
||||||
typedef agg::rendering_buffer::row_data row_data;
|
typedef agg::rendering_buffer::row_data row_data;
|
||||||
typedef agg::order_bgra order_type;
|
typedef agg::order_bgra order_type;
|
||||||
|
|
||||||
|
typedef agg::comp_op_rgba_src_in<color_type, order_type> comp_src_in;
|
||||||
|
typedef agg::comp_op_rgba_src_out<color_type, order_type> comp_src_out;
|
||||||
|
typedef agg::comp_op_rgba_src_atop<color_type, order_type> comp_src_atop;
|
||||||
|
typedef agg::comp_op_rgba_dst_over<color_type, order_type> comp_dst_over;
|
||||||
|
typedef agg::comp_op_rgba_dst_in<color_type, order_type> comp_dst_in;
|
||||||
|
typedef agg::comp_op_rgba_dst_out<color_type, order_type> comp_dst_out;
|
||||||
|
typedef agg::comp_op_rgba_dst_atop<color_type, order_type> comp_dst_atop;
|
||||||
|
typedef agg::comp_op_rgba_xor<color_type, order_type> comp_xor;
|
||||||
|
typedef agg::comp_op_rgba_clear<color_type, order_type> comp_clear;
|
||||||
|
typedef agg::comp_op_rgba_difference<color_type, order_type>
|
||||||
|
comp_difference;
|
||||||
|
typedef agg::comp_op_rgba_lighten<color_type, order_type> comp_lighten;
|
||||||
|
typedef agg::comp_op_rgba_darken<color_type, order_type> comp_darken;
|
||||||
|
|
||||||
|
typedef AggCompOpAdapter<comp_src_in, agg_buffer> alpha_src_in;
|
||||||
|
typedef AggCompOpAdapter<comp_src_out, agg_buffer> alpha_src_out;
|
||||||
|
typedef AggCompOpAdapter<comp_src_atop, agg_buffer> alpha_src_atop;
|
||||||
|
typedef AggCompOpAdapter<comp_dst_over, agg_buffer> alpha_dst_over;
|
||||||
|
typedef AggCompOpAdapter<comp_dst_in, agg_buffer> alpha_dst_in;
|
||||||
|
typedef AggCompOpAdapter<comp_dst_out, agg_buffer> alpha_dst_out;
|
||||||
|
typedef AggCompOpAdapter<comp_dst_atop, agg_buffer> alpha_dst_atop;
|
||||||
|
typedef AggCompOpAdapter<comp_xor, agg_buffer> alpha_xor;
|
||||||
|
typedef AggCompOpAdapter<comp_clear, agg_buffer> alpha_clear;
|
||||||
|
typedef AggCompOpAdapter<comp_difference, agg_buffer> alpha_difference;
|
||||||
|
typedef AggCompOpAdapter<comp_lighten, agg_buffer> alpha_lighten;
|
||||||
|
typedef AggCompOpAdapter<comp_darken, agg_buffer> alpha_darken;
|
||||||
|
|
||||||
enum base_scale_e
|
enum base_scale_e
|
||||||
{
|
{
|
||||||
base_shift = color_type::base_shift,
|
base_shift = color_type::base_shift,
|
||||||
@@ -146,6 +177,17 @@ class PixelFormat {
|
|||||||
blend_solid_span fBlendSolidVSpan;
|
blend_solid_span fBlendSolidVSpan;
|
||||||
blend_color_span fBlendColorHSpan;
|
blend_color_span fBlendColorHSpan;
|
||||||
blend_color_span fBlendColorVSpan;
|
blend_color_span fBlendColorVSpan;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SetAggCompOpAdapter()
|
||||||
|
{
|
||||||
|
fBlendPixel = T::blend_pixel;
|
||||||
|
fBlendHLine = T::blend_hline;
|
||||||
|
fBlendSolidHSpanSubpix = T::blend_solid_hspan_subpix;
|
||||||
|
fBlendSolidHSpan = T::blend_solid_hspan;
|
||||||
|
fBlendSolidVSpan = T::blend_solid_vspan;
|
||||||
|
fBlendColorHSpan = T::blend_color_hspan;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// inlined functions
|
// inlined functions
|
||||||
|
|||||||
@@ -5,6 +5,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//#define DUMP_BLENDING_RESULTS
|
||||||
|
#ifdef DUMP_BLENDING_RESULTS
|
||||||
|
#include <BitmapStream.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <TranslatorRoster.h>
|
||||||
|
#include <String.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32 kBitmapBits[] = {
|
uint32 kBitmapBits[] = {
|
||||||
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
||||||
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
||||||
@@ -188,6 +196,8 @@ virtual void Draw(BRect updateRect);
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BBitmap * fBitmap;
|
BBitmap * fBitmap;
|
||||||
|
BBitmap * fTriangleLeft;
|
||||||
|
BBitmap * fTriangleRight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -212,7 +222,7 @@ private:
|
|||||||
DrawingModeApp::DrawingModeApp()
|
DrawingModeApp::DrawingModeApp()
|
||||||
: BApplication("application/x.vnd-Haiku.DrawingModeTest")
|
: BApplication("application/x.vnd-Haiku.DrawingModeTest")
|
||||||
{
|
{
|
||||||
fWindow = new DrawingModeWindow(BRect(200, 200, 380, 600));
|
fWindow = new DrawingModeWindow(BRect(200, 200, 760, 800));
|
||||||
fWindow->Show();
|
fWindow->Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,12 +244,34 @@ DrawingModeView::DrawingModeView(BRect frame)
|
|||||||
{
|
{
|
||||||
fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGB32);
|
fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGB32);
|
||||||
memcpy(fBitmap->Bits(), kBitmapBits, fBitmap->BitsLength());
|
memcpy(fBitmap->Bits(), kBitmapBits, fBitmap->BitsLength());
|
||||||
|
|
||||||
|
uint32 triangleLeftBits[32 * 32] = { 0 };
|
||||||
|
uint32 triangleRightBits[32 * 32] = { 0 };
|
||||||
|
for(int y = 0; y < 32; ++y) {
|
||||||
|
for(int x = 0; x < 32; ++x) {
|
||||||
|
if(x < 32 - y) {
|
||||||
|
triangleLeftBits[y * 32 + x] = 0xffff0000;
|
||||||
|
}
|
||||||
|
if(x >= y) {
|
||||||
|
triangleRightBits[y * 32 + x] = 0xff0000ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fTriangleLeft = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
|
||||||
|
memcpy(fTriangleLeft->Bits(), triangleLeftBits,
|
||||||
|
fTriangleLeft->BitsLength());
|
||||||
|
fTriangleRight = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
|
||||||
|
memcpy(fTriangleRight->Bits(), triangleRightBits,
|
||||||
|
fTriangleRight->BitsLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DrawingModeView::~DrawingModeView()
|
DrawingModeView::~DrawingModeView()
|
||||||
{
|
{
|
||||||
delete fBitmap;
|
delete fBitmap;
|
||||||
|
delete fTriangleLeft;
|
||||||
|
delete fTriangleRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -256,21 +288,45 @@ DrawingModeView::Draw(BRect updateRect)
|
|||||||
BRect bitmapBounds = fBitmap->Bounds();
|
BRect bitmapBounds = fBitmap->Bounds();
|
||||||
int32 imageHeight = bitmapBounds.IntegerHeight() + 10;
|
int32 imageHeight = bitmapBounds.IntegerHeight() + 10;
|
||||||
int32 imageWidth = bitmapBounds.IntegerWidth() + 10;
|
int32 imageWidth = bitmapBounds.IntegerWidth() + 10;
|
||||||
|
BRect triangleBounds = fTriangleLeft->Bounds();
|
||||||
|
int32 triangleHeight = triangleBounds.IntegerHeight() + 10;
|
||||||
|
int32 triangleWidth = triangleBounds.IntegerWidth() + 10;
|
||||||
|
|
||||||
|
#define MODE(m) { m, #m }
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
drawing_mode mode;
|
drawing_mode mode;
|
||||||
const char *name;
|
const char *name;
|
||||||
} drawingModes[] = {
|
} drawingModes[] = {
|
||||||
{ B_OP_COPY, "B_OP_COPY" },
|
MODE(B_OP_COPY),
|
||||||
{ B_OP_OVER, "B_OP_OVER" },
|
MODE(B_OP_OVER),
|
||||||
{ B_OP_ERASE, "B_OP_ERASE" },
|
MODE(B_OP_ERASE),
|
||||||
{ B_OP_INVERT, "B_OP_INVERT" },
|
MODE(B_OP_INVERT),
|
||||||
{ B_OP_SELECT, "B_OP_SELECT" },
|
MODE(B_OP_SELECT),
|
||||||
{ B_OP_ADD, "B_OP_ADD" },
|
MODE(B_OP_ADD),
|
||||||
{ B_OP_SUBTRACT, "B_OP_SUBTRACT" },
|
MODE(B_OP_SUBTRACT),
|
||||||
{ B_OP_BLEND, "B_OP_BLEND" },
|
MODE(B_OP_BLEND),
|
||||||
{ B_OP_MIN, "B_OP_MIN" },
|
MODE(B_OP_MIN),
|
||||||
{ B_OP_MAX, "B_OP_MAX" }
|
MODE(B_OP_MAX)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
alpha_function mode;
|
||||||
|
const char *name;
|
||||||
|
} blendingModes[] = {
|
||||||
|
MODE(B_ALPHA_COMPOSITE_SOURCE_OVER),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_SOURCE_IN),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_SOURCE_OUT),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_SOURCE_ATOP),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DESTINATION_OVER),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DESTINATION_IN),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DESTINATION_OUT),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DESTINATION_ATOP),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_XOR),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_CLEAR),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DIFFERENCE),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_LIGHTEN),
|
||||||
|
MODE(B_ALPHA_COMPOSITE_DARKEN)
|
||||||
};
|
};
|
||||||
|
|
||||||
int32 modeCount = sizeof(drawingModes) / sizeof(drawingModes[0]);
|
int32 modeCount = sizeof(drawingModes) / sizeof(drawingModes[0]);
|
||||||
@@ -312,6 +368,92 @@ DrawingModeView::Draw(BRect updateRect)
|
|||||||
DrawString(drawingModes[i].name, BPoint(imageWidth * 2,
|
DrawString(drawingModes[i].name, BPoint(imageWidth * 2,
|
||||||
imageHeight * i + 20));
|
imageHeight * i + 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DUMP_BLENDING_RESULTS
|
||||||
|
BTranslatorRoster* roster = BTranslatorRoster::Default();
|
||||||
|
if (roster == NULL)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
translator_id* outId;
|
||||||
|
int32 outCount;
|
||||||
|
translation_format pngFormat;
|
||||||
|
roster->GetAllTranslators(&outId, &outCount);
|
||||||
|
for(int32 i = 0; i < outCount; ++i) {
|
||||||
|
const translation_format* formats;
|
||||||
|
int32 formatCount;
|
||||||
|
roster->GetOutputFormats(outId[i], &formats, &formatCount);
|
||||||
|
for(int32 j = 0; j < formatCount; ++j) {
|
||||||
|
if(strcmp(formats[j].MIME, "image/png") == 0) {
|
||||||
|
pngFormat = formats[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t r = B_OK;
|
||||||
|
{
|
||||||
|
BFile file("DESTINATION.png",
|
||||||
|
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
BBitmapStream stream(fTriangleLeft);
|
||||||
|
r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
|
||||||
|
if(r != B_OK)
|
||||||
|
fprintf(stderr, "Failed to save PNG file for destination\n");
|
||||||
|
stream.DetachBitmap(&fTriangleLeft);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BFile file("SOURCE.png", B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
BBitmapStream stream(fTriangleRight);
|
||||||
|
r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
|
||||||
|
if(r != B_OK)
|
||||||
|
fprintf(stderr, "Failed to save PNG file for source\n");
|
||||||
|
stream.DetachBitmap(&fTriangleRight);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
modeCount = sizeof(blendingModes) / sizeof(blendingModes[0]);
|
||||||
|
const int columnOffset = 180;
|
||||||
|
BView *blitter = new BView(BRect(0, 0, 31, 31),
|
||||||
|
"blitter", B_FOLLOW_ALL, B_WILL_DRAW);
|
||||||
|
BBitmap *resultBitmap = new BBitmap(BRect(0, 0, 31, 31),
|
||||||
|
B_RGBA32, true, false);
|
||||||
|
resultBitmap->AddChild(blitter);
|
||||||
|
for (int32 i = 0; i < modeCount; i++) {
|
||||||
|
resultBitmap->Lock();
|
||||||
|
blitter->SetDrawingMode(B_OP_COPY);
|
||||||
|
blitter->SetHighColor(0, 0, 0, 0);
|
||||||
|
blitter->FillRect(resultBitmap->Bounds());
|
||||||
|
blitter->DrawBitmap(fTriangleLeft, B_ORIGIN);
|
||||||
|
blitter->SetDrawingMode(B_OP_ALPHA);
|
||||||
|
blitter->SetBlendingMode(B_PIXEL_ALPHA, blendingModes[i].mode);
|
||||||
|
blitter->DrawBitmap(fTriangleRight, B_ORIGIN);
|
||||||
|
resultBitmap->Unlock();
|
||||||
|
|
||||||
|
#ifdef DUMP_BLENDING_RESULTS
|
||||||
|
BBitmapStream stream(resultBitmap);
|
||||||
|
BString fileName(blendingModes[i].name);
|
||||||
|
BFile file(fileName.Append(".png"),
|
||||||
|
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
|
||||||
|
r = roster->Translate(&stream, NULL, NULL, &file, pngFormat.type);
|
||||||
|
if(r != B_OK) {
|
||||||
|
fprintf(stderr, "Failed to save PNG file for %s\n",
|
||||||
|
blendingModes[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.DetachBitmap(&resultBitmap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SetDrawingMode(B_OP_ALPHA);
|
||||||
|
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||||
|
DrawBitmap(resultBitmap, BPoint(columnOffset, triangleHeight * i));
|
||||||
|
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
DrawString(blendingModes[i].name, BPoint(columnOffset + triangleWidth,
|
||||||
|
triangleHeight * i + 20));
|
||||||
|
}
|
||||||
|
resultBitmap->Lock();
|
||||||
|
resultBitmap->RemoveChild(blitter);
|
||||||
|
delete resultBitmap;
|
||||||
|
delete blitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,10 @@ UseHeaders [ FDirName os interface ] ;
|
|||||||
|
|
||||||
Application DrawingModes :
|
Application DrawingModes :
|
||||||
DrawingModes.cpp
|
DrawingModes.cpp
|
||||||
: [ TargetLibstdc++ ] be
|
: [ TargetLibstdc++ ] be translation
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if ( $(TARGET_PLATFORM) = libbe_test ) {
|
||||||
|
HaikuInstall install-test-apps : $(HAIKU_APP_TEST_DIR) : DrawingModes
|
||||||
|
: tests!apps ;
|
||||||
|
}
|
||||||
|
|||||||