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 <danger_mail@list.ru> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
@ -111,3 +111,204 @@
|
||||
|
||||
\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:
|
||||
- \c B_ALPHA_OVERLAY Used for drawing a image with transparency over an opaque
|
||||
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
|
||||
\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
|
||||
*/
|
||||
|
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_CLEAR.png
Normal file
After Width: | Height: | Size: 83 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_DARKEN.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_DESTINATION.png
Normal file
After Width: | Height: | Size: 207 B |
After Width: | Height: | Size: 232 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_DESTINATION_IN.png
Normal file
After Width: | Height: | Size: 187 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_DESTINATION_OUT.png
Normal file
After Width: | Height: | Size: 205 B |
After Width: | Height: | Size: 234 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_DIFFERENCE.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_LIGHTEN.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_SOURCE.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_SOURCE_ATOP.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_SOURCE_IN.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_SOURCE_OUT.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_SOURCE_OVER.png
Normal file
After Width: | Height: | Size: 237 B |
BIN
docs/user/interface/images/B_ALPHA_COMPOSITE_XOR.png
Normal file
After Width: | Height: | Size: 274 B |
@ -298,7 +298,20 @@ enum source_alpha {
|
||||
|
||||
enum alpha_function {
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
|
119
src/servers/app/drawing/Painter/drawing_modes/AggCompOpAdapter.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2020, Kacper Kasper <kacperkasper@gmail.com>
|
||||
* 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;
|
||||
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;
|
||||
|
@ -17,9 +17,12 @@
|
||||
#include <agg_basics.h>
|
||||
#include <agg_color_rgba.h>
|
||||
#include <agg_rendering_buffer.h>
|
||||
#include <agg_pixfmt_rgba.h>
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
#include "AggCompOpAdapter.h"
|
||||
|
||||
class PatternHandler;
|
||||
|
||||
class PixelFormat {
|
||||
@ -28,6 +31,34 @@ class PixelFormat {
|
||||
typedef agg::rendering_buffer agg_buffer;
|
||||
typedef agg::rendering_buffer::row_data row_data;
|
||||
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
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
@ -146,6 +177,17 @@ class PixelFormat {
|
||||
blend_solid_span fBlendSolidVSpan;
|
||||
blend_color_span fBlendColorHSpan;
|
||||
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
|
||||
|
@ -5,6 +5,14 @@
|
||||
#include <stdio.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[] = {
|
||||
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
||||
0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477, 0x00777477,
|
||||
@ -188,6 +196,8 @@ virtual void Draw(BRect updateRect);
|
||||
|
||||
private:
|
||||
BBitmap * fBitmap;
|
||||
BBitmap * fTriangleLeft;
|
||||
BBitmap * fTriangleRight;
|
||||
};
|
||||
|
||||
|
||||
@ -212,7 +222,7 @@ private:
|
||||
DrawingModeApp::DrawingModeApp()
|
||||
: BApplication("application/x.vnd-Haiku.DrawingModeTest")
|
||||
{
|
||||
fWindow = new DrawingModeWindow(BRect(200, 200, 380, 600));
|
||||
fWindow = new DrawingModeWindow(BRect(200, 200, 760, 800));
|
||||
fWindow->Show();
|
||||
}
|
||||
|
||||
@ -234,12 +244,34 @@ DrawingModeView::DrawingModeView(BRect frame)
|
||||
{
|
||||
fBitmap = new BBitmap(BRect(0, 0, 31, 31), B_RGB32);
|
||||
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()
|
||||
{
|
||||
delete fBitmap;
|
||||
delete fTriangleLeft;
|
||||
delete fTriangleRight;
|
||||
}
|
||||
|
||||
|
||||
@ -256,21 +288,45 @@ DrawingModeView::Draw(BRect updateRect)
|
||||
BRect bitmapBounds = fBitmap->Bounds();
|
||||
int32 imageHeight = bitmapBounds.IntegerHeight() + 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 {
|
||||
drawing_mode mode;
|
||||
const char *name;
|
||||
} drawingModes[] = {
|
||||
{ B_OP_COPY, "B_OP_COPY" },
|
||||
{ B_OP_OVER, "B_OP_OVER" },
|
||||
{ B_OP_ERASE, "B_OP_ERASE" },
|
||||
{ B_OP_INVERT, "B_OP_INVERT" },
|
||||
{ B_OP_SELECT, "B_OP_SELECT" },
|
||||
{ B_OP_ADD, "B_OP_ADD" },
|
||||
{ B_OP_SUBTRACT, "B_OP_SUBTRACT" },
|
||||
{ B_OP_BLEND, "B_OP_BLEND" },
|
||||
{ B_OP_MIN, "B_OP_MIN" },
|
||||
{ B_OP_MAX, "B_OP_MAX" }
|
||||
MODE(B_OP_COPY),
|
||||
MODE(B_OP_OVER),
|
||||
MODE(B_OP_ERASE),
|
||||
MODE(B_OP_INVERT),
|
||||
MODE(B_OP_SELECT),
|
||||
MODE(B_OP_ADD),
|
||||
MODE(B_OP_SUBTRACT),
|
||||
MODE(B_OP_BLEND),
|
||||
MODE(B_OP_MIN),
|
||||
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]);
|
||||
@ -312,6 +368,92 @@ DrawingModeView::Draw(BRect updateRect)
|
||||
DrawString(drawingModes[i].name, BPoint(imageWidth * 2,
|
||||
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 :
|
||||
DrawingModes.cpp
|
||||
: [ TargetLibstdc++ ] be
|
||||
: [ TargetLibstdc++ ] be translation
|
||||
;
|
||||
|
||||
if ( $(TARGET_PLATFORM) = libbe_test ) {
|
||||
HaikuInstall install-test-apps : $(HAIKU_APP_TEST_DIR) : DrawingModes
|
||||
: tests!apps ;
|
||||
}
|
||||
|