experimented with BView::CopyBits(), found out how it should work, but didn't do the changes yet for a correct implementation
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12444 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -524,13 +524,45 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link)
|
||||
{
|
||||
BRect src;
|
||||
BRect dest;
|
||||
|
||||
|
||||
link.Read<BRect>(&src);
|
||||
link.Read<BRect>(&dest);
|
||||
|
||||
|
||||
// NOTE: The correct behaviour is this:
|
||||
// * The region that is copied is the
|
||||
// src rectangle, no matter if it fits
|
||||
// into the dest rectangle. It is copied
|
||||
// by the offset dest.LeftTop() - src.LeftTop()
|
||||
// * The dest rectangle is used for invalidation:
|
||||
// Any area in the dest rectangle that could
|
||||
// not be copied from src (because either the
|
||||
// src rectangle was not big enough, or because there
|
||||
// were parts cut off by the current layer clipping),
|
||||
// are triggering BView::Draw() to be called
|
||||
// and for these parts only.
|
||||
// TODO: The DisplayDriver::CopyBits() call needs
|
||||
// to get a BRegion and an offset by which to copy
|
||||
// all the rects in that region. The region is calculated as
|
||||
// * The src rectangle minus the currect clipping of the layer
|
||||
// * minus the part of the region that is outside the layer
|
||||
// when the region is translated by the offset!
|
||||
// Then, an invalidation needs to be triggered for the
|
||||
// following region: the dest rectangle minus the
|
||||
// region we calculated in step one translated by the
|
||||
// offset.
|
||||
// By implementing it this way, we don't mix the update
|
||||
// triggering with the actual graphical operation in
|
||||
// DisplayDriver. I know that normally DisplayDriver takes
|
||||
// care of the clipping, but this is different, because
|
||||
// CopyBits() is the only drawing call that can trigger
|
||||
// invalidation.
|
||||
// TODO: In DisplayDriver, implement the described CopyBits()
|
||||
// version. Also, the current implementation is wrong because it
|
||||
// clips the source rectangle to the dest rectangle.
|
||||
|
||||
src = cl->ConvertToTop(src);
|
||||
dest = cl->ConvertToTop(dest);
|
||||
|
||||
|
||||
cl->fDriver->CopyBits(src, dest, cl->fLayerData);
|
||||
|
||||
break;
|
||||
|
||||
@@ -423,10 +423,9 @@ Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
|
||||
fBaseRenderer->ymax() >= y) {
|
||||
int32 i = max_c(fBaseRenderer->xmin(), x1);
|
||||
int32 end = min_c(fBaseRenderer->xmax(), x2);
|
||||
uint8* handle = dst + i * 4;
|
||||
uint32* handle = (uint32*)(dst + i * 4);
|
||||
for (; i <= end; i++) {
|
||||
*(uint32*)handle = color.data32;
|
||||
handle += 4;
|
||||
*handle++ = color.data32;
|
||||
}
|
||||
}
|
||||
} while (fBaseRenderer->next_clip_box());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
SubDir OBOS_TOP src tests servers app ;
|
||||
|
||||
SubInclude OBOS_TOP src tests servers app copy_bits ;
|
||||
SubInclude OBOS_TOP src tests servers app painter ;
|
||||
SubInclude OBOS_TOP src tests servers app windows ;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
SubDir OBOS_TOP src tests servers app copy_bits ;
|
||||
|
||||
UseHeaders [ FDirName os app ] ;
|
||||
UseHeaders [ FDirName os interface ] ;
|
||||
|
||||
SimpleTest CopyBits :
|
||||
main.cpp
|
||||
# for running natively under R5:
|
||||
# : be ;
|
||||
# for running in the Haiku app_server under R5:
|
||||
: libopenbeos.so ;
|
||||
# for running on Haiku:
|
||||
# : libbe.so ;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
For the test to run properly on BeOS, you need to make links to some Haiku libs in your ~/config/lib folder. The test itself links to libopenbeos.so, app_server additionally links to libappserver.so, libz.so, libpng.so and libfreetype.so.
|
||||
|
||||
The script "run" launches the Haiku app_server and a second later the test app which connects to it.
|
||||
@@ -0,0 +1,242 @@
|
||||
// main.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Message.h"
|
||||
#include "Button.h"
|
||||
#include "View.h"
|
||||
#include "Window.h"
|
||||
|
||||
#define MSG_COPY_BITS 'cbts'
|
||||
|
||||
class TestView : public BView {
|
||||
|
||||
enum {
|
||||
TRACKING_NONE,
|
||||
TRACKING_SOURCE,
|
||||
TRACKING_DEST
|
||||
};
|
||||
|
||||
public:
|
||||
TestView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags)
|
||||
: BView(frame, name, resizeFlags, flags),
|
||||
fTracking(TRACKING_NONE),
|
||||
fCopyBitsJustCalled(false)
|
||||
{
|
||||
fSourceRect.Set(frame.left, frame.top,
|
||||
(frame.left + frame.right) / 2,
|
||||
frame.bottom);
|
||||
fDestRect.Set((frame.left + frame.right) / 2,
|
||||
frame.top,
|
||||
frame.right, frame.bottom);
|
||||
fSourceRect.InsetBy(10.0, 10.0);
|
||||
fDestRect.InsetBy(10.0, 10.0);
|
||||
}
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
|
||||
private:
|
||||
void _TrackMouse(BPoint where);
|
||||
|
||||
BRect fSourceRect;
|
||||
BRect fDestRect;
|
||||
|
||||
uint32 fTracking;
|
||||
|
||||
bool fCopyBitsJustCalled;
|
||||
};
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
TestView::MessageReceived(BMessage* message)
|
||||
{
|
||||
if (message->what == MSG_COPY_BITS) {
|
||||
printf("MSG_COPY_BITS\n");
|
||||
fSourceRect.PrintToStream();
|
||||
fDestRect.PrintToStream();
|
||||
CopyBits(fSourceRect, fDestRect);
|
||||
fCopyBitsJustCalled = true;
|
||||
} else
|
||||
BView::MessageReceived(message);
|
||||
}
|
||||
|
||||
// Draw
|
||||
void
|
||||
TestView::Draw(BRect updateRect)
|
||||
{
|
||||
if (fCopyBitsJustCalled) {
|
||||
printf("TestView::Draw(%.1f, %.1f, %.1f, %.1f) after CopyBits()\n",
|
||||
updateRect.left, updateRect.top, updateRect.right, updateRect.bottom);
|
||||
fCopyBitsJustCalled = false;
|
||||
}
|
||||
|
||||
SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
FillRect(updateRect);
|
||||
|
||||
BRect r(Bounds());
|
||||
|
||||
// draw some pattern with lines
|
||||
float width = r.Width();
|
||||
float height = r.Height();
|
||||
int32 lineCount = 20;
|
||||
for (int32 i = 0; i < lineCount; i++) {
|
||||
SetHighColor(255, (255 / lineCount) * i, 255 - (255 / lineCount) * i);
|
||||
StrokeLine(BPoint(r.left + (width / lineCount) * i, r.top),
|
||||
BPoint(r.left, r.top + (height / lineCount) * i));
|
||||
StrokeLine(BPoint(r.right - (width / lineCount) * i, r.bottom),
|
||||
BPoint(r.right, r.bottom - (height / lineCount) * i));
|
||||
}
|
||||
|
||||
SetHighColor(255, 0, 0, 128);
|
||||
|
||||
const char* message = "Left-Click and drag";
|
||||
width = StringWidth(message);
|
||||
BPoint p(r.left + r.Width() / 2.0 - width / 2.0,
|
||||
r.top + r.Height() / 2.0);
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
message = "to draw source rect!";
|
||||
width = StringWidth(message);
|
||||
p.x = r.left + r.Width() / 2.0 - width / 2.0;
|
||||
p.y += 20;
|
||||
|
||||
DrawString(message, p);
|
||||
|
||||
SetHighColor(0, 255, 0, 255);
|
||||
StrokeRect(fSourceRect);
|
||||
|
||||
SetHighColor(0, 0, 255, 255);
|
||||
StrokeRect(fDestRect);
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
TestView::MouseDown(BPoint where)
|
||||
{
|
||||
BMessage* message = Window()->CurrentMessage();
|
||||
uint32 buttons;
|
||||
if (message && message->FindInt32("buttons", (int32*)&buttons) >= B_OK) {
|
||||
if (buttons & B_PRIMARY_MOUSE_BUTTON) {
|
||||
fTracking = TRACKING_SOURCE;
|
||||
fSourceRect.left = where.x;
|
||||
fSourceRect.top = where.y;
|
||||
}
|
||||
if (buttons & B_SECONDARY_MOUSE_BUTTON) {
|
||||
fTracking = TRACKING_DEST;
|
||||
fDestRect.left = where.x;
|
||||
fDestRect.top = where.y;
|
||||
}
|
||||
Invalidate();
|
||||
_TrackMouse(where);
|
||||
}
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
TestView::MouseUp(BPoint where)
|
||||
{
|
||||
fTracking = TRACKING_NONE;
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
TestView::MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage)
|
||||
{
|
||||
if (fTracking > TRACKING_NONE) {
|
||||
_TrackMouse(where);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
min4(float a, float b, float c, float d)
|
||||
{
|
||||
return min_c(a, min_c(b, min_c(c, d)));
|
||||
}
|
||||
|
||||
float
|
||||
max4(float a, float b, float c, float d)
|
||||
{
|
||||
return max_c(a, max_c(b, max_c(c, d)));
|
||||
}
|
||||
|
||||
// _TrackMouse
|
||||
void
|
||||
TestView::_TrackMouse(BPoint where)
|
||||
{
|
||||
BRect before;
|
||||
BRect after;
|
||||
bool invalidate = false;
|
||||
switch (fTracking) {
|
||||
case TRACKING_SOURCE:
|
||||
before = fSourceRect;
|
||||
fSourceRect.right = where.x;
|
||||
fSourceRect.bottom = where.y;
|
||||
after = fSourceRect;
|
||||
invalidate = true;
|
||||
break;
|
||||
case TRACKING_DEST:
|
||||
before = fDestRect;
|
||||
fDestRect.right = where.x;
|
||||
fDestRect.bottom = where.y;
|
||||
after = fDestRect;
|
||||
invalidate = true;
|
||||
break;
|
||||
}
|
||||
if (invalidate) {
|
||||
BRect dirty(min4(before.left, before.right, after.left, after.right),
|
||||
min4(before.top, before.bottom, after.top, after.bottom),
|
||||
max4(before.left, before.right, after.left, after.right),
|
||||
max4(before.top, before.bottom, after.top, after.bottom));
|
||||
Invalidate(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// show_window
|
||||
void
|
||||
show_window(BRect frame, const char* name)
|
||||
{
|
||||
BWindow* window = new BWindow(frame, name,
|
||||
B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
BView* view = new TestView(window->Bounds(), "test", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW/* | B_FULL_UPDATE_ON_RESIZE*/);
|
||||
|
||||
window->AddChild(view);
|
||||
BRect b(0.0, 0.0, 50.0, 15.0);
|
||||
b.OffsetTo(5.0, view->Bounds().bottom - (b.Height() + 15.0));
|
||||
BButton* control = new BButton(b, "button", "Copy", new BMessage(MSG_COPY_BITS));
|
||||
view->AddChild(control);
|
||||
printf("button frame:\n");
|
||||
control->Frame().PrintToStream();
|
||||
control->SetTarget(view);
|
||||
|
||||
window->Show();
|
||||
}
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
BApplication* app = new BApplication("application/x.vnd-Haiku.CopyBits");
|
||||
|
||||
BRect frame(50.0, 50.0, 300.0, 250.0);
|
||||
show_window(frame, "CopyBits Test");
|
||||
|
||||
app->Run();
|
||||
|
||||
delete app;
|
||||
return 0;
|
||||
}
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
../../../../../distro/x86.R1/beos/system/servers/app_server &
|
||||
sleep 1s
|
||||
../../../../../tests/servers/app/copy_bits/CopyBits
|
||||
Reference in New Issue
Block a user