2006-10-31 00:20:38 +03:00
|
|
|
/*
|
2014-07-15 03:02:44 +04:00
|
|
|
* Copyright 2003-2010 Haiku, Inc. All rights reserved.
|
2006-10-31 00:20:38 +03:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
2014-07-15 03:02:44 +04:00
|
|
|
* Adrian Oanca, adioanca@cotty.iren.ro
|
2006-10-31 00:20:38 +03:00
|
|
|
*/
|
|
|
|
#ifndef SHAPE_PRIVATE_H
|
|
|
|
#define SHAPE_PRIVATE_H
|
|
|
|
|
app_server: add a cache for AlphaMasks
* If the same shape alpha mask is set again and again, we now keep
the rendered masks in a cache. On certain websites, WebKit sets
the same shape for clipping hundreds of times, which uses a lot
of time to render the masks.
* When a shape mask was generated, we put it into AlphaMaskCache.
The constructor for ShapeAlphaMask is made private and a factory
method is used for instantiation instead, which transparently
looks up in the cache whether a suitable mask was already generated
before (so the entire caching is encapsulated inside the AlphaMask
class).
* When taking a mask out of the cache, we still create a new
AlphaMask instance. However, the new instance will share the
mask bitmap with the previously generated instance (aside from
the rendering of their bitmap, AlphaMask instances are pretty
lightweight). Shape masks are only seen as identical when
their shape is the same, the inverse flag, and they have the
same parent mask.
* Cache is limited to a fixed size of currently 8 MiB, using a
simple random replacement scheme. An LRU scheme can be added in
the future if necessary. Counting of bytes for the cache size
includes parent masks of masks in the cache, even if the parent
itself is not cached. A reference counter for "indirect" cache
references keeps track of which masks are not part of the cache,
but still need to be added to the cache byte size.
* For now, only for ShapeAlphaMasks, other mask types can be added
as necessary.
2015-11-13 13:52:41 +03:00
|
|
|
#include <Point.h>
|
|
|
|
#include <Rect.h>
|
|
|
|
#include <Referenceable.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2014-07-15 03:02:44 +04:00
|
|
|
|
Basically, this changeset implements BShape::ArcTo(). In more detail:
* Added BShape::ArcTo() and BShapeIterator::IterateArcTo(), using a previously
unused virtual slot. (Added the symbols for binary compatibility for GCC2
and GCC4.)
* Added operator=(), operator==() and operator!=() to BShape.
* Added BShape::BezierTo() version taking three points, which is sometimes
more convenient.
* Added the four new shape data ops OP_LARGE_ARC_TO_CW, OP_LARGE_ARC_TO_CCW,
OP_SMALL_ARC_TO_CW and OP_SMALL_ARC_TO_CCW. For a single arc, provided the
radius is large enough, there are four possibilities to draw the arc, these
are controlled by the two boolean flags to ArcTo() and mapped to the new
commands accordingly.
* Some style cleanup in Shape.cpp (sorry for mixing it up, but it gets
worse below...)
* Added ShapeTest to src/tests/servers/app.
* Changed the way BShapes are transformed from view to screen space in the
app_server. For arcs, it would be nontrivial to apply a proper transformation,
it's much easier to let AGG take care of it. This affects ServerPicture as
well.
* Wrapped iterating the BShape into try/catch blocks in ShapeIterator. But
I really don't understand the purpose of the class in the first place.
Maybe it can now be dropped, since coordinates don't have to be transformed
in place anymore.
* Refactored copy&paste shape iteration code in Painter. The transformation
to screen space happens there.
* Since RemoteDrawingEngine needed to be adopted anyway, I also updated
it for the new DrawString() with offsets version. But the client still needs
to be adapted.
* Style cleanup in Painter.h
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35905 a95241bf-73f2-0310-859d-f6bbb57e9c96
2010-03-18 19:58:19 +03:00
|
|
|
#define OP_LINETO 0x10000000
|
|
|
|
#define OP_BEZIERTO 0x20000000
|
|
|
|
#define OP_CLOSE 0x40000000
|
|
|
|
#define OP_MOVETO 0x80000000
|
|
|
|
#define OP_LARGE_ARC_TO_CW 0x01000000
|
|
|
|
#define OP_LARGE_ARC_TO_CCW 0x02000000
|
|
|
|
#define OP_SMALL_ARC_TO_CW 0x04000000
|
|
|
|
#define OP_SMALL_ARC_TO_CCW 0x08000000
|
2006-10-31 00:20:38 +03:00
|
|
|
|
|
|
|
|
2018-06-19 05:06:26 +03:00
|
|
|
class shape_data : public BReferenceable {
|
|
|
|
public:
|
2014-07-15 03:02:44 +04:00
|
|
|
uint32* opList;
|
app_server: add a cache for AlphaMasks
* If the same shape alpha mask is set again and again, we now keep
the rendered masks in a cache. On certain websites, WebKit sets
the same shape for clipping hundreds of times, which uses a lot
of time to render the masks.
* When a shape mask was generated, we put it into AlphaMaskCache.
The constructor for ShapeAlphaMask is made private and a factory
method is used for instantiation instead, which transparently
looks up in the cache whether a suitable mask was already generated
before (so the entire caching is encapsulated inside the AlphaMask
class).
* When taking a mask out of the cache, we still create a new
AlphaMask instance. However, the new instance will share the
mask bitmap with the previously generated instance (aside from
the rendering of their bitmap, AlphaMask instances are pretty
lightweight). Shape masks are only seen as identical when
their shape is the same, the inverse flag, and they have the
same parent mask.
* Cache is limited to a fixed size of currently 8 MiB, using a
simple random replacement scheme. An LRU scheme can be added in
the future if necessary. Counting of bytes for the cache size
includes parent masks of masks in the cache, even if the parent
itself is not cached. A reference counter for "indirect" cache
references keeps track of which masks are not part of the cache,
but still need to be added to the cache byte size.
* For now, only for ShapeAlphaMasks, other mask types can be added
as necessary.
2015-11-13 13:52:41 +03:00
|
|
|
BPoint* ptList;
|
2006-10-31 00:20:38 +03:00
|
|
|
int32 opCount;
|
|
|
|
int32 opSize;
|
|
|
|
int32 ptCount;
|
|
|
|
int32 ptSize;
|
2015-11-09 20:09:22 +03:00
|
|
|
|
app_server: add a cache for AlphaMasks
* If the same shape alpha mask is set again and again, we now keep
the rendered masks in a cache. On certain websites, WebKit sets
the same shape for clipping hundreds of times, which uses a lot
of time to render the masks.
* When a shape mask was generated, we put it into AlphaMaskCache.
The constructor for ShapeAlphaMask is made private and a factory
method is used for instantiation instead, which transparently
looks up in the cache whether a suitable mask was already generated
before (so the entire caching is encapsulated inside the AlphaMask
class).
* When taking a mask out of the cache, we still create a new
AlphaMask instance. However, the new instance will share the
mask bitmap with the previously generated instance (aside from
the rendering of their bitmap, AlphaMask instances are pretty
lightweight). Shape masks are only seen as identical when
their shape is the same, the inverse flag, and they have the
same parent mask.
* Cache is limited to a fixed size of currently 8 MiB, using a
simple random replacement scheme. An LRU scheme can be added in
the future if necessary. Counting of bytes for the cache size
includes parent masks of masks in the cache, even if the parent
itself is not cached. A reference counter for "indirect" cache
references keeps track of which masks are not part of the cache,
but still need to be added to the cache byte size.
* For now, only for ShapeAlphaMasks, other mask types can be added
as necessary.
2015-11-13 13:52:41 +03:00
|
|
|
bool fOwnsMemory;
|
|
|
|
|
|
|
|
shape_data()
|
|
|
|
:
|
|
|
|
fOwnsMemory(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~shape_data()
|
|
|
|
{
|
|
|
|
if (fOwnsMemory) {
|
|
|
|
delete[] opList;
|
|
|
|
delete[] ptList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shape_data(const shape_data& other)
|
|
|
|
{
|
|
|
|
opList = new(std::nothrow) uint32[other.opCount];
|
|
|
|
ptList = new(std::nothrow) BPoint[other.ptCount];
|
|
|
|
fOwnsMemory = true;
|
|
|
|
opCount = other.opCount;
|
|
|
|
opSize = other.opSize;
|
|
|
|
ptCount = other.ptCount;
|
|
|
|
ptSize = other.ptSize;
|
2019-05-24 23:10:13 +03:00
|
|
|
memcpy((void*)opList, other.opList, opSize);
|
|
|
|
memcpy((void*)ptList, other.ptList, ptSize);
|
app_server: add a cache for AlphaMasks
* If the same shape alpha mask is set again and again, we now keep
the rendered masks in a cache. On certain websites, WebKit sets
the same shape for clipping hundreds of times, which uses a lot
of time to render the masks.
* When a shape mask was generated, we put it into AlphaMaskCache.
The constructor for ShapeAlphaMask is made private and a factory
method is used for instantiation instead, which transparently
looks up in the cache whether a suitable mask was already generated
before (so the entire caching is encapsulated inside the AlphaMask
class).
* When taking a mask out of the cache, we still create a new
AlphaMask instance. However, the new instance will share the
mask bitmap with the previously generated instance (aside from
the rendering of their bitmap, AlphaMask instances are pretty
lightweight). Shape masks are only seen as identical when
their shape is the same, the inverse flag, and they have the
same parent mask.
* Cache is limited to a fixed size of currently 8 MiB, using a
simple random replacement scheme. An LRU scheme can be added in
the future if necessary. Counting of bytes for the cache size
includes parent masks of masks in the cache, even if the parent
itself is not cached. A reference counter for "indirect" cache
references keeps track of which masks are not part of the cache,
but still need to be added to the cache byte size.
* For now, only for ShapeAlphaMasks, other mask types can be added
as necessary.
2015-11-13 13:52:41 +03:00
|
|
|
}
|
|
|
|
|
2015-11-09 20:09:22 +03:00
|
|
|
BRect DetermineBoundingBox() const
|
|
|
|
{
|
|
|
|
BRect bounds;
|
|
|
|
|
|
|
|
if (ptCount == 0)
|
|
|
|
return bounds;
|
|
|
|
|
|
|
|
// TODO: This implementation doesn't take into account curves at all.
|
|
|
|
bounds.left = ptList[0].x;
|
|
|
|
bounds.top = ptList[0].y;
|
|
|
|
bounds.right = ptList[0].x;
|
|
|
|
bounds.bottom = ptList[0].y;
|
|
|
|
|
|
|
|
for (int32 i = 1; i < ptCount; i++) {
|
|
|
|
if (bounds.left > ptList[i].x)
|
|
|
|
bounds.left = ptList[i].x;
|
|
|
|
|
|
|
|
if (bounds.top > ptList[i].y)
|
|
|
|
bounds.top = ptList[i].y;
|
|
|
|
|
|
|
|
if (bounds.right < ptList[i].x)
|
|
|
|
bounds.right = ptList[i].x;
|
|
|
|
|
|
|
|
if (bounds.bottom < ptList[i].y)
|
|
|
|
bounds.bottom = ptList[i].y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bounds;
|
|
|
|
}
|
2006-10-31 00:20:38 +03:00
|
|
|
};
|
|
|
|
|
2014-07-15 03:02:44 +04:00
|
|
|
|
|
|
|
#endif // SHAPE_PRIVATE_H
|