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:
Stephan Aßmus
2005-04-19 18:55:46 +00:00
parent 83d94df950
commit 0999749164
7 changed files with 302 additions and 6 deletions
+35 -3
View File
@@ -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;
+2 -3
View File
@@ -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
View File
@@ -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 ;
+14
View File
@@ -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 ;
+3
View File
@@ -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.
+242
View File
@@ -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;
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
../../../../../distro/x86.R1/beos/system/servers/app_server &
sleep 1s
../../../../../tests/servers/app/copy_bits/CopyBits