Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
4076f993
Commit
4076f993
authored
Jul 25, 2013
by
Maciej Suminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a layer compositor for the Cairo backend.
parent
27113348
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
460 additions
and
152 deletions
+460
-152
CMakeLists.txt
common/CMakeLists.txt
+1
-0
cairo_compositor.cpp
common/gal/cairo/cairo_compositor.cpp
+161
-0
cairo_gal.cpp
common/gal/cairo/cairo_gal.cpp
+165
-138
cairo_compositor.h
include/gal/cairo/cairo_compositor.h
+108
-0
cairo_gal.h
include/gal/cairo/cairo_gal.h
+25
-14
No files found.
common/CMakeLists.txt
View file @
4076f993
...
...
@@ -50,6 +50,7 @@ set(GAL_SRCS
# Cairo GAL
gal/cairo/cairo_gal.cpp
gal/cairo/cairo_compositor.cpp
)
add_library
(
gal STATIC
${
GAL_SRCS
}
)
...
...
common/gal/cairo/cairo_compositor.cpp
0 → 100644
View file @
4076f993
/*i
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http:O//www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file cairo_compositor.cpp
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image (Cairo flavour).
*/
#include <gal/cairo/cairo_compositor.h>
#include <wx/log.h>
using
namespace
KiGfx
;
CAIRO_COMPOSITOR
::
CAIRO_COMPOSITOR
(
cairo_t
**
aMainContext
)
:
m_current
(
0
),
m_currentContext
(
aMainContext
),
m_mainContext
(
*
aMainContext
)
{
// Obtain the transformation matrix used in the main context
cairo_get_matrix
(
m_mainContext
,
&
m_matrix
);
}
CAIRO_COMPOSITOR
::~
CAIRO_COMPOSITOR
()
{
clean
();
}
void
CAIRO_COMPOSITOR
::
Initialize
()
{
// Nothing has to be done
}
void
CAIRO_COMPOSITOR
::
Resize
(
unsigned
int
aWidth
,
unsigned
int
aHeight
)
{
clean
();
m_width
=
aWidth
;
m_height
=
aHeight
;
m_stride
=
cairo_format_stride_for_width
(
CAIRO_FORMAT_ARGB32
,
m_width
);
m_bufferSize
=
m_stride
*
m_height
;
}
unsigned
int
CAIRO_COMPOSITOR
::
GetBuffer
()
{
// Pixel storage
BitmapPtr
bitmap
(
new
unsigned
int
[
m_bufferSize
]
);
// Create the Cairo surface
cairo_surface_t
*
surface
=
cairo_image_surface_create_for_data
(
(
unsigned
char
*
)
bitmap
.
get
(),
CAIRO_FORMAT_ARGB32
,
m_width
,
m_height
,
m_stride
);
cairo_t
*
context
=
cairo_create
(
surface
);
#ifdef __WXDEBUG__
cairo_status_t
status
=
cairo_status
(
context
);
wxASSERT_MSG
(
status
==
CAIRO_STATUS_SUCCESS
,
"Cairo context creation error"
);
#endif
/* __WXDEBUG__ */
// Set default settings for the buffer
cairo_set_antialias
(
context
,
CAIRO_ANTIALIAS_SUBPIXEL
);
cairo_set_line_join
(
context
,
CAIRO_LINE_JOIN_ROUND
);
cairo_set_line_cap
(
context
,
CAIRO_LINE_CAP_ROUND
);
// Use the same transformation matrix as the main context
cairo_set_matrix
(
context
,
&
m_matrix
);
// Store the new buffer
CAIRO_BUFFER
buffer
=
{
context
,
surface
,
bitmap
};
m_buffers
.
push_back
(
buffer
);
return
usedBuffers
();
}
void
CAIRO_COMPOSITOR
::
SetBuffer
(
unsigned
int
aBufferHandle
)
{
if
(
aBufferHandle
<=
usedBuffers
()
)
{
m_current
=
aBufferHandle
-
1
;
*
m_currentContext
=
m_buffers
[
m_current
].
context
;
}
#ifdef __WXDEBUG__
else
wxLogDebug
(
wxT
(
"Tried to use a not existing buffer"
)
);
#endif
}
void
CAIRO_COMPOSITOR
::
ClearBuffer
()
{
// Reset the transformation matrix, so it is possible to composite images using
// screen coordinates instead of world coordinates
cairo_identity_matrix
(
m_buffers
[
m_current
].
context
);
cairo_set_source_rgba
(
m_buffers
[
m_current
].
context
,
0.0
,
0.0
,
0.0
,
0.0
);
cairo_rectangle
(
m_buffers
[
m_current
].
context
,
0.0
,
0.0
,
m_width
,
m_height
);
cairo_fill
(
m_buffers
[
m_current
].
context
);
// Restore the transformation matrix
cairo_set_matrix
(
m_buffers
[
m_current
].
context
,
&
m_matrix
);
}
void
CAIRO_COMPOSITOR
::
DrawBuffer
(
unsigned
int
aBufferHandle
)
{
if
(
aBufferHandle
<=
usedBuffers
()
)
{
// Reset the transformation matrix, so it is possible to composite images using
// screen coordinates instead of world coordinates
cairo_identity_matrix
(
m_mainContext
);
cairo_set_source_surface
(
m_mainContext
,
m_buffers
[
aBufferHandle
-
1
].
surface
,
0.0
,
0.0
);
cairo_paint
(
m_mainContext
);
// Restore the transformation matrix
cairo_set_matrix
(
m_mainContext
,
&
m_matrix
);
}
#ifdef __WXDEBUG__
else
wxLogDebug
(
wxT
(
"Tried to use a not existing buffer"
)
);
#endif
}
void
CAIRO_COMPOSITOR
::
clean
()
{
CAIRO_BUFFERS
::
const_iterator
it
;
for
(
it
=
m_buffers
.
begin
();
it
!=
m_buffers
.
end
();
++
it
)
{
cairo_destroy
(
it
->
context
);
cairo_surface_destroy
(
it
->
surface
);
}
m_buffers
.
clear
();
}
common/gal/cairo/cairo_gal.cpp
View file @
4076f993
...
...
@@ -29,6 +29,7 @@
#include <wx/log.h>
#include <gal/cairo/cairo_gal.h>
#include <gal/cairo/cairo_compositor.h>
#include <gal/definitions.h>
#include <limits>
...
...
@@ -89,13 +90,12 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
CAIRO_GAL
::~
CAIRO_GAL
()
{
deinitSurface
();
deleteBitmaps
();
delete
cursorPixels
;
delete
cursorPixelsSaved
;
ClearCache
();
deleteBitmaps
();
}
...
...
@@ -107,11 +107,10 @@ void CAIRO_GAL::onPaint( wxPaintEvent& aEvent )
void
CAIRO_GAL
::
ResizeScreen
(
int
aWidth
,
int
aHeight
)
{
deleteBitmaps
();
screenSize
=
VECTOR2D
(
aWidth
,
aHeight
);
// Recreate the bitmaps
deleteBitmaps
();
allocateBitmaps
();
SetSize
(
wxSize
(
aWidth
,
aHeight
)
);
...
...
@@ -128,28 +127,19 @@ void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
void
CAIRO_GAL
::
initSurface
()
{
if
(
isInitialized
)
return
;
// The size of the client area needs to be greater than zero
clientRectangle
=
parentWindow
->
GetClientRect
();
if
(
clientRectangle
.
width
==
0
||
clientRectangle
.
height
==
0
)
throw
EXCEPTION_ZERO_CLIENT_RECTANGLE
;
wxASSERT
(
!
isInitialized
);
// Create the Cairo surface
cairoSurface
=
cairo_image_surface_create_for_data
(
(
unsigned
char
*
)
bitmapBuffer
,
CAIRO_FORMAT_RGB24
,
clientRectangle
.
width
,
clientRectangle
.
height
,
stride
);
cairoImage
=
cairo_create
(
cairoSurface
);
surface
=
cairo_image_surface_create_for_data
(
(
unsigned
char
*
)
bitmapBuffer
,
GAL_FORMAT
,
screenSize
.
x
,
screenSize
.
y
,
stride
);
context
=
cairo_create
(
surface
);
#ifdef __WXDEBUG__
cairo_status_t
status
=
cairo_status
(
c
airoImage
);
cairo_status_t
status
=
cairo_status
(
c
ontext
);
wxASSERT_MSG
(
status
==
CAIRO_STATUS_SUCCESS
,
"Cairo context creation error"
);
#endif
/* __WXDEBUG__ */
currentContext
=
context
;
// -----------------------------------------------------------------
cairo_set_antialias
(
cairoImage
,
CAIRO_ANTIALIAS_SUBPIXEL
);
cairo_set_antialias
(
context
,
CAIRO_ANTIALIAS_SUBPIXEL
);
// Clear the screen
ClearScreen
();
...
...
@@ -162,21 +152,20 @@ void CAIRO_GAL::initSurface()
worldScreenMatrix
.
m_data
[
1
][
1
],
worldScreenMatrix
.
m_data
[
0
][
2
],
worldScreenMatrix
.
m_data
[
1
][
2
]
);
cairo_set_matrix
(
c
airoImage
,
&
cairoWorldScreenMatrix
);
cairo_set_matrix
(
c
ontext
,
&
cairoWorldScreenMatrix
);
isSetAttributes
=
false
;
// Start drawing with a new path
cairo_new_path
(
c
airoImage
);
cairo_new_path
(
c
ontext
);
isElementAdded
=
true
;
cairo_set_line_join
(
c
airoImage
,
CAIRO_LINE_JOIN_ROUND
);
cairo_set_line_cap
(
c
airoImage
,
CAIRO_LINE_CAP_ROUND
);
cairo_set_line_join
(
c
ontext
,
CAIRO_LINE_JOIN_ROUND
);
cairo_set_line_cap
(
c
ontext
,
CAIRO_LINE_CAP_ROUND
);
lineWidth
=
0
;
isDeleteSavedPixels
=
true
;
isInitialized
=
true
;
}
...
...
@@ -187,13 +176,25 @@ void CAIRO_GAL::deinitSurface()
return
;
// Destroy Cairo objects
cairo_destroy
(
c
airoImage
);
cairo_surface_destroy
(
cairoS
urface
);
cairo_destroy
(
c
ontext
);
cairo_surface_destroy
(
s
urface
);
isInitialized
=
false
;
}
void
CAIRO_GAL
::
setCompositor
()
{
// Recreate the compositor with the new Cairo context
compositor
.
reset
(
new
CAIRO_COMPOSITOR
(
&
currentContext
)
);
compositor
->
Resize
(
screenSize
.
x
,
screenSize
.
y
);
// Prepare buffers
mainBuffer
=
compositor
->
GetBuffer
();
overlayBuffer
=
compositor
->
GetBuffer
();
}
unsigned
int
CAIRO_GAL
::
getNewGroupNumber
()
{
wxASSERT_MSG
(
groups
.
size
()
<
std
::
numeric_limits
<
unsigned
int
>::
max
(),
...
...
@@ -211,8 +212,10 @@ unsigned int CAIRO_GAL::getNewGroupNumber()
void
CAIRO_GAL
::
BeginDrawing
()
throw
(
int
)
{
initSurface
();
setCompositor
();
cairo_push_group
(
cairoImage
);
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
cairo_push_group
(
currentContext
);
}
...
...
@@ -221,13 +224,18 @@ void CAIRO_GAL::EndDrawing()
// Force remaining objects to be drawn
Flush
();
cairo_pop_group_to_source
(
cairoImage
);
cairo_paint_with_alpha
(
cairoImage
,
fillColor
.
a
);
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
cairo_pop_group_to_source
(
currentContext
);
cairo_paint_with_alpha
(
currentContext
,
fillColor
.
a
);
// Merge buffers on the screen
compositor
->
DrawBuffer
(
mainBuffer
);
compositor
->
DrawBuffer
(
overlayBuffer
);
// This code was taken from the wxCairo example - it's not the most efficient one
// Here is a good place for optimizations
// Now translate the raw
image
data from the format stored
// Now translate the raw
context
data from the format stored
// by cairo into a format understood by wxImage.
unsigned
char
*
wxOutputPtr
=
wxOutput
;
...
...
@@ -282,14 +290,36 @@ void CAIRO_GAL::RestoreScreen()
void
CAIRO_GAL
::
SetTarget
(
RenderTarget
aTarget
)
{
wxASSERT_MSG
(
false
,
wxT
(
"Not implemented yet"
)
);
// If the compositor is not set, that means that there is a recaching process going on
// and we do not need the compositor now
if
(
!
compositor
)
return
;
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
cairo_pop_group_to_source
(
currentContext
);
cairo_paint_with_alpha
(
currentContext
,
fillColor
.
a
);
switch
(
aTarget
)
{
default
:
case
TARGET_CACHED
:
case
TARGET_NONCACHED
:
compositor
->
SetBuffer
(
mainBuffer
);
break
;
case
TARGET_OVERLAY
:
compositor
->
SetBuffer
(
overlayBuffer
);
break
;
}
cairo_push_group
(
currentContext
);
}
void
CAIRO_GAL
::
DrawLine
(
const
VECTOR2D
&
aStartPoint
,
const
VECTOR2D
&
aEndPoint
)
{
cairo_move_to
(
c
airoImage
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
airoImage
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_move_to
(
c
urrentContext
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
urrentContext
,
aEndPoint
.
x
,
aEndPoint
.
y
);
isElementAdded
=
true
;
}
...
...
@@ -299,32 +329,34 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
{
if
(
isFillEnabled
)
{
// Filled tracks mode
SetLineWidth
(
aWidth
);
cairo_move_to
(
c
airoImage
,
(
double
)
aStartPoint
.
x
,
(
double
)
aStartPoint
.
y
);
cairo_line_to
(
c
airoImage
,
(
double
)
aEndPoint
.
x
,
(
double
)
aEndPoint
.
y
);
cairo_move_to
(
c
urrentContext
,
(
double
)
aStartPoint
.
x
,
(
double
)
aStartPoint
.
y
);
cairo_line_to
(
c
urrentContext
,
(
double
)
aEndPoint
.
x
,
(
double
)
aEndPoint
.
y
);
}
else
{
// Outline mode for tracks
VECTOR2D
startEndVector
=
aEndPoint
-
aStartPoint
;
double
lineAngle
=
atan2
(
startEndVector
.
y
,
startEndVector
.
x
);
double
lineLength
=
startEndVector
.
EuclideanNorm
();
cairo_save
(
c
airoImage
);
cairo_save
(
c
urrentContext
);
cairo_translate
(
c
airoImage
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_rotate
(
c
airoImage
,
lineAngle
);
cairo_translate
(
c
urrentContext
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_rotate
(
c
urrentContext
,
lineAngle
);
cairo_arc
(
c
airoImage
,
0.0
,
0.0
,
aWidth
/
2.0
,
M_PI
/
2.0
,
3.0
*
M_PI
/
2.0
);
cairo_arc
(
c
airoImage
,
lineLength
,
0.0
,
aWidth
/
2.0
,
-
M_PI
/
2.0
,
M_PI
/
2.0
);
cairo_arc
(
c
urrentContext
,
0.0
,
0.0
,
aWidth
/
2.0
,
M_PI
/
2.0
,
3.0
*
M_PI
/
2.0
);
cairo_arc
(
c
urrentContext
,
lineLength
,
0.0
,
aWidth
/
2.0
,
-
M_PI
/
2.0
,
M_PI
/
2.0
);
cairo_move_to
(
c
airoImage
,
0.0
,
aWidth
/
2.0
);
cairo_line_to
(
c
airoImage
,
lineLength
,
aWidth
/
2.0
);
cairo_move_to
(
c
urrentContext
,
0.0
,
aWidth
/
2.0
);
cairo_line_to
(
c
urrentContext
,
lineLength
,
aWidth
/
2.0
);
cairo_move_to
(
c
airoImage
,
0.0
,
-
aWidth
/
2.0
);
cairo_line_to
(
c
airoImage
,
lineLength
,
-
aWidth
/
2.0
);
cairo_move_to
(
c
urrentContext
,
0.0
,
-
aWidth
/
2.0
);
cairo_line_to
(
c
urrentContext
,
lineLength
,
-
aWidth
/
2.0
);
cairo_restore
(
c
airoImage
);
cairo_restore
(
c
urrentContext
);
}
isElementAdded
=
true
;
...
...
@@ -334,8 +366,8 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
void
CAIRO_GAL
::
DrawCircle
(
const
VECTOR2D
&
aCenterPoint
,
double
aRadius
)
{
// A circle is drawn using an arc
cairo_new_sub_path
(
c
airoImage
);
cairo_arc
(
c
airoImage
,
aCenterPoint
.
x
,
aCenterPoint
.
y
,
aRadius
,
0.0
,
2
*
M_PI
);
cairo_new_sub_path
(
c
urrentContext
);
cairo_arc
(
c
urrentContext
,
aCenterPoint
.
x
,
aCenterPoint
.
y
,
aRadius
,
0.0
,
2
*
M_PI
);
isElementAdded
=
true
;
}
...
...
@@ -346,8 +378,8 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS
{
SWAP
(
aStartAngle
,
>
,
aEndAngle
);
cairo_new_sub_path
(
c
airoImage
);
cairo_arc
(
c
airoImage
,
aCenterPoint
.
x
,
aCenterPoint
.
y
,
aRadius
,
aStartAngle
,
aEndAngle
);
cairo_new_sub_path
(
c
urrentContext
);
cairo_arc
(
c
urrentContext
,
aCenterPoint
.
x
,
aCenterPoint
.
y
,
aRadius
,
aStartAngle
,
aEndAngle
);
isElementAdded
=
true
;
}
...
...
@@ -355,21 +387,13 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS
void
CAIRO_GAL
::
DrawPolyline
(
std
::
deque
<
VECTOR2D
>&
aPointList
)
{
bool
isFirstPoint
=
true
;
// Iterate over the point list and draw the segments
std
::
deque
<
VECTOR2D
>::
const_iterator
it
;
for
(
it
=
aPointList
.
begin
();
it
!=
aPointList
.
end
();
++
it
)
std
::
deque
<
VECTOR2D
>::
const_iterator
it
=
aPointList
.
begin
();
cairo_move_to
(
currentContext
,
it
->
x
,
it
->
y
);
for
(
++
it
;
it
!=
aPointList
.
end
();
++
it
)
{
if
(
isFirstPoint
)
{
cairo_move_to
(
cairoImage
,
it
->
x
,
it
->
y
);
isFirstPoint
=
false
;
}
else
{
cairo_line_to
(
cairoImage
,
it
->
x
,
it
->
y
);
}
cairo_line_to
(
currentContext
,
it
->
x
,
it
->
y
);
}
isElementAdded
=
true
;
...
...
@@ -378,21 +402,13 @@ void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
void
CAIRO_GAL
::
DrawPolygon
(
const
std
::
deque
<
VECTOR2D
>&
aPointList
)
{
bool
isFirstPoint
=
true
;
// Iterate over the point list and draw the polygon
std
::
deque
<
VECTOR2D
>::
const_iterator
it
;
for
(
it
=
aPointList
.
begin
();
it
!=
aPointList
.
end
();
++
it
)
std
::
deque
<
VECTOR2D
>::
const_iterator
it
=
aPointList
.
begin
();
cairo_move_to
(
currentContext
,
it
->
x
,
it
->
y
);
for
(
++
it
;
it
!=
aPointList
.
end
();
++
it
)
{
if
(
isFirstPoint
)
{
cairo_move_to
(
cairoImage
,
it
->
x
,
it
->
y
);
isFirstPoint
=
false
;
}
else
{
cairo_line_to
(
cairoImage
,
it
->
x
,
it
->
y
);
}
cairo_line_to
(
currentContext
,
it
->
x
,
it
->
y
);
}
isElementAdded
=
true
;
...
...
@@ -406,11 +422,11 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
VECTOR2D
diagonalPointB
(
aStartPoint
.
x
,
aEndPoint
.
y
);
// The path is composed from 4 segments
cairo_move_to
(
c
airoImage
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
airoImage
,
diagonalPointA
.
x
,
diagonalPointA
.
y
);
cairo_line_to
(
c
airoImage
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_line_to
(
c
airoImage
,
diagonalPointB
.
x
,
diagonalPointB
.
y
);
cairo_close_path
(
c
airoImage
);
cairo_move_to
(
c
urrentContext
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
urrentContext
,
diagonalPointA
.
x
,
diagonalPointA
.
y
);
cairo_line_to
(
c
urrentContext
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_line_to
(
c
urrentContext
,
diagonalPointB
.
x
,
diagonalPointB
.
y
);
cairo_close_path
(
c
urrentContext
);
isElementAdded
=
true
;
}
...
...
@@ -419,10 +435,11 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
void
CAIRO_GAL
::
DrawCurve
(
const
VECTOR2D
&
aStartPoint
,
const
VECTOR2D
&
aControlPointA
,
const
VECTOR2D
&
aControlPointB
,
const
VECTOR2D
&
aEndPoint
)
{
cairo_move_to
(
c
airoImage
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_curve_to
(
c
airoImage
,
aControlPointA
.
x
,
aControlPointA
.
y
,
aControlPointB
.
x
,
cairo_move_to
(
c
urrentContext
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_curve_to
(
c
urrentContext
,
aControlPointA
.
x
,
aControlPointA
.
y
,
aControlPointB
.
x
,
aControlPointB
.
y
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_line_to
(
cairoImage
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_line_to
(
currentContext
,
aEndPoint
.
x
,
aEndPoint
.
y
);
isElementAdded
=
true
;
}
...
...
@@ -466,7 +483,6 @@ void CAIRO_GAL::SetIsStroke( bool aIsStrokeEnabled )
void
CAIRO_GAL
::
SetStrokeColor
(
const
COLOR4D
&
aColor
)
{
storePath
();
strokeColor
=
aColor
;
if
(
isGrouping
)
...
...
@@ -506,12 +522,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth )
lineWidth
=
aLineWidth
;
// Make lines appear at least 1 pixel wide, no matter of zoom
double
x
=
1.0
,
y
=
1.0
;
cairo_device_to_user_distance
(
cairoImage
,
&
x
,
&
y
);
double
minWidth
=
std
::
min
(
fabs
(
x
),
fabs
(
y
)
);
cairo_set_line_width
(
cairoImage
,
std
::
max
(
aLineWidth
,
minWidth
)
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
...
...
@@ -519,16 +529,23 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth )
groupElement
.
arguments
[
0
]
=
aLineWidth
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
// Make lines appear at least 1 pixel wide, no matter of zoom
double
x
=
1.0
,
y
=
1.0
;
cairo_device_to_user_distance
(
currentContext
,
&
x
,
&
y
);
double
minWidth
=
std
::
min
(
fabs
(
x
),
fabs
(
y
)
);
cairo_set_line_width
(
currentContext
,
std
::
max
(
aLineWidth
,
minWidth
)
);
}
}
void
CAIRO_GAL
::
ClearScreen
()
{
// Clear screen
cairo_set_source_rgba
(
cairoImage
,
backgroundColor
.
r
,
backgroundColor
.
g
,
backgroundColor
.
b
,
1.0
);
cairo_rectangle
(
cairoImage
,
0.0
,
0.0
,
screenSize
.
x
,
screenSize
.
y
);
cairo_fill
(
cairoImage
);
cairo_set_source_rgb
(
currentContext
,
backgroundColor
.
r
,
backgroundColor
.
g
,
backgroundColor
.
b
);
cairo_rectangle
(
currentContext
,
0.0
,
0.0
,
screenSize
.
x
,
screenSize
.
y
);
cairo_fill
(
currentContext
);
}
...
...
@@ -540,10 +557,10 @@ void CAIRO_GAL::SetLayerDepth( double aLayerDepth )
{
storePath
();
cairo_pop_group_to_source
(
cairoImage
);
cairo_paint_with_alpha
(
cairoImage
,
fillColor
.
a
);
cairo_push_group
(
cairoImage
);
// cairo_pop_group_to_source( currentContext
);
// cairo_paint_with_alpha( currentContext
, fillColor.a );
//
// cairo_push_group( currentContext
);
}
}
...
...
@@ -560,7 +577,7 @@ void CAIRO_GAL::Transform( MATRIX3x3D aTransformation )
aTransformation
.
m_data
[
0
][
2
],
aTransformation
.
m_data
[
1
][
2
]
);
cairo_transform
(
c
airoImage
,
&
cairoTransformation
);
cairo_transform
(
c
urrentContext
,
&
cairoTransformation
);
}
...
...
@@ -568,8 +585,6 @@ void CAIRO_GAL::Rotate( double aAngle )
{
storePath
();
cairo_rotate
(
cairoImage
,
aAngle
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
...
...
@@ -577,6 +592,10 @@ void CAIRO_GAL::Rotate( double aAngle )
groupElement
.
arguments
[
0
]
=
aAngle
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
cairo_rotate
(
currentContext
,
aAngle
);
}
}
...
...
@@ -584,8 +603,6 @@ void CAIRO_GAL::Translate( const VECTOR2D& aTranslation )
{
storePath
();
cairo_translate
(
cairoImage
,
aTranslation
.
x
,
aTranslation
.
y
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
...
...
@@ -594,6 +611,10 @@ void CAIRO_GAL::Translate( const VECTOR2D& aTranslation )
groupElement
.
arguments
[
1
]
=
aTranslation
.
y
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
cairo_translate
(
currentContext
,
aTranslation
.
x
,
aTranslation
.
y
);
}
}
...
...
@@ -601,8 +622,6 @@ void CAIRO_GAL::Scale( const VECTOR2D& aScale )
{
storePath
();
cairo_scale
(
cairoImage
,
aScale
.
x
,
aScale
.
y
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
...
...
@@ -611,6 +630,10 @@ void CAIRO_GAL::Scale( const VECTOR2D& aScale )
groupElement
.
arguments
[
1
]
=
aScale
.
y
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
cairo_scale
(
currentContext
,
aScale
.
x
,
aScale
.
y
);
}
}
...
...
@@ -618,14 +641,16 @@ void CAIRO_GAL::Save()
{
storePath
();
cairo_save
(
cairoImage
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
groupElement
.
command
=
CMD_SAVE
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
cairo_save
(
currentContext
);
}
}
...
...
@@ -633,14 +658,16 @@ void CAIRO_GAL::Restore()
{
storePath
();
cairo_restore
(
cairoImage
);
if
(
isGrouping
)
{
GroupElement
groupElement
;
groupElement
.
command
=
CMD_RESTORE
;
currentGroup
->
push_back
(
groupElement
);
}
else
{
cairo_restore
(
currentContext
);
}
}
...
...
@@ -734,50 +761,50 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber )
{
// Make lines appear at least 1 pixel wide, no matter of zoom
double
x
=
1.0
,
y
=
1.0
;
cairo_device_to_user_distance
(
c
airoImage
,
&
x
,
&
y
);
cairo_device_to_user_distance
(
c
urrentContext
,
&
x
,
&
y
);
double
minWidth
=
std
::
min
(
fabs
(
x
),
fabs
(
y
)
);
cairo_set_line_width
(
c
airoImage
,
std
::
max
(
it
->
arguments
[
0
],
minWidth
)
);
cairo_set_line_width
(
c
urrentContext
,
std
::
max
(
it
->
arguments
[
0
],
minWidth
)
);
}
break
;
case
CMD_STROKE_PATH
:
cairo_set_source_rgb
(
c
airoImage
,
strokeColor
.
r
,
strokeColor
.
g
,
strokeColor
.
b
);
cairo_append_path
(
c
airoImage
,
it
->
cairoPath
);
cairo_stroke
(
c
airoImage
);
cairo_set_source_rgb
(
c
urrentContext
,
strokeColor
.
r
,
strokeColor
.
g
,
strokeColor
.
b
);
cairo_append_path
(
c
urrentContext
,
it
->
cairoPath
);
cairo_stroke
(
c
urrentContext
);
break
;
case
CMD_FILL_PATH
:
cairo_set_source_rgb
(
c
airoImage
,
fillColor
.
r
,
fillColor
.
g
,
fillColor
.
b
);
cairo_append_path
(
c
airoImage
,
it
->
cairoPath
);
cairo_fill
(
c
airoImage
);
cairo_set_source_rgb
(
c
urrentContext
,
fillColor
.
r
,
fillColor
.
g
,
fillColor
.
b
);
cairo_append_path
(
c
urrentContext
,
it
->
cairoPath
);
cairo_fill
(
c
urrentContext
);
break
;
case
CMD_TRANSFORM
:
cairo_matrix_t
matrix
;
cairo_matrix_init
(
&
matrix
,
it
->
arguments
[
0
],
it
->
arguments
[
1
],
it
->
arguments
[
2
],
it
->
arguments
[
3
],
it
->
arguments
[
4
],
it
->
arguments
[
5
]
);
cairo_transform
(
c
airoImage
,
&
matrix
);
cairo_transform
(
c
urrentContext
,
&
matrix
);
break
;
case
CMD_ROTATE
:
cairo_rotate
(
c
airoImage
,
it
->
arguments
[
0
]
);
cairo_rotate
(
c
urrentContext
,
it
->
arguments
[
0
]
);
break
;
case
CMD_TRANSLATE
:
cairo_translate
(
c
airoImage
,
it
->
arguments
[
0
],
it
->
arguments
[
1
]
);
cairo_translate
(
c
urrentContext
,
it
->
arguments
[
0
],
it
->
arguments
[
1
]
);
break
;
case
CMD_SCALE
:
cairo_scale
(
c
airoImage
,
it
->
arguments
[
0
],
it
->
arguments
[
1
]
);
cairo_scale
(
c
urrentContext
,
it
->
arguments
[
0
],
it
->
arguments
[
1
]
);
break
;
case
CMD_SAVE
:
cairo_save
(
c
airoImage
);
cairo_save
(
c
urrentContext
);
break
;
case
CMD_RESTORE
:
cairo_restore
(
c
airoImage
);
cairo_restore
(
c
urrentContext
);
break
;
case
CMD_CALL_GROUP
:
...
...
@@ -851,14 +878,14 @@ void CAIRO_GAL::storePath()
{
if
(
isFillEnabled
)
{
cairo_set_source_rgb
(
c
airoImage
,
fillColor
.
r
,
fillColor
.
g
,
fillColor
.
b
);
cairo_fill_preserve
(
c
airoImage
);
cairo_set_source_rgb
(
c
urrentContext
,
fillColor
.
r
,
fillColor
.
g
,
fillColor
.
b
);
cairo_fill_preserve
(
c
urrentContext
);
}
if
(
isStrokeEnabled
)
{
cairo_set_source_rgb
(
c
airoImage
,
strokeColor
.
r
,
strokeColor
.
g
,
strokeColor
.
b
);
cairo_stroke_preserve
(
c
airoImage
);
cairo_set_source_rgb
(
c
urrentContext
,
strokeColor
.
r
,
strokeColor
.
g
,
strokeColor
.
b
);
cairo_stroke_preserve
(
c
urrentContext
);
}
}
else
...
...
@@ -869,7 +896,7 @@ void CAIRO_GAL::storePath()
if
(
isStrokeEnabled
)
{
GroupElement
groupElement
;
groupElement
.
cairoPath
=
cairo_copy_path
(
c
airoImage
);
groupElement
.
cairoPath
=
cairo_copy_path
(
c
urrentContext
);
groupElement
.
command
=
CMD_STROKE_PATH
;
currentGroup
->
push_back
(
groupElement
);
}
...
...
@@ -877,13 +904,13 @@ void CAIRO_GAL::storePath()
if
(
isFillEnabled
)
{
GroupElement
groupElement
;
groupElement
.
cairoPath
=
cairo_copy_path
(
c
airoImage
);
groupElement
.
cairoPath
=
cairo_copy_path
(
c
urrentContext
);
groupElement
.
command
=
CMD_FILL_PATH
;
currentGroup
->
push_back
(
groupElement
);
}
}
cairo_new_path
(
c
airoImage
);
cairo_new_path
(
c
urrentContext
);
}
}
...
...
@@ -962,17 +989,17 @@ void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition )
void
CAIRO_GAL
::
DrawGridLine
(
const
VECTOR2D
&
aStartPoint
,
const
VECTOR2D
&
aEndPoint
)
{
cairo_move_to
(
c
airoImage
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
airoImage
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_set_source_rgb
a
(
cairoImage
,
gridColor
.
r
,
gridColor
.
g
,
gridColor
.
b
,
gridColor
.
a
);
cairo_stroke
(
c
airoImage
);
cairo_move_to
(
c
urrentContext
,
aStartPoint
.
x
,
aStartPoint
.
y
);
cairo_line_to
(
c
urrentContext
,
aEndPoint
.
x
,
aEndPoint
.
y
);
cairo_set_source_rgb
(
currentContext
,
gridColor
.
r
,
gridColor
.
g
,
gridColor
.
b
);
cairo_stroke
(
c
urrentContext
);
}
void
CAIRO_GAL
::
allocateBitmaps
()
{
// Create buffer, use the system independent Cairo
image
backend
stride
=
cairo_format_stride_for_width
(
CAIRO_FORMAT_RGB24
,
screenSize
.
x
);
// Create buffer, use the system independent Cairo
context
backend
stride
=
cairo_format_stride_for_width
(
GAL_FORMAT
,
screenSize
.
x
);
bufferSize
=
stride
*
screenSize
.
y
;
bitmapBuffer
=
new
unsigned
int
[
bufferSize
];
...
...
include/gal/cairo/cairo_compositor.h
0 → 100644
View file @
4076f993
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file cairo_compositor.h
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image (Cairo flavour).
*/
#ifndef CAIRO_COMPOSITOR_H_
#define CAIRO_COMPOSITOR_H_
#include <gal/compositor.h>
#include <cairo.h>
#include <boost/smart_ptr/shared_array.hpp>
#include <deque>
namespace
KiGfx
{
class
CAIRO_COMPOSITOR
:
public
COMPOSITOR
{
public
:
CAIRO_COMPOSITOR
(
cairo_t
**
aMainContext
);
virtual
~
CAIRO_COMPOSITOR
();
/// @copydoc COMPOSITOR::Initialize()
virtual
void
Initialize
();
/// @copydoc COMPOSITOR::Resize()
virtual
void
Resize
(
unsigned
int
aWidth
,
unsigned
int
aHeight
);
/// @copydoc COMPOSITOR::GetBuffer()
virtual
unsigned
int
GetBuffer
();
/// @copydoc COMPOSITOR::SetBuffer()
virtual
void
SetBuffer
(
unsigned
int
aBufferHandle
);
/// @copydoc COMPOSITOR::ClearBuffer()
virtual
void
ClearBuffer
();
/// @copydoc COMPOSITOR::DrawBuffer()
virtual
void
DrawBuffer
(
unsigned
int
aBufferHandle
);
protected
:
typedef
boost
::
shared_array
<
unsigned
int
>
BitmapPtr
;
typedef
struct
{
cairo_t
*
context
;
///< Main texture handle
cairo_surface_t
*
surface
;
///< Point to which an image from texture is attached
BitmapPtr
bitmap
;
///< Pixel storage
}
CAIRO_BUFFER
;
unsigned
int
m_current
;
///< Currently used buffer handle
typedef
std
::
deque
<
CAIRO_BUFFER
>
CAIRO_BUFFERS
;
/// Pointer to the current context, so it can be changed
cairo_t
**
m_currentContext
;
/// Rendering target used for compositing (the main display)
cairo_t
*
m_mainContext
;
/// Transformation matrix
cairo_matrix_t
m_matrix
;
/// Stores information about initialized buffers
CAIRO_BUFFERS
m_buffers
;
unsigned
int
m_stride
;
///< Stride to use given the desired format and width
unsigned
int
m_bufferSize
;
///< Amount of memory needed to store a buffer
/**
* Function clean()
* performs freeing of resources.
*/
void
clean
();
/// Returns number of currently used buffers
unsigned
int
usedBuffers
()
{
return
m_buffers
.
size
();
}
};
}
// namespace KiGfx
#endif
/* COMPOSITOR_H_ */
include/gal/cairo/cairo_gal.h
View file @
4076f993
...
...
@@ -33,7 +33,7 @@
#include <cairo.h>
#include <gal/graphics_abstraction_layer.h>
#include <boost/smart_ptr/shared_ptr.hpp>
#if defined(__WXMSW__)
#define SCREEN_DEPTH 24
...
...
@@ -62,6 +62,8 @@
*/
namespace
KiGfx
{
class
CAIRO_COMPOSITOR
;
class
CAIRO_GAL
:
public
GAL
,
public
wxWindow
{
public
:
...
...
@@ -81,7 +83,7 @@ public:
* @param aName is the name of this window for use by wxWindow::FindWindowByName()
*/
CAIRO_GAL
(
wxWindow
*
aParent
,
wxEvtHandler
*
aMouseListener
=
NULL
,
wxEvtHandler
*
aPaintListener
=
NULL
,
const
wxString
&
aName
=
wxT
(
"CairoCanvas"
)
);
wxEvtHandler
*
aPaintListener
=
NULL
,
const
wxString
&
aName
=
wxT
(
"CairoCanvas"
)
);
virtual
~
CAIRO_GAL
();
...
...
@@ -299,11 +301,15 @@ private:
/// Super class definition
typedef
GAL
super
;
// Compositing variables
boost
::
shared_ptr
<
CAIRO_COMPOSITOR
>
compositor
;
///< Object for layers compositing
unsigned
int
mainBuffer
;
///< Handle to the main buffer
unsigned
int
overlayBuffer
;
///< Handle to the overlay buffer
// Variables related to wxWidgets
wxWindow
*
parentWindow
;
///< Parent window
wxEvtHandler
*
mouseListener
;
///< Mouse listener
wxEvtHandler
*
paintListener
;
///< Paint listener
wxRect
clientRectangle
;
///< Area definition of the surface
unsigned
int
bufferSize
;
///< Size of buffers cairoOutput, bitmapBuffers
unsigned
char
*
wxOutput
;
///< wxImage comaptible buffer
...
...
@@ -315,11 +321,6 @@ private:
wxBitmap
*
cursorPixelsSaved
;
///< Saved cursor pixels
int
cursorSize
;
///< Cursor size
// Variables for the grouping function
int
actualGroupIndex
;
///< The index of the actual group
bool
isGrouping
;
///< Is grouping enabled ?
bool
isElementAdded
;
///< Was an graphic element added ?
/// Maximum number of arguments for one command
static
const
int
MAX_CAIRO_ARGUMENTS
=
6
;
...
...
@@ -352,15 +353,19 @@ private:
cairo_path_t
*
cairoPath
;
///< Pointer to a Cairo path
}
GroupElement
;
// Variables for the grouping function
bool
isGrouping
;
///< Is grouping enabled ?
bool
isElementAdded
;
///< Was an graphic element added ?
typedef
std
::
deque
<
GroupElement
>
Group
;
///< A graphic group type definition
std
::
map
<
int
,
Group
>
groups
;
///< List of graphic groups
unsigned
int
groupCounter
;
///< Counter used for generating keys for groups
Group
*
currentGroup
;
///< Currently used group
std
::
map
<
int
,
Group
>
groups
;
///< List of graphic groups
unsigned
int
groupCounter
;
///< Counter used for generating keys for groups
Group
*
currentGroup
;
///< Currently used group
// Variables related to Cairo <-> wxWidgets
cairo_matrix_t
cairoWorldScreenMatrix
;
///< Cairo world to screen transformation matrix
cairo_t
*
cairoImage
;
///< Cairo image
cairo_surface_t
*
cairoSurface
;
///< Cairo surface
cairo_t
*
currentContext
;
///< Currently used Cairo context for drawing
cairo_t
*
context
;
///< Cairo image
cairo_surface_t
*
surface
;
///< Cairo surface
unsigned
int
*
bitmapBuffer
;
///< Storage of the cairo image
unsigned
int
*
bitmapBufferBackup
;
///< Backup storage of the cairo image
int
stride
;
///< Stride value for Cairo
...
...
@@ -400,15 +405,21 @@ private:
/// Prepare Cairo surfaces for drawing
void
initSurface
();
// Destroy Cairo surfaces when are not needed anymore
//
/
Destroy Cairo surfaces when are not needed anymore
void
deinitSurface
();
/// Prepare the compositor
void
setCompositor
();
/**
* @brief Returns a valid key that can be used as a new group number.
*
* @return An unique group number that is not used by any other group.
*/
unsigned
int
getNewGroupNumber
();
/// Format used to store pixels
static
const
cairo_format_t
GAL_FORMAT
=
CAIRO_FORMAT_RGB24
;
};
}
// namespace KiGfx
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment