Initial version of the Painter framework, which should be usable as a drawing backend.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10603 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4b0c008cc5
commit
4569b90da0
73
src/servers/app/server/Painter/BitmapBuffer.cpp
Normal file
73
src/servers/app/server/Painter/BitmapBuffer.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// BitmapBuffer.h
|
||||
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include "BitmapBuffer.h"
|
||||
|
||||
// constructor
|
||||
BitmapBuffer::BitmapBuffer(BBitmap* bitmap)
|
||||
: fBitmap(bitmap)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
BitmapBuffer::~BitmapBuffer()
|
||||
{
|
||||
delete fBitmap;
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
BitmapBuffer::InitCheck() const
|
||||
{
|
||||
status_t ret = B_NO_INIT;
|
||||
if (fBitmap)
|
||||
ret = fBitmap->InitCheck();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ColorSpace
|
||||
color_space
|
||||
BitmapBuffer::ColorSpace() const
|
||||
{
|
||||
if (InitCheck() >= B_OK)
|
||||
return fBitmap->ColorSpace();
|
||||
return B_NO_COLOR_SPACE;
|
||||
}
|
||||
|
||||
// Bits
|
||||
void*
|
||||
BitmapBuffer::Bits() const
|
||||
{
|
||||
if (InitCheck() >= B_OK)
|
||||
return fBitmap->Bits();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// BytesPerRow
|
||||
uint32
|
||||
BitmapBuffer::BytesPerRow() const
|
||||
{
|
||||
if (InitCheck() >= B_OK)
|
||||
return fBitmap->BytesPerRow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Width
|
||||
uint32
|
||||
BitmapBuffer::Width() const
|
||||
{
|
||||
if (InitCheck() >= B_OK)
|
||||
return fBitmap->Bounds().IntegerWidth() + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Height
|
||||
uint32
|
||||
BitmapBuffer::Height() const
|
||||
{
|
||||
if (InitCheck() >= B_OK)
|
||||
return fBitmap->Bounds().IntegerHeight() + 1;
|
||||
return 0;
|
||||
}
|
||||
|
28
src/servers/app/server/Painter/BitmapBuffer.h
Normal file
28
src/servers/app/server/Painter/BitmapBuffer.h
Normal file
@ -0,0 +1,28 @@
|
||||
// BitmapBuffer.h
|
||||
|
||||
#ifndef BITMAP_BUFFER_H
|
||||
#define BITMAP_BUFFER_H
|
||||
|
||||
#include "RenderingBuffer.h"
|
||||
|
||||
class BBitmap;
|
||||
|
||||
class BitmapBuffer : public RenderingBuffer {
|
||||
public:
|
||||
BitmapBuffer(BBitmap* bitmap);
|
||||
virtual ~BitmapBuffer();
|
||||
|
||||
virtual status_t InitCheck() const;
|
||||
|
||||
virtual color_space ColorSpace() const;
|
||||
virtual void* Bits() const;
|
||||
virtual uint32 BytesPerRow() const;
|
||||
virtual uint32 Width() const;
|
||||
virtual uint32 Height() const;
|
||||
|
||||
private:
|
||||
|
||||
BBitmap* fBitmap;
|
||||
};
|
||||
|
||||
#endif // BITMAP_BUFFER_H
|
49
src/servers/app/server/Painter/BitmapView.cpp
Normal file
49
src/servers/app/server/Painter/BitmapView.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// BitmapView.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
|
||||
#include "BitmapView.h"
|
||||
|
||||
// constructor
|
||||
BitmapView::BitmapView(BRect frame, const char* name,
|
||||
BBitmap* bitmap)
|
||||
: BView(frame, name, B_FOLLOW_NONE, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
||||
fBitmap(bitmap)
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_32_BIT);
|
||||
}
|
||||
|
||||
// destructor
|
||||
BitmapView::~BitmapView()
|
||||
{
|
||||
delete fBitmap;
|
||||
}
|
||||
|
||||
// Draw
|
||||
void
|
||||
BitmapView::Draw(BRect updateRect)
|
||||
{
|
||||
if (fBitmap)
|
||||
DrawBitmap(fBitmap, Bounds().LeftTop());
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
BitmapView::MouseDown(BPoint where)
|
||||
{
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
BitmapView::MouseUp(BPoint where)
|
||||
{
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
BitmapView::MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage)
|
||||
{
|
||||
}
|
29
src/servers/app/server/Painter/BitmapView.h
Normal file
29
src/servers/app/server/Painter/BitmapView.h
Normal file
@ -0,0 +1,29 @@
|
||||
// BitmapView.h
|
||||
|
||||
#ifndef BITMAP_VIEW_H
|
||||
#define BITMAP_VIEW_H
|
||||
|
||||
#include <View.h>
|
||||
|
||||
class BBitmap;
|
||||
|
||||
class BitmapView : public BView {
|
||||
public:
|
||||
BitmapView(BRect frame,
|
||||
const char* name,
|
||||
BBitmap* bitmap);
|
||||
virtual ~BitmapView();
|
||||
|
||||
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:
|
||||
BBitmap* fBitmap;
|
||||
};
|
||||
|
||||
|
||||
#endif // BITMAP_VIEW_H
|
943
src/servers/app/server/Painter/Painter.cpp
Normal file
943
src/servers/app/server/Painter/Painter.cpp
Normal file
@ -0,0 +1,943 @@
|
||||
// Painter.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Region.h>
|
||||
|
||||
#include <agg_bezier_arc.h>
|
||||
#include <agg_conv_curve.h>
|
||||
#include <agg_conv_stroke.h>
|
||||
#include <agg_ellipse.h>
|
||||
#include <agg_path_storage.h>
|
||||
#include <agg_rounded_rect.h>
|
||||
#include <agg_span_image_filter_rgba32.h>
|
||||
#include <agg_span_interpolator_linear.h>
|
||||
|
||||
#include "AGGTextRenderer.h"
|
||||
#include "DrawingModeFactory.h"
|
||||
#include "FontManager.h"
|
||||
#include "PatternHandler.h"
|
||||
#include "RenderingBuffer.h"
|
||||
#include "ShapeConverter.h"
|
||||
|
||||
#include "Painter.h"
|
||||
|
||||
int
|
||||
roundf(float v)
|
||||
{
|
||||
if (v >= 0.0)
|
||||
return (int)floorf(v + 0.5);
|
||||
else
|
||||
return (int)floorf(v - 0.5);
|
||||
}
|
||||
|
||||
// constructor
|
||||
Painter::Painter()
|
||||
: fBuffer(NULL),
|
||||
fPixelFormat(NULL),
|
||||
fBaseRenderer(NULL),
|
||||
fOutlineRenderer(NULL),
|
||||
fOutlineRasterizer(NULL),
|
||||
fScanline(NULL),
|
||||
fRasterizer(NULL),
|
||||
fRenderer(NULL),
|
||||
fFontRendererSolid(NULL),
|
||||
fFontRendererBin(NULL),
|
||||
fSubpixelPrecise(false),
|
||||
fScale(1.0),
|
||||
fPenSize(1.0),
|
||||
fOrigin(0.0, 0.0),
|
||||
fClippingRegion(NULL),
|
||||
fDrawingMode(B_OP_COPY),
|
||||
fPenLocation(0.0, 0.0),
|
||||
fPatternHandler(new PatternHandler()),
|
||||
fFont(be_plain_font),
|
||||
fTextRenderer(new AGGTextRenderer())
|
||||
{
|
||||
_UpdateFont();
|
||||
}
|
||||
|
||||
// destructor
|
||||
Painter::~Painter()
|
||||
{
|
||||
_MakeEmpty();
|
||||
|
||||
delete fClippingRegion;
|
||||
delete fPatternHandler;
|
||||
delete fTextRenderer;
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// AttachToBuffer
|
||||
void
|
||||
Painter::AttachToBuffer(RenderingBuffer* buffer)
|
||||
{
|
||||
if (buffer && buffer->InitCheck() >= B_OK) {
|
||||
// clean up previous stuff
|
||||
_MakeEmpty();
|
||||
|
||||
fBuffer = new agg::rendering_buffer();
|
||||
fBuffer->attach((uint8*)buffer->Bits(),
|
||||
buffer->Width(),
|
||||
buffer->Height(),
|
||||
buffer->BytesPerRow());
|
||||
|
||||
fPixelFormat = new pixfmt(*fBuffer, fPatternHandler);
|
||||
fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode));
|
||||
|
||||
fBaseRenderer = new renderer_base(*fPixelFormat);
|
||||
|
||||
// These are the AGG renderes and rasterizes which
|
||||
// will be used for stroking paths
|
||||
rgb_color color = fPatternHandler->HighColor();
|
||||
#if ALIASED_DRAWING
|
||||
fOutlineRenderer = new outline_renderer_type(*fBaseRenderer);
|
||||
|
||||
fOutlineRenderer->line_color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
|
||||
fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
|
||||
#else
|
||||
float width = fPenSize;
|
||||
_Transform(&width);
|
||||
agg::line_profile_aa prof;
|
||||
prof.width(width);
|
||||
|
||||
fOutlineRenderer = new outline_renderer_type(*fBaseRenderer, prof);
|
||||
fOutlineRenderer->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
|
||||
|
||||
fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
|
||||
#endif
|
||||
|
||||
// the renderer used for filling paths
|
||||
fRenderer = new renderer_type(*fBaseRenderer);
|
||||
fRasterizer = new rasterizer_type();
|
||||
fScanline = new scanline_type();
|
||||
|
||||
#if ALIASED_DRAWING
|
||||
fRasterizer->gamma(agg::gamma_threshold(0.5));
|
||||
#endif
|
||||
|
||||
fRenderer->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
|
||||
// These are renderers needed for drawing text
|
||||
fFontRendererSolid = new font_renderer_solid_type(*fBaseRenderer);
|
||||
|
||||
fFontRendererBin = new font_renderer_bin_type(*fBaseRenderer);
|
||||
|
||||
|
||||
_RebuildClipping();
|
||||
}
|
||||
}
|
||||
|
||||
// DetachFromBuffer
|
||||
void
|
||||
Painter::DetachFromBuffer()
|
||||
{
|
||||
_MakeEmpty();
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// ConstrainClipping
|
||||
void
|
||||
Painter::ConstrainClipping(const BRegion& region)
|
||||
{
|
||||
// The idea is that if the clipping region was
|
||||
// never constrained, there is *no* clipping.
|
||||
// This is of course different from having
|
||||
// an *empty* clipping region.
|
||||
if (!fClippingRegion)
|
||||
fClippingRegion = new BRegion(region);
|
||||
else
|
||||
*fClippingRegion = region;
|
||||
_RebuildClipping();
|
||||
}
|
||||
|
||||
// SetHighColor
|
||||
void
|
||||
Painter::SetHighColor(const rgb_color& color)
|
||||
{
|
||||
fPatternHandler->SetHighColor(color);
|
||||
|
||||
if (fOutlineRenderer)
|
||||
#if ALIASED_DRAWING
|
||||
fOutlineRenderer->line_color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
#else
|
||||
fOutlineRenderer->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
#endif
|
||||
if (fRenderer)
|
||||
fRenderer->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
if (fFontRendererSolid)
|
||||
fFontRendererSolid->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
if (fFontRendererBin)
|
||||
fFontRendererBin->color(agg::rgba(color.red / 255.0,
|
||||
color.green / 255.0,
|
||||
color.blue / 255.0));
|
||||
|
||||
}
|
||||
|
||||
// SetLowColor
|
||||
void
|
||||
Painter::SetLowColor(const rgb_color& color)
|
||||
{
|
||||
fPatternHandler->SetLowColor(color);;
|
||||
}
|
||||
|
||||
// SetScale
|
||||
void
|
||||
Painter::SetScale(float scale)
|
||||
{
|
||||
fScale = scale;
|
||||
_RebuildClipping();
|
||||
}
|
||||
|
||||
// SetScale
|
||||
void
|
||||
Painter::SetPenSize(float size)
|
||||
{
|
||||
fPenSize = size;
|
||||
}
|
||||
|
||||
// SetOrigin
|
||||
void
|
||||
Painter::SetOrigin(const BPoint& origin)
|
||||
{
|
||||
// NOTE: The BeBook says that the coordinate system
|
||||
// of a view cannot be changed during an update, because
|
||||
// it would mess up the clipping, and this is indeed
|
||||
// what would happen in this implementation as well.
|
||||
// I don't know yet what actually happens if you still
|
||||
// try to call SetOrigin() from within BView::Draw()
|
||||
fOrigin = origin;
|
||||
_RebuildClipping();
|
||||
}
|
||||
|
||||
// SetDrawingMode
|
||||
void
|
||||
Painter::SetDrawingMode(drawing_mode mode)
|
||||
{
|
||||
if (fDrawingMode != mode) {
|
||||
fDrawingMode = mode;
|
||||
if (fPixelFormat) {
|
||||
fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetPenLocation
|
||||
void
|
||||
Painter::SetPenLocation(const BPoint& location)
|
||||
{
|
||||
fPenLocation = location;
|
||||
}
|
||||
|
||||
// SetFont
|
||||
void
|
||||
Painter::SetFont(const BFont& font)
|
||||
{
|
||||
fFont = font;
|
||||
_UpdateFont();
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// StrokeLine
|
||||
void
|
||||
Painter::StrokeLine(BPoint a, BPoint b, const pattern& p)
|
||||
{
|
||||
_Transform(&a);
|
||||
_Transform(&b);
|
||||
|
||||
agg::path_storage path;
|
||||
path.move_to(a.x, a.y);
|
||||
path.line_to(b.x, b.y);
|
||||
|
||||
_StrokePath(path, p);
|
||||
|
||||
SetPenLocation(b);
|
||||
}
|
||||
|
||||
// StrokeLine
|
||||
void
|
||||
Painter::StrokeLine(BPoint b, const pattern& p)
|
||||
{
|
||||
// TODO: move this function elsewhere
|
||||
StrokeLine(fPenLocation, b);
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// StrokeTriangle
|
||||
void
|
||||
Painter::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const pattern& p) const
|
||||
{
|
||||
_DrawTriangle(pt1, pt2, pt3, p, false);
|
||||
}
|
||||
|
||||
// FillTriangle
|
||||
void
|
||||
Painter::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const pattern& p) const
|
||||
{
|
||||
_DrawTriangle(pt1, pt2, pt3, p, true);
|
||||
}
|
||||
|
||||
// StrokePolygon
|
||||
void
|
||||
Painter::StrokePolygon(const BPoint* ptArray, int32 numPts,
|
||||
bool closed, const pattern& p) const
|
||||
{
|
||||
_DrawPolygon(ptArray, numPts, closed, p, false);
|
||||
}
|
||||
|
||||
// FillPolygon
|
||||
void
|
||||
Painter::FillPolygon(const BPoint* ptArray, int32 numPts,
|
||||
bool closed, const pattern& p) const
|
||||
{
|
||||
_DrawPolygon(ptArray, numPts, closed, p, true);
|
||||
}
|
||||
|
||||
// StrokeBezier
|
||||
void
|
||||
Painter::StrokeBezier(const BPoint* controlPoints, const pattern& p) const
|
||||
{
|
||||
agg::path_storage curve;
|
||||
|
||||
BPoint p1(controlPoints[0]);
|
||||
BPoint p2(controlPoints[1]);
|
||||
BPoint p3(controlPoints[2]);
|
||||
BPoint p4(controlPoints[3]);
|
||||
_Transform(&p1);
|
||||
_Transform(&p2);
|
||||
_Transform(&p3);
|
||||
_Transform(&p4);
|
||||
|
||||
curve.move_to(p1.x, p1.y);
|
||||
curve.curve4(p1.x, p1.y,
|
||||
p2.x, p2.y,
|
||||
p3.x, p3.y);
|
||||
|
||||
|
||||
agg::conv_curve<agg::path_storage> path(curve);
|
||||
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// FillBezier
|
||||
void
|
||||
Painter::FillBezier(const BPoint* controlPoints, const pattern& p) const
|
||||
{
|
||||
agg::path_storage curve;
|
||||
|
||||
BPoint p1(controlPoints[0]);
|
||||
BPoint p2(controlPoints[1]);
|
||||
BPoint p3(controlPoints[2]);
|
||||
BPoint p4(controlPoints[3]);
|
||||
_Transform(&p1);
|
||||
_Transform(&p2);
|
||||
_Transform(&p3);
|
||||
_Transform(&p4);
|
||||
|
||||
curve.move_to(p1.x, p1.y);
|
||||
curve.curve4(p1.x, p1.y,
|
||||
p2.x, p2.y,
|
||||
p3.x, p3.y);
|
||||
curve.close_polygon();
|
||||
|
||||
agg::conv_curve<agg::path_storage> path(curve);
|
||||
|
||||
_FillPath(path, p);
|
||||
}
|
||||
|
||||
// StrokeShape
|
||||
void
|
||||
Painter::StrokeShape(/*const */BShape* shape, const pattern& p) const
|
||||
{
|
||||
_DrawShape(shape, p, false);
|
||||
}
|
||||
|
||||
// FillShape
|
||||
void
|
||||
Painter::FillShape(/*const */BShape* shape, const pattern& p) const
|
||||
{
|
||||
_DrawShape(shape, p, true);
|
||||
}
|
||||
|
||||
// StrokeRect
|
||||
void
|
||||
Painter::StrokeRect(const BRect& r, const pattern& p) const
|
||||
{
|
||||
BPoint a(r.left, r.top);
|
||||
BPoint b(r.right, r.top);
|
||||
BPoint c(r.right, r.bottom);
|
||||
BPoint d(r.left, r.bottom);
|
||||
_Transform(&a);
|
||||
_Transform(&b);
|
||||
_Transform(&c);
|
||||
_Transform(&d);
|
||||
|
||||
agg::path_storage path;
|
||||
path.move_to(a.x, a.y);
|
||||
path.line_to(b.x, b.y);
|
||||
path.line_to(c.x, c.y);
|
||||
path.line_to(d.x, d.y);
|
||||
path.close_polygon();
|
||||
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// FillRect
|
||||
void
|
||||
Painter::FillRect(const BRect& r, const pattern& p) const
|
||||
{
|
||||
BPoint a(r.left, r.top);
|
||||
BPoint b(r.right, r.top);
|
||||
BPoint c(r.right, r.bottom);
|
||||
BPoint d(r.left, r.bottom);
|
||||
_Transform(&a, false);
|
||||
_Transform(&b, false);
|
||||
_Transform(&c, false);
|
||||
_Transform(&d, false);
|
||||
|
||||
// account for stricter interpretation of coordinates in AGG
|
||||
// the rectangle ranges from the top-left (.0, .0)
|
||||
// to the bottom-right (.9999, .9999) corner of pixels
|
||||
b.x += 1.0;
|
||||
c.x += 1.0;
|
||||
c.y += 1.0;
|
||||
d.y += 1.0;
|
||||
|
||||
agg::path_storage path;
|
||||
path.move_to(a.x, a.y);
|
||||
path.line_to(b.x, b.y);
|
||||
path.line_to(c.x, c.y);
|
||||
path.line_to(d.x, d.y);
|
||||
path.close_polygon();
|
||||
|
||||
_FillPath(path, p);
|
||||
}
|
||||
|
||||
// StrokeRoundRect
|
||||
void
|
||||
Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius,
|
||||
const pattern& p) const
|
||||
{
|
||||
BPoint lt(r.left, r.top);
|
||||
BPoint rb(r.right, r.bottom);
|
||||
_Transform(<);
|
||||
_Transform(&rb);
|
||||
|
||||
_Transform(&xRadius);
|
||||
_Transform(&yRadius);
|
||||
|
||||
agg::rounded_rect rect;
|
||||
rect.rect(lt.x, lt.y, rb.x, rb.y);
|
||||
rect.radius(xRadius, yRadius);
|
||||
|
||||
// agg::conv_curve<agg::rounded_rect> path(rect);
|
||||
|
||||
// _StrokePath(path, p);
|
||||
_StrokePath(rect, p);
|
||||
}
|
||||
|
||||
// FillRoundRect
|
||||
void
|
||||
Painter::FillRoundRect(const BRect& r, float xRadius, float yRadius,
|
||||
const pattern& p) const
|
||||
{
|
||||
BPoint lt(r.left, r.top);
|
||||
BPoint rb(r.right, r.bottom);
|
||||
_Transform(<, false);
|
||||
_Transform(&rb, false);
|
||||
|
||||
// account for stricter interpretation of coordinates in AGG
|
||||
// the rectangle ranges from the top-left (.0, .0)
|
||||
// to the bottom-right (.9999, .9999) corner of pixels
|
||||
rb.x += 1.0;
|
||||
rb.y += 1.0;
|
||||
|
||||
_Transform(&xRadius);
|
||||
_Transform(&yRadius);
|
||||
|
||||
agg::rounded_rect rect;
|
||||
rect.rect(lt.x, lt.y, rb.x, rb.y);
|
||||
rect.radius(xRadius, yRadius);
|
||||
|
||||
agg::conv_curve<agg::rounded_rect> path(rect);
|
||||
|
||||
_FillPath(path, p);
|
||||
}
|
||||
|
||||
// StrokeEllipse
|
||||
void
|
||||
Painter::StrokeEllipse(BPoint center, float xRadius, float yRadius,
|
||||
const pattern& p) const
|
||||
{
|
||||
_DrawEllipse(center, xRadius, yRadius, p, false);
|
||||
}
|
||||
|
||||
// FillEllipse
|
||||
void
|
||||
Painter::FillEllipse(BPoint center, float xRadius, float yRadius,
|
||||
const pattern& p) const
|
||||
{
|
||||
_DrawEllipse(center, xRadius, yRadius, p, true);
|
||||
}
|
||||
|
||||
// StrokeArc
|
||||
void
|
||||
Painter::StrokeArc(BPoint center, float xRadius, float yRadius,
|
||||
float angle, float span, const pattern& p) const
|
||||
{
|
||||
_Transform(¢er);
|
||||
_Transform(&xRadius);
|
||||
_Transform(&yRadius);
|
||||
|
||||
double angleRad = (angle * PI) / 180.0;
|
||||
double spanRad = (span * PI) / 180.0;
|
||||
agg::bezier_arc arc(center.x, center.y, xRadius, yRadius,
|
||||
-angleRad, -spanRad);
|
||||
|
||||
agg::conv_curve<agg::bezier_arc> path(arc);
|
||||
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// FillArc
|
||||
void
|
||||
Painter::FillArc(BPoint center, float xRadius, float yRadius,
|
||||
float angle, float span, const pattern& p) const
|
||||
{
|
||||
_Transform(¢er);
|
||||
_Transform(&xRadius);
|
||||
_Transform(&yRadius);
|
||||
|
||||
double angleRad = (angle * PI) / 180.0;
|
||||
double spanRad = (span * PI) / 180.0;
|
||||
agg::bezier_arc arc(center.x, center.y, xRadius, yRadius,
|
||||
-angleRad, -spanRad);
|
||||
|
||||
agg::conv_curve<agg::bezier_arc> segmentedArc(arc);
|
||||
|
||||
agg::path_storage path;
|
||||
|
||||
// build a new path by starting at the center point,
|
||||
// then traversing the arc, then going back to the center
|
||||
path.move_to(center.x, center.y);
|
||||
|
||||
segmentedArc.rewind(0);
|
||||
double x;
|
||||
double y;
|
||||
unsigned cmd = segmentedArc.vertex(&x, &y);
|
||||
while (!agg::is_stop(cmd)) {
|
||||
path.line_to(x, y);
|
||||
cmd = segmentedArc.vertex(&x, &y);
|
||||
}
|
||||
|
||||
path.close_polygon();
|
||||
|
||||
_FillPath(path, p);
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// DrawString
|
||||
void
|
||||
Painter::DrawString(const char* utf8String, BPoint baseLine) const
|
||||
{
|
||||
fPatternHandler->SetPattern(B_SOLID_HIGH);
|
||||
|
||||
_Transform(&baseLine);
|
||||
|
||||
Transformable transform;
|
||||
// TODO: convert BFont::Shear(), which is in degrees 45°...135° to whatever AGG is using
|
||||
// transform.ShearBy(B_ORIGIN, fFont.Shear(), 0.0);
|
||||
transform.RotateBy(B_ORIGIN, -fFont.Rotation());
|
||||
transform.ScaleBy(B_ORIGIN, fScale, fScale);
|
||||
transform.TranslateBy(baseLine);
|
||||
|
||||
fTextRenderer->RenderString(utf8String,
|
||||
fFontRendererSolid,
|
||||
fFontRendererBin,
|
||||
transform);
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// DrawBitmap
|
||||
void
|
||||
Painter::DrawBitmap(const BBitmap* bitmap,
|
||||
BRect bitmapRect, BRect viewRect) const
|
||||
{
|
||||
typedef agg::span_allocator<agg::rgba8> span_alloc_type;
|
||||
typedef agg::span_interpolator_linear<> interpolator_type;
|
||||
typedef agg::span_image_filter_rgba32_nn<agg::order_bgra32,
|
||||
interpolator_type> span_gen_type;
|
||||
typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_type;
|
||||
|
||||
if (bitmap && bitmap->IsValid()
|
||||
&& bitmapRect.IsValid() && bitmapRect.Intersects(bitmap->Bounds())
|
||||
&& viewRect.IsValid()) {
|
||||
|
||||
// calculate the scaling
|
||||
double xScale = (viewRect.Width() + 1) / (bitmapRect.Width() + 1);
|
||||
double yScale = (viewRect.Height() + 1) / (bitmapRect.Height() + 1);
|
||||
|
||||
float xOffset = viewRect.left - (bitmapRect.left * xScale);
|
||||
float yOffset = viewRect.top - (bitmapRect.top * yScale);
|
||||
|
||||
BRect actualBitmapRect = bitmap->Bounds();
|
||||
|
||||
// constrain rect to passed bitmap bounds
|
||||
bitmapRect = bitmapRect & actualBitmapRect;
|
||||
|
||||
|
||||
// source rendering buffer
|
||||
agg::rendering_buffer srcBuffer;
|
||||
srcBuffer.attach((uint8*)bitmap->Bits(),
|
||||
actualBitmapRect.IntegerWidth() + 1,
|
||||
actualBitmapRect.IntegerHeight() + 1,
|
||||
bitmap->BytesPerRow());
|
||||
|
||||
agg::trans_affine srcMatrix;
|
||||
srcMatrix *= agg::trans_affine_translation(fOrigin.x, fOrigin.y);
|
||||
srcMatrix *= agg::trans_affine_scaling(fScale, fScale);
|
||||
|
||||
agg::trans_affine imgMatrix;
|
||||
// TODO: What about bitmap bounds that have a top-left corner other than B_ORIGIN?!?
|
||||
// Ignoring it produces the same result as BView though...
|
||||
// imgMatrix *= agg::trans_affine_translation(actualBitmapRect.left, actualBitmapRect.top);
|
||||
imgMatrix *= agg::trans_affine_scaling(xScale, yScale);
|
||||
imgMatrix *= agg::trans_affine_translation(xOffset, yOffset);
|
||||
imgMatrix *= agg::trans_affine_translation(fOrigin.x, fOrigin.y);
|
||||
imgMatrix *= agg::trans_affine_scaling(fScale, fScale);
|
||||
imgMatrix.invert();
|
||||
|
||||
span_alloc_type sa;
|
||||
interpolator_type interpolator(imgMatrix);
|
||||
|
||||
span_gen_type sg(sa, srcBuffer, agg::rgba(0, 0, 0, 0), interpolator);
|
||||
|
||||
image_renderer_type ri(*fBaseRenderer, sg);
|
||||
|
||||
agg::rasterizer_scanline_aa<> pf;
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
// path encloses image
|
||||
agg::path_storage path;
|
||||
path.move_to(viewRect.left, viewRect.top);
|
||||
path.line_to(viewRect.right + 1, viewRect.top);
|
||||
path.line_to(viewRect.right + 1, viewRect.bottom + 1);
|
||||
path.line_to(viewRect.left, viewRect.bottom + 1);
|
||||
path.line_to(viewRect.left, viewRect.top);
|
||||
|
||||
agg::conv_transform<agg::path_storage> tr(path, srcMatrix);
|
||||
|
||||
pf.add_path(tr);
|
||||
agg::render_scanlines(pf, sl, ri);
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _MakeEmpty
|
||||
void
|
||||
Painter::_MakeEmpty()
|
||||
{
|
||||
delete fBuffer;
|
||||
fBuffer = NULL;
|
||||
|
||||
delete fPixelFormat;
|
||||
fPixelFormat = NULL;
|
||||
|
||||
delete fBaseRenderer;
|
||||
fBaseRenderer = NULL;
|
||||
|
||||
delete fOutlineRenderer;
|
||||
fOutlineRenderer = NULL;
|
||||
|
||||
delete fOutlineRasterizer;
|
||||
fOutlineRasterizer = NULL;
|
||||
|
||||
delete fScanline;
|
||||
fScanline = NULL;
|
||||
|
||||
delete fRasterizer;
|
||||
fRasterizer = NULL;
|
||||
|
||||
delete fRenderer;
|
||||
fRenderer = NULL;
|
||||
|
||||
delete fFontRendererSolid;
|
||||
fFontRendererSolid = NULL;
|
||||
|
||||
delete fFontRendererBin;
|
||||
fFontRendererBin = NULL;
|
||||
}
|
||||
|
||||
// _Transform
|
||||
void
|
||||
Painter::_Transform(BPoint* point, bool centerOffset) const
|
||||
{
|
||||
*point += fOrigin;
|
||||
// rounding
|
||||
if (!fSubpixelPrecise) {
|
||||
// TODO: validate usage of floor() for values < 0
|
||||
point->x = floorf(point->x);
|
||||
point->y = floorf(point->y);
|
||||
}
|
||||
// apply the scale
|
||||
point->x *= fScale;
|
||||
point->y *= fScale;
|
||||
// this code is supposed to move coordinates to the center of pixels,
|
||||
// as AGG considers (0,0) to be the "upper left corner" of a pixel,
|
||||
// but BViews are less strict on those details
|
||||
if (centerOffset) {
|
||||
point->x += 0.5;
|
||||
point->y += 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// _Transform
|
||||
BPoint
|
||||
Painter::_Transform(const BPoint& point, bool centerOffset) const
|
||||
{
|
||||
BPoint ret = point;
|
||||
_Transform(&ret, centerOffset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// _Transform
|
||||
void
|
||||
Painter::_Transform(float* width) const
|
||||
{
|
||||
*width *= fScale;
|
||||
if (*width < 1)
|
||||
*width = 1;
|
||||
}
|
||||
|
||||
// _Transform
|
||||
float
|
||||
Painter::_Transform(const float& width) const
|
||||
{
|
||||
float w = width * fScale;
|
||||
if (w < 1)
|
||||
w = 1;
|
||||
return w;
|
||||
}
|
||||
|
||||
// _RebuildClipping
|
||||
void
|
||||
Painter::_RebuildClipping()
|
||||
{
|
||||
if (fBaseRenderer) {
|
||||
fBaseRenderer->reset_clipping(!fClippingRegion);
|
||||
if (fClippingRegion) {
|
||||
int32 count = fClippingRegion->CountRects();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BRect r = fClippingRegion->RectAt(i);
|
||||
// NOTE: The rounding here appears to give somewhat
|
||||
// different results compared to Be's implementation,
|
||||
// though I was unable to figure out the difference
|
||||
BPoint lt(r.LeftTop());
|
||||
BPoint rb(r.RightBottom());
|
||||
rb += BPoint(1.0, 1.0);
|
||||
// _Transform(<, false);
|
||||
// _Transform(&rb, false);
|
||||
lt += fOrigin;
|
||||
lt.x *= fScale;
|
||||
lt.y *= fScale;
|
||||
rb += fOrigin;
|
||||
rb.x *= fScale;
|
||||
rb.y *= fScale;
|
||||
rb -= BPoint(1.0, 1.0);
|
||||
// fBaseRenderer->add_clip_box(floorf(lt.x),
|
||||
// floorf(lt.y),
|
||||
// ceilf(rb.x),
|
||||
// ceilf(rb.y));
|
||||
fBaseRenderer->add_clip_box(roundf(lt.x),
|
||||
roundf(lt.y),
|
||||
roundf(rb.x),
|
||||
roundf(rb.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _UpdateFont
|
||||
void
|
||||
Painter::_UpdateFont()
|
||||
{
|
||||
font_family family;
|
||||
font_style style;
|
||||
fFont.GetFamilyAndStyle(&family, &style);
|
||||
|
||||
bool success = fTextRenderer->SetFamilyAndStyle(family, style);
|
||||
if (!success) {
|
||||
fprintf(stderr, "unable to set '%s' + '%s'\n", family, style);
|
||||
fprintf(stderr, "font is still: '%s' + '%s'\n",
|
||||
fTextRenderer->Family(), fTextRenderer->Style());
|
||||
}
|
||||
|
||||
fTextRenderer->SetPointSize(fFont.Size());
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _DrawTriangle
|
||||
inline void
|
||||
Painter::_DrawTriangle(BPoint pt1, BPoint pt2, BPoint pt3,
|
||||
const pattern& p, bool fill) const
|
||||
{
|
||||
_Transform(&pt1);
|
||||
_Transform(&pt2);
|
||||
_Transform(&pt3);
|
||||
|
||||
agg::path_storage path;
|
||||
|
||||
path.move_to(pt1.x, pt1.y);
|
||||
path.line_to(pt2.x, pt2.y);
|
||||
path.line_to(pt3.x, pt3.y);
|
||||
|
||||
path.close_polygon();
|
||||
|
||||
if (fill)
|
||||
_FillPath(path, p);
|
||||
else
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// _DrawEllipse
|
||||
inline void
|
||||
Painter::_DrawEllipse(BPoint center, float xRadius, float yRadius,
|
||||
const pattern& p, bool fill) const
|
||||
{
|
||||
// TODO: I think the conversion and the offset of
|
||||
// pixel centers might not be correct here, and it
|
||||
// might even be necessary to treat Fill and Stroke
|
||||
// differently, as with Fill-/StrokeRect().
|
||||
_Transform(¢er);
|
||||
_Transform(&xRadius);
|
||||
_Transform(&yRadius);
|
||||
|
||||
float width = fPenSize;
|
||||
_Transform(&width);
|
||||
|
||||
int32 divisions = (int32)((xRadius + yRadius) * PI) / 2 * (int32)width;
|
||||
|
||||
agg::ellipse path(center.x, center.y, xRadius, yRadius, divisions);
|
||||
|
||||
if (fill)
|
||||
_FillPath(path, p);
|
||||
else
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// _DrawShape
|
||||
inline void
|
||||
Painter::_DrawShape(/*const */BShape* shape, const pattern& p, bool fill) const
|
||||
{
|
||||
// TODO: untested
|
||||
agg::path_storage path;
|
||||
ShapeConverter converter(&path);
|
||||
|
||||
// account for our view coordinate system
|
||||
converter.ScaleBy(B_ORIGIN, fScale, fScale);
|
||||
converter.TranslateBy(fOrigin);
|
||||
// offset locations to center of pixels
|
||||
converter.TranslateBy(BPoint(0.5, 0.5));
|
||||
|
||||
converter.Iterate(shape);
|
||||
|
||||
if (fill)
|
||||
_FillPath(path, p);
|
||||
else
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
|
||||
// _DrawPolygon
|
||||
inline void
|
||||
Painter::_DrawPolygon(const BPoint* ptArray, int32 numPts,
|
||||
bool closed, const pattern& p, bool fill) const
|
||||
{
|
||||
if (numPts > 0) {
|
||||
|
||||
agg::path_storage path;
|
||||
BPoint point = _Transform(*ptArray);
|
||||
path.move_to(point.x, point.y);
|
||||
|
||||
for (int32 i = 1; i < numPts; i++) {
|
||||
ptArray++;
|
||||
point = _Transform(*ptArray);
|
||||
path.line_to(point.x, point.y);
|
||||
}
|
||||
|
||||
if (closed)
|
||||
path.close_polygon();
|
||||
|
||||
if (fill)
|
||||
_FillPath(path, p);
|
||||
else
|
||||
_StrokePath(path, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// _StrokePath
|
||||
template<class VertexSource>
|
||||
void
|
||||
Painter::_StrokePath(VertexSource& path, const pattern& p) const
|
||||
{
|
||||
fPatternHandler->SetPattern(p);
|
||||
|
||||
float width = fPenSize;
|
||||
_Transform(&width);
|
||||
|
||||
#if ALIASED_DRAWING
|
||||
if (width > 1.0) {
|
||||
agg::conv_stroke<VertexSource> stroke(path);
|
||||
stroke.width(width);
|
||||
|
||||
fRasterizer->add_path(stroke);
|
||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
||||
} else {
|
||||
fOutlineRasterizer->add_path(path);
|
||||
}
|
||||
#else
|
||||
agg::line_profile_aa prof;
|
||||
prof.width(width);
|
||||
fOutlineRenderer->profile(prof);
|
||||
fOutlineRasterizer->add_path(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
// _FillPath
|
||||
template<class VertexSource>
|
||||
void
|
||||
Painter::_FillPath(VertexSource& path, const pattern& p) const
|
||||
{
|
||||
fPatternHandler->SetPattern(p);
|
||||
|
||||
fRasterizer->add_path(path);
|
||||
agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
|
||||
}
|
288
src/servers/app/server/Painter/Painter.h
Normal file
288
src/servers/app/server/Painter/Painter.h
Normal file
@ -0,0 +1,288 @@
|
||||
// Painter.h
|
||||
|
||||
#ifndef PAINTER_H
|
||||
#define PAINTER_H
|
||||
|
||||
#include <Font.h>
|
||||
#include <Rect.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "forwarding_pixfmt.h"
|
||||
|
||||
class AGGTextRenderer;
|
||||
class BBitmap;
|
||||
class BRegion;
|
||||
class PatternHandler;
|
||||
class RenderingBuffer;
|
||||
|
||||
class Painter {
|
||||
public:
|
||||
Painter();
|
||||
virtual ~Painter();
|
||||
|
||||
// frame buffer stuff
|
||||
void AttachToBuffer(RenderingBuffer* buffer);
|
||||
void DetachFromBuffer();
|
||||
|
||||
void ConstrainClipping(const BRegion& region);
|
||||
|
||||
// object settings
|
||||
void SetHighColor(const rgb_color& color);
|
||||
void SetHighColor(uint8 r, uint8 g, uint8 b, uint8 a = 255);
|
||||
void SetLowColor(const rgb_color& color);
|
||||
void SetLowColor(uint8 r, uint8 g, uint8 b, uint8 a = 255);
|
||||
|
||||
void SetScale(float scale);
|
||||
void SetPenSize(float size);
|
||||
void SetOrigin(const BPoint& origin);
|
||||
void SetDrawingMode(drawing_mode mode);
|
||||
void SetPenLocation(const BPoint& location);
|
||||
void SetFont(const BFont& font);
|
||||
|
||||
// painting functions
|
||||
|
||||
// lines
|
||||
void StrokeLine( BPoint a,
|
||||
BPoint b,
|
||||
const pattern& p = B_SOLID_HIGH);
|
||||
|
||||
void StrokeLine( BPoint b,
|
||||
const pattern& p = B_SOLID_HIGH);
|
||||
|
||||
// triangles
|
||||
void StrokeTriangle( BPoint pt1,
|
||||
BPoint pt2,
|
||||
BPoint pt3,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillTriangle( BPoint pt1,
|
||||
BPoint pt2,
|
||||
BPoint pt3,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// polygons
|
||||
void StrokePolygon( const BPoint* ptArray,
|
||||
int32 numPts,
|
||||
bool closed = true,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillPolygon( const BPoint* ptArray,
|
||||
int32 numPts,
|
||||
bool closed = true,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// bezier curves
|
||||
void StrokeBezier( const BPoint* controlPoints,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillBezier( const BPoint* controlPoints,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// shapes
|
||||
void StrokeShape( /*const */BShape* shape,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillShape( /*const */BShape* shape,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
|
||||
// rects
|
||||
void StrokeRect( const BRect& r,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillRect( const BRect& r,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// round rects
|
||||
void StrokeRoundRect(const BRect& r,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillRoundRect( const BRect& r,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// ellipses
|
||||
void StrokeEllipse( BPoint center,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillEllipse( BPoint center,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// arcs
|
||||
void StrokeArc( BPoint center,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
float angle,
|
||||
float span,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
void FillArc( BPoint center,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
float angle,
|
||||
float span,
|
||||
const pattern& p = B_SOLID_HIGH) const;
|
||||
|
||||
// strings
|
||||
void DrawString( const char* utf8String,
|
||||
BPoint baseLine) const;
|
||||
|
||||
// bitmaps
|
||||
void DrawBitmap( const BBitmap* bitmap,
|
||||
BRect bitmapRect,
|
||||
BRect viewRect) const;
|
||||
|
||||
|
||||
// MISSING:
|
||||
/* void FillRegion( const BRegion* region,
|
||||
const pattern& p = B_SOLID_HIGH);
|
||||
|
||||
void InvertRect( BRect r);
|
||||
|
||||
|
||||
// "screen blits"
|
||||
void CopyBits( BRect src, BRect dst);
|
||||
|
||||
|
||||
// more string support
|
||||
void DrawChar( char aChar);
|
||||
|
||||
void DrawChar( char aChar,
|
||||
BPoint location);
|
||||
|
||||
void DrawString( const char* string,
|
||||
const escapement_delta* delta = NULL);
|
||||
|
||||
void DrawString( const char* string,
|
||||
BPoint location,
|
||||
const escapement_delta* delta = NULL);
|
||||
|
||||
void DrawString( const char* string,
|
||||
int32 length,
|
||||
const escapement_delta* delta = NULL);
|
||||
|
||||
void DrawString( const char* string,
|
||||
int32 length,
|
||||
BPoint location,
|
||||
const escapement_delta* delta = 0L);*/
|
||||
|
||||
|
||||
private:
|
||||
void _MakeEmpty();
|
||||
|
||||
void _Transform(BPoint* point,
|
||||
bool centerOffset = true) const;
|
||||
BPoint _Transform(const BPoint& point,
|
||||
bool centerOffset = true) const;
|
||||
void _Transform(float* width) const;
|
||||
float _Transform(const float& width) const;
|
||||
|
||||
void _RebuildClipping();
|
||||
|
||||
void _UpdateFont();
|
||||
|
||||
// drawing functions stroke/fill
|
||||
void _DrawTriangle( BPoint pt1,
|
||||
BPoint pt2,
|
||||
BPoint pt3,
|
||||
const pattern& p,
|
||||
bool fill) const;
|
||||
void _DrawEllipse( BPoint center,
|
||||
float xRadius,
|
||||
float yRadius,
|
||||
const pattern& p,
|
||||
bool fill) const;
|
||||
void _DrawShape( /*const */BShape* shape,
|
||||
const pattern& p,
|
||||
bool fill) const;
|
||||
void _DrawPolygon( const BPoint* ptArray,
|
||||
int32 numPts,
|
||||
bool closed,
|
||||
const pattern& p,
|
||||
bool fill) const;
|
||||
|
||||
|
||||
template<class VertexSource>
|
||||
void _StrokePath(VertexSource& path,
|
||||
const pattern& p) const;
|
||||
template<class VertexSource>
|
||||
void _FillPath(VertexSource& path,
|
||||
const pattern& p) const;
|
||||
|
||||
agg::rendering_buffer* fBuffer;
|
||||
|
||||
// Man könnte das alles vielleicht wieder schneller machen,
|
||||
// wenn man für jeden blending_mode einen eigenen Renderer
|
||||
// mit eignenem entsprechenden Pixelformat vorhält.
|
||||
// Dann könnten für B_SOLID_HIGH und jegliche andere const pattern&
|
||||
// getrennt zwei Versionen von jedem blending_mode existieren.
|
||||
|
||||
// AGG rendering and rasterization classes
|
||||
pixfmt* fPixelFormat;
|
||||
renderer_base* fBaseRenderer;
|
||||
|
||||
outline_renderer_type* fOutlineRenderer;
|
||||
outline_rasterizer_type* fOutlineRasterizer;
|
||||
|
||||
scanline_type* fScanline;
|
||||
rasterizer_type* fRasterizer;
|
||||
renderer_type* fRenderer;
|
||||
|
||||
font_renderer_solid_type* fFontRendererSolid;
|
||||
font_renderer_bin_type* fFontRendererBin;
|
||||
|
||||
// for internal coordinate rounding/transformation,
|
||||
// does not concern rendering
|
||||
bool fSubpixelPrecise;
|
||||
|
||||
float fScale;
|
||||
float fPenSize;
|
||||
BPoint fOrigin;
|
||||
BRegion* fClippingRegion; // NULL indicates no clipping at all
|
||||
drawing_mode fDrawingMode;
|
||||
BPoint fPenLocation;
|
||||
PatternHandler* fPatternHandler;
|
||||
|
||||
BFont fFont;
|
||||
// a class handling rendering and caching of glyphs
|
||||
// it is setup to load from a specific Freetype supported
|
||||
// font file, it uses the FontManager to locate a file
|
||||
// by Family and Style
|
||||
AGGTextRenderer* fTextRenderer;
|
||||
};
|
||||
|
||||
// SetHighColor
|
||||
inline void
|
||||
Painter::SetHighColor(uint8 r, uint8 g, uint8 b, uint8 a)
|
||||
{
|
||||
rgb_color color;
|
||||
color.red = r;
|
||||
color.green = g;
|
||||
color.blue = b;
|
||||
color.alpha = a;
|
||||
SetHighColor(color);
|
||||
}
|
||||
|
||||
// SetLowColor
|
||||
inline void
|
||||
Painter::SetLowColor(uint8 r, uint8 g, uint8 b, uint8 a)
|
||||
{
|
||||
rgb_color color;
|
||||
color.red = r;
|
||||
color.green = g;
|
||||
color.blue = b;
|
||||
color.alpha = a;
|
||||
SetLowColor(color);
|
||||
}
|
||||
|
||||
|
||||
#endif // PAINTER_H
|
||||
|
||||
|
33
src/servers/app/server/Painter/README
Normal file
33
src/servers/app/server/Painter/README
Normal file
@ -0,0 +1,33 @@
|
||||
About:
|
||||
|
||||
Painter is a class implementing the BView drawing functions with the Anti-Grain Geometry 2D engine. It should be usable by the Haiku app_server as the complete drawing backend. It can be attached to a frame buffer and used just like a BView that is attached to a BBitmap. Full anti-aliased drawing is available as a compile time option (defines.h). I hope it will be possible to integrate this into the existing Haiku app_server framework without too much hassle.
|
||||
|
||||
|
||||
|
||||
Status:
|
||||
|
||||
1) Most of the drawing modes are unimplemented.
|
||||
|
||||
I want to work out the effects of the drawing_mode together with the source_alpha and alpha_func. Currently, Painter supports B_OP_COPY, B_OP_OVER and B_OP_INVERT with patterns. It is kind of ignorant towards the orginal app_servers treatment of alpha in the high and low color. I think it acts for the most part as if the BView was SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE), especially for drawing bitmaps, which will of course be fixed, but should be no obstacle in integrating Painter right now.
|
||||
|
||||
2) Only 32 bit frame buffers are support yet.
|
||||
|
||||
Most of the work in supporting other color spaces is only in the drawing_mode classes. It makes no sense to start work on these before I have even nailed the details once on the 32 bit case.
|
||||
|
||||
3) Only 32 bit Bitmaps are supported for drawing yet.
|
||||
|
||||
There is some work involved when trying to make this fast. The conversion should probably take place in the interpolator class that AGG uses for up/downscaling a bitmap.
|
||||
|
||||
4) Most of the BView behaviour for DrawString() is missing.
|
||||
|
||||
There is a lot of inconsistency in the BView implementation concerning the "current pen position", but all versions of DrawString() do put the pen at the position of the virtual next character. I will see to that when I implement all this escapment_delta stuff.
|
||||
|
||||
5) Font handling is somewhat weird.
|
||||
|
||||
There is a FontManager class that is supposed to be an interface between font family/style names and font files on disk loadable by Freetype. There is a TextRenderer interface class and AGGTextRenderer implementation that can be used to get the job done, but this is of course very open for discussion. I didn't really look at what was already available in the Haiku repository, but just took from WonderBrush what I already had. The biggest problem when testing Painter on R5 is the sometimes slightly different naming of font families in Freetype and R5. Sometimes, FontManager is not able to match up the correct file for the given family and style. For the "default" "Swiss911 BT", it works. If the be_plain_font can not be "loaded" by FontManager, it might look like font rendering is not working at all, you might have to tweak this, or maybe hardcode a font that works. Of course, on a "true Haiku system", once such a thing exists, this problem will be non-existent. Fonts will just be named as Freetype suggests, and everything will match up fine.
|
||||
|
||||
6) The framework is still developing.
|
||||
|
||||
I'm still working on many ends of Painter and I might refactor things. The basic idea will of course stay for the most part, and is of course open for discussion by the rest of the team. I felt I wanted to get some results first, then see how it can all be improved. So, keep the comments comming.
|
||||
|
||||
|
22
src/servers/app/server/Painter/RenderingBuffer.h
Normal file
22
src/servers/app/server/Painter/RenderingBuffer.h
Normal file
@ -0,0 +1,22 @@
|
||||
// RenderingBuffer.h
|
||||
|
||||
#ifndef RENDERING_BUFFER_H
|
||||
#define RENDERING_BUFFER_H
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
class RenderingBuffer {
|
||||
public:
|
||||
RenderingBuffer() {};
|
||||
virtual ~RenderingBuffer() {};
|
||||
|
||||
virtual status_t InitCheck() const = 0;
|
||||
|
||||
virtual color_space ColorSpace() const = 0;
|
||||
virtual void* Bits() const = 0;
|
||||
virtual uint32 BytesPerRow() const = 0;
|
||||
virtual uint32 Width() const = 0;
|
||||
virtual uint32 Height() const = 0;
|
||||
};
|
||||
|
||||
#endif // RENDERING_BUFFER_H
|
90
src/servers/app/server/Painter/ShapeConverter.cpp
Normal file
90
src/servers/app/server/Painter/ShapeConverter.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// ShapeConverter.cpp
|
||||
|
||||
#include "ShapeConverter.h"
|
||||
|
||||
// constructor
|
||||
ShapeConverter::ShapeConverter()
|
||||
: BShapeIterator(),
|
||||
Transformable(),
|
||||
fPath(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
ShapeConverter::ShapeConverter(agg::path_storage* path)
|
||||
: BShapeIterator(),
|
||||
Transformable(),
|
||||
fPath(path)
|
||||
{
|
||||
}
|
||||
|
||||
// SetPath
|
||||
void
|
||||
ShapeConverter::SetPath(agg::path_storage* path)
|
||||
{
|
||||
fPath = path;
|
||||
}
|
||||
|
||||
// IterateMoveTo
|
||||
status_t
|
||||
ShapeConverter::IterateMoveTo(BPoint* point)
|
||||
{
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
Transform(&x, &y);
|
||||
|
||||
fPath->move_to(x, y);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// IterateLineTo
|
||||
status_t
|
||||
ShapeConverter::IterateLineTo(int32 lineCount, BPoint* linePts)
|
||||
{
|
||||
while (lineCount--) {
|
||||
|
||||
double x = linePts->x;
|
||||
double y = linePts->y;
|
||||
Transform(&x, &y);
|
||||
|
||||
fPath->line_to(x, y);
|
||||
|
||||
linePts++;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// IterateBezierTo
|
||||
status_t
|
||||
ShapeConverter::IterateBezierTo(int32 bezierCount, BPoint* bezierPts)
|
||||
{
|
||||
while (bezierCount--) {
|
||||
|
||||
double x1 = bezierPts[0].x;
|
||||
double y1 = bezierPts[0].y;
|
||||
|
||||
double x2 = bezierPts[1].x;
|
||||
double y2 = bezierPts[1].y;
|
||||
|
||||
double x3 = bezierPts[2].x;
|
||||
double y3 = bezierPts[2].y;
|
||||
|
||||
Transform(&x1, &y1);
|
||||
Transform(&x2, &y2);
|
||||
Transform(&x3, &y3);
|
||||
|
||||
fPath->curve4(x1, y1, x2, y2, x3, y3);
|
||||
|
||||
bezierPts += 3;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// IterateClose
|
||||
status_t
|
||||
ShapeConverter::IterateClose()
|
||||
{
|
||||
fPath->close_polygon();
|
||||
return B_OK;
|
||||
}
|
34
src/servers/app/server/Painter/ShapeConverter.h
Normal file
34
src/servers/app/server/Painter/ShapeConverter.h
Normal file
@ -0,0 +1,34 @@
|
||||
// ShapeConverter.h
|
||||
|
||||
#ifndef SHAPE_CONVERTER_H
|
||||
#define SHAPE_CONVERTER_H
|
||||
|
||||
#include <Shape.h>
|
||||
|
||||
#include <agg_path_storage.h>
|
||||
|
||||
#include "Transformable.h"
|
||||
|
||||
class BPoint;
|
||||
|
||||
// TODO: test if this actually works
|
||||
|
||||
class ShapeConverter : public BShapeIterator,
|
||||
public Transformable {
|
||||
public:
|
||||
ShapeConverter();
|
||||
ShapeConverter(agg::path_storage* path);
|
||||
virtual ~ShapeConverter() {};
|
||||
|
||||
void SetPath(agg::path_storage* path);
|
||||
|
||||
virtual status_t IterateMoveTo(BPoint* point);
|
||||
virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts);
|
||||
virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts);
|
||||
virtual status_t IterateClose();
|
||||
|
||||
private:
|
||||
agg::path_storage* fPath;
|
||||
};
|
||||
|
||||
#endif // SHAPE_CONVERTER_H
|
309
src/servers/app/server/Painter/Transformable.cpp
Normal file
309
src/servers/app/server/Painter/Transformable.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
// Transformable.h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Message.h>
|
||||
|
||||
#include "Transformable.h"
|
||||
|
||||
// min4
|
||||
inline float
|
||||
min4(float a, float b, float c, float d)
|
||||
{
|
||||
return min_c(a, min_c(b, min_c(c, d)));
|
||||
}
|
||||
|
||||
// max4
|
||||
inline float
|
||||
max4(float a, float b, float c, float d)
|
||||
{
|
||||
return max_c(a, max_c(b, max_c(c, d)));
|
||||
}
|
||||
|
||||
// constructor
|
||||
Transformable::Transformable()
|
||||
: agg::trans_affine()
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
Transformable::Transformable(const Transformable& other)
|
||||
: agg::trans_affine(other)
|
||||
{
|
||||
}
|
||||
|
||||
// constructor
|
||||
Transformable::Transformable(const BMessage* archive)
|
||||
: agg::trans_affine()
|
||||
{
|
||||
if (archive) {
|
||||
double storage[6];
|
||||
status_t ret = B_OK;
|
||||
for (int32 i = 0; i < 6; i++) {
|
||||
ret = archive->FindDouble("affine matrix", i, &storage[i]);
|
||||
if (ret < B_OK)
|
||||
break;
|
||||
}
|
||||
if (ret >= B_OK)
|
||||
load_from(storage);
|
||||
}
|
||||
}
|
||||
|
||||
// destructor
|
||||
Transformable::~Transformable()
|
||||
{
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
Transformable::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t ret = BArchivable::Archive(into, deep);
|
||||
if (ret >= B_OK) {
|
||||
double storage[6];
|
||||
store_to(storage);
|
||||
for (int32 i = 0; i < 6; i++) {
|
||||
ret = into->AddDouble("affine matrix", storage[i]);
|
||||
if (ret < B_OK)
|
||||
break;
|
||||
}
|
||||
// finish off
|
||||
if (ret >= B_OK)
|
||||
ret = into->AddString("class", "Transformable");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// StoreTo
|
||||
void
|
||||
Transformable::StoreTo(double matrix[6]) const
|
||||
{
|
||||
store_to(matrix);
|
||||
}
|
||||
|
||||
// LoadFrom
|
||||
void
|
||||
Transformable::LoadFrom(double matrix[6])
|
||||
{
|
||||
// before calling the potentially heavy TransformationChanged()
|
||||
// hook function, we make sure that it is actually true
|
||||
Transformable t;
|
||||
t.load_from(matrix);
|
||||
if (*this != t) {
|
||||
load_from(matrix);
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// SetTransformable
|
||||
void
|
||||
Transformable::SetTransformable(const Transformable& other)
|
||||
{
|
||||
if (*this != other) {
|
||||
*this = other;
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// operator=
|
||||
Transformable&
|
||||
Transformable::operator=(const Transformable& other)
|
||||
{
|
||||
if (other != *this) {
|
||||
reset();
|
||||
multiply(other);
|
||||
TransformationChanged();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Multiply
|
||||
Transformable&
|
||||
Transformable::Multiply(const Transformable& other)
|
||||
{
|
||||
if (!other.IsIdentity()) {
|
||||
multiply(other);
|
||||
TransformationChanged();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reset
|
||||
void
|
||||
Transformable::Reset()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// IsIdentity
|
||||
bool
|
||||
Transformable::IsIdentity() const
|
||||
{
|
||||
double m[6];
|
||||
store_to(m);
|
||||
if (m[0] == 1.0 &&
|
||||
m[1] == 0.0 &&
|
||||
m[2] == 0.0 &&
|
||||
m[3] == 1.0 &&
|
||||
m[4] == 0.0 &&
|
||||
m[5] == 0.0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// operator==
|
||||
bool
|
||||
Transformable::operator==(const Transformable& other) const
|
||||
{
|
||||
double m1[6];
|
||||
other.store_to(m1);
|
||||
double m2[6];
|
||||
store_to(m2);
|
||||
if (m1[0] == m2[0] &&
|
||||
m1[1] == m2[1] &&
|
||||
m1[2] == m2[2] &&
|
||||
m1[3] == m2[3] &&
|
||||
m1[4] == m2[4] &&
|
||||
m1[5] == m2[5])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// operator!=
|
||||
bool
|
||||
Transformable::operator!=(const Transformable& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Transform
|
||||
void
|
||||
Transformable::Transform(double* x, double* y) const
|
||||
{
|
||||
transform(x, y);
|
||||
}
|
||||
|
||||
// Transform
|
||||
void
|
||||
Transformable::Transform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform
|
||||
BPoint
|
||||
Transformable::Transform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
Transform(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
void
|
||||
Transformable::InverseTransform(double* x, double* y) const
|
||||
{
|
||||
inverse_transform(x, y);
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
void
|
||||
Transformable::InverseTransform(BPoint* point) const
|
||||
{
|
||||
if (point) {
|
||||
double x = point->x;
|
||||
double y = point->y;
|
||||
|
||||
inverse_transform(&x, &y);
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
// InverseTransform
|
||||
BPoint
|
||||
Transformable::InverseTransform(const BPoint& point) const
|
||||
{
|
||||
BPoint p(point);
|
||||
InverseTransform(&p);
|
||||
return p;
|
||||
}
|
||||
|
||||
// TransformBounds
|
||||
BRect
|
||||
Transformable::TransformBounds(BRect bounds) const
|
||||
{
|
||||
if (bounds.IsValid()) {
|
||||
BPoint lt(bounds.left, bounds.top);
|
||||
BPoint rt(bounds.right, bounds.top);
|
||||
BPoint lb(bounds.left, bounds.bottom);
|
||||
BPoint rb(bounds.right, bounds.bottom);
|
||||
|
||||
Transform(<);
|
||||
Transform(&rt);
|
||||
Transform(&lb);
|
||||
Transform(&rb);
|
||||
|
||||
return BRect(floorf(min4(lt.x, rt.x, lb.x, rb.x)),
|
||||
floorf(min4(lt.y, rt.y, lb.y, rb.y)),
|
||||
ceilf(max4(lt.x, rt.x, lb.x, rb.x)),
|
||||
ceilf(max4(lt.y, rt.y, lb.y, rb.y)));
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
// TranslateBy
|
||||
void
|
||||
Transformable::TranslateBy(BPoint offset)
|
||||
{
|
||||
if (offset.x != 0.0 || offset.y != 0.0) {
|
||||
multiply(agg::trans_affine_translation(offset.x, offset.y));
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// RotateBy
|
||||
void
|
||||
Transformable::RotateBy(BPoint origin, double degrees)
|
||||
{
|
||||
if (degrees != 0.0) {
|
||||
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||
multiply(agg::trans_affine_rotation(degrees * (PI / 180.0)));
|
||||
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// ScaleBy
|
||||
void
|
||||
Transformable::ScaleBy(BPoint origin, double xScale, double yScale)
|
||||
{
|
||||
if (xScale != 1.0 || yScale != 1.0) {
|
||||
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||
multiply(agg::trans_affine_scaling(xScale, yScale));
|
||||
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// ShearBy
|
||||
void
|
||||
Transformable::ShearBy(BPoint origin, double xShear, double yShear)
|
||||
{
|
||||
if (xShear != 0.0 || yShear != 0.0) {
|
||||
multiply(agg::trans_affine_translation(-origin.x, -origin.y));
|
||||
multiply(agg::trans_affine_skewing(xShear, yShear));
|
||||
multiply(agg::trans_affine_translation(origin.x, origin.y));
|
||||
TransformationChanged();
|
||||
}
|
||||
}
|
59
src/servers/app/server/Painter/Transformable.h
Normal file
59
src/servers/app/server/Painter/Transformable.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Transformable.h
|
||||
|
||||
#ifndef TRANSFORMABLE_H
|
||||
#define TRANSFORMABLE_H
|
||||
|
||||
#include <Archivable.h>
|
||||
#include <Rect.h>
|
||||
|
||||
#include <agg_trans_affine.h>
|
||||
|
||||
class Transformable : public BArchivable,
|
||||
public agg::trans_affine {
|
||||
public:
|
||||
Transformable();
|
||||
Transformable(const Transformable& other);
|
||||
Transformable(const BMessage* archive);
|
||||
virtual ~Transformable();
|
||||
|
||||
// the BArchivable protocol
|
||||
// stores matrix directly to message, deep is ignored
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
|
||||
void StoreTo(double matrix[6]) const;
|
||||
void LoadFrom(double matrix[6]);
|
||||
|
||||
// set to or combine with other matrix
|
||||
void SetTransformable(const Transformable& other);
|
||||
Transformable& operator=(const Transformable& other);
|
||||
Transformable& Multiply(const Transformable& other);
|
||||
void Reset();
|
||||
|
||||
bool IsIdentity() const;
|
||||
bool operator==(const Transformable& other) const;
|
||||
bool operator!=(const Transformable& other) const;
|
||||
|
||||
// transforms coordiantes
|
||||
void Transform(double* x, double* y) const;
|
||||
void Transform(BPoint* point) const;
|
||||
BPoint Transform(const BPoint& point) const;
|
||||
|
||||
void InverseTransform(double* x, double* y) const;
|
||||
void InverseTransform(BPoint* point) const;
|
||||
BPoint InverseTransform(const BPoint& point) const;
|
||||
|
||||
// transforms the rectangle "bounds" and
|
||||
// returns the *bounding box* of that
|
||||
BRect TransformBounds(BRect bounds) const;
|
||||
|
||||
// some convenience functions
|
||||
virtual void TranslateBy(BPoint offset);
|
||||
virtual void RotateBy(BPoint origin, double degrees);
|
||||
virtual void ScaleBy(BPoint origin, double xScale, double yScale);
|
||||
virtual void ShearBy(BPoint origin, double xShear, double yShear);
|
||||
|
||||
virtual void TransformationChanged() {}
|
||||
};
|
||||
|
||||
#endif // TRANSFORMABLE_H
|
||||
|
48
src/servers/app/server/Painter/defines.h
Normal file
48
src/servers/app/server/Painter/defines.h
Normal file
@ -0,0 +1,48 @@
|
||||
// agg_renderer_types.h
|
||||
|
||||
#ifndef DEFINES_H
|
||||
#define DEFINES_H
|
||||
|
||||
#include <agg_rasterizer_outline.h>
|
||||
#include <agg_rasterizer_outline_aa.h>
|
||||
#include <agg_rasterizer_scanline_aa.h>
|
||||
#include <agg_renderer_mclip.h>
|
||||
#include <agg_renderer_outline_aa.h>
|
||||
#include <agg_renderer_primitives.h>
|
||||
#include <agg_renderer_scanline.h>
|
||||
#include <agg_scanline_bin.h>
|
||||
#include <agg_scanline_p.h>
|
||||
//#include <agg_scanline_u.h>
|
||||
#include <agg_rendering_buffer.h>
|
||||
|
||||
#include "forwarding_pixfmt.h"
|
||||
|
||||
#define ALIASED_DRAWING 0
|
||||
|
||||
// typedef agg::pixfmt_bgra32 pixfmt;
|
||||
typedef agg::forwarding_pixel_format<agg::order_bgra32> pixfmt;
|
||||
typedef agg::renderer_mclip<pixfmt> renderer_base;
|
||||
|
||||
#if ALIASED_DRAWING
|
||||
typedef agg::renderer_primitives<renderer_base> outline_renderer_type;
|
||||
typedef agg::rasterizer_outline<outline_renderer_type> outline_rasterizer_type;
|
||||
|
||||
typedef agg::scanline_bin scanline_type;
|
||||
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
||||
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_type;
|
||||
#else
|
||||
typedef agg::renderer_outline_aa<renderer_base> outline_renderer_type;
|
||||
typedef agg::rasterizer_outline_aa<outline_renderer_type> outline_rasterizer_type;
|
||||
|
||||
typedef agg::scanline_p8 scanline_type;
|
||||
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
|
||||
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_type;
|
||||
#endif
|
||||
|
||||
typedef agg::renderer_scanline_aa_solid<renderer_base> font_renderer_solid_type;
|
||||
typedef agg::renderer_scanline_bin_solid<renderer_base> font_renderer_bin_type;
|
||||
|
||||
|
||||
#endif // DEFINES_H
|
||||
|
||||
|
107
src/servers/app/server/Painter/drawing_modes/DrawingMode.h
Normal file
107
src/servers/app/server/Painter/drawing_modes/DrawingMode.h
Normal file
@ -0,0 +1,107 @@
|
||||
// DrawingMode.h
|
||||
|
||||
#ifndef DRAWING_MODE_H
|
||||
#define DRAWING_MODE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <agg_basics.h>
|
||||
#include <agg_color_rgba8.h>
|
||||
#include <agg_rendering_buffer.h>
|
||||
|
||||
class PatternHandler;
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================DrawingMode
|
||||
class DrawingMode
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
DrawingMode()
|
||||
: m_rbuf(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_rendering_buffer(rendering_buffer* rbuf)
|
||||
{
|
||||
m_rbuf = rbuf;
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
void set_pattern_handler(const PatternHandler* handler)
|
||||
{
|
||||
fPatternHandler = handler;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingMode::blend_pixel()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingMode::blend_hline()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingMode::blend_vline()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//################################
|
||||
printf("DrawingMode::blend_solid_hspan()\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//################################
|
||||
printf("DrawingMode::blend_solid_vspan()\n");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingMode::blend_color_hspan()\n");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingMode::blend_color_vspan()\n");
|
||||
}
|
||||
|
||||
protected:
|
||||
rendering_buffer* m_rbuf;
|
||||
const PatternHandler* fPatternHandler;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DRAWING_MODE_H
|
||||
|
254
src/servers/app/server/Painter/drawing_modes/DrawingModeCopy.h
Normal file
254
src/servers/app/server/Painter/drawing_modes/DrawingModeCopy.h
Normal file
@ -0,0 +1,254 @@
|
||||
// DrawingModeCopy.h
|
||||
|
||||
#ifndef DRAWING_MODE_COPY_H
|
||||
#define DRAWING_MODE_COPY_H
|
||||
|
||||
#include "DrawingMode.h"
|
||||
#include "PatternHandler.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================DrawingModeCopy
|
||||
template<class Order>
|
||||
class DrawingModeCopy : public DrawingMode
|
||||
{
|
||||
public:
|
||||
typedef Order order_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
DrawingModeCopy()
|
||||
: DrawingMode()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeCopy::blend_pixel()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(cover) * int(c.a);
|
||||
int alpha = int(cover) * int(color.alpha);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeCopy::blend_hline()\n");
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingModeCopy::blend_vline()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeCopy::blend_solid_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(*covers++) * c.a;
|
||||
int alpha = int(*covers++) * color.alpha;
|
||||
//int alpha = int(*covers++);
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
/*if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}*/
|
||||
}
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeCopy::blend_solid_vspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(*covers++) * c.a;
|
||||
int alpha = int(*covers++) * color.alpha;
|
||||
//int alpha = int(*covers++);
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
/*if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}*/
|
||||
}
|
||||
p += m_rbuf->stride();
|
||||
y++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingModeCopy::blend_color_hspan()\n");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingModeCopy::blend_color_vspan()\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef DrawingModeCopy<order_rgba32> DrawingModeRGBA32Copy; //----DrawingModeRGBA32Copy
|
||||
typedef DrawingModeCopy<order_argb32> DrawingModeARGB32Copy; //----DrawingModeARGB32Copy
|
||||
typedef DrawingModeCopy<order_abgr32> DrawingModeABGR32Copy; //----DrawingModeABGR32Copy
|
||||
typedef DrawingModeCopy<order_bgra32> DrawingModeBGRA32Copy; //----DrawingModeBGRA32Copy
|
||||
}
|
||||
|
||||
#endif // DRAWING_MODE_COPY_H
|
||||
|
@ -0,0 +1,29 @@
|
||||
// DrawingModeFactory.h
|
||||
|
||||
|
||||
#include "DrawingModeCopy.h"
|
||||
#include "DrawingModeInvert.h"
|
||||
#include "DrawingModeOver.h"
|
||||
|
||||
#include "DrawingModeFactory.h"
|
||||
|
||||
// DrawingModeFor
|
||||
agg::DrawingMode*
|
||||
DrawingModeFactory::DrawingModeFor(drawing_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case B_OP_INVERT:
|
||||
return new agg::DrawingModeBGRA32Invert();
|
||||
break;
|
||||
case B_OP_COPY:
|
||||
return new agg::DrawingModeBGRA32Copy();
|
||||
break;
|
||||
case B_OP_OVER:
|
||||
return new agg::DrawingModeBGRA32Over();
|
||||
break;
|
||||
|
||||
default:
|
||||
return new agg::DrawingModeBGRA32Copy();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
// DrawingModeFactory.h
|
||||
|
||||
#ifndef DRAWING_MODE_FACTORY_H
|
||||
#define DRAWING_MODE_FACTORY_H
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
#include "DrawingMode.h"
|
||||
|
||||
class DrawingModeFactory {
|
||||
public:
|
||||
DrawingModeFactory() {}
|
||||
virtual ~DrawingModeFactory() {}
|
||||
|
||||
static agg::DrawingMode* DrawingModeFor(drawing_mode mode);
|
||||
};
|
||||
|
||||
#endif // DRAWING_MODE_FACTORY_H
|
||||
|
264
src/servers/app/server/Painter/drawing_modes/DrawingModeInvert.h
Normal file
264
src/servers/app/server/Painter/drawing_modes/DrawingModeInvert.h
Normal file
@ -0,0 +1,264 @@
|
||||
// DrawingModeInvert.h
|
||||
|
||||
#ifndef DRAWING_MODE_INVERT_H
|
||||
#define DRAWING_MODE_INVERT_H
|
||||
|
||||
#include "DrawingMode.h"
|
||||
|
||||
#define BINARY 1
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================DrawingModeInvert
|
||||
template<class Order>
|
||||
class DrawingModeInvert : public DrawingMode
|
||||
{
|
||||
public:
|
||||
typedef Order order_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
DrawingModeInvert()
|
||||
: DrawingMode()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeInvert::blend_pixel()\n");
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
#if BINARY
|
||||
int alpha = int(cover);
|
||||
if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
#else
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)(((((255 - r) - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)(((((255 - g) - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)(((((255 - b) - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeInvert::blend_hline()\n");
|
||||
#if BINARY
|
||||
if (cover > 127) {
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
#else
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)(((((255 - r) - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)(((((255 - g) - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)(((((255 - b) - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
x++;
|
||||
p += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingModeInvert::blend_vline()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeInvert::blend_solid_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
#if BINARY
|
||||
int alpha = int(*covers);
|
||||
if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
#else
|
||||
int alpha = int(*covers) * c.a;
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)(((((255 - r) - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)(((((255 - g) - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)(((((255 - b) - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
covers++;
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeInvert::blend_solid_vspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
#if BINARY
|
||||
int alpha = int(*covers);
|
||||
if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
#else
|
||||
int alpha = int(*covers) * c.a;
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = 255 - p[Order::R];
|
||||
p[Order::G] = 255 - p[Order::G];
|
||||
p[Order::B] = 255 - p[Order::B];
|
||||
// p[Order::A] = 255 - p[Order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)(((((255 - r) - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)(((((255 - g) - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)(((((255 - b) - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
covers++;
|
||||
p += m_rbuf->stride();
|
||||
y++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingModeInvert::blend_color_hspan()\n");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingModeInvert::blend_color_vspan()\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef DrawingModeInvert<order_rgba32> DrawingModeRGBA32Invert; //----DrawingModeRGBA32Invert
|
||||
typedef DrawingModeInvert<order_argb32> DrawingModeARGB32Invert; //----DrawingModeARGB32Invert
|
||||
typedef DrawingModeInvert<order_abgr32> DrawingModeABGR32Invert; //----DrawingModeABGR32Invert
|
||||
typedef DrawingModeInvert<order_bgra32> DrawingModeBGRA32Invert; //----DrawingModeBGRA32Invert
|
||||
}
|
||||
|
||||
#endif // DRAWING_MODE_INVERT_H
|
||||
|
277
src/servers/app/server/Painter/drawing_modes/DrawingModeOver.h
Normal file
277
src/servers/app/server/Painter/drawing_modes/DrawingModeOver.h
Normal file
@ -0,0 +1,277 @@
|
||||
// DrawingModeOver.h
|
||||
|
||||
#ifndef DRAWING_MODE_OVER_H
|
||||
#define DRAWING_MODE_OVER_H
|
||||
|
||||
#include "DrawingMode.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//====================================================DrawingModeOver
|
||||
template<class Order>
|
||||
class DrawingModeOver : public DrawingMode
|
||||
{
|
||||
public:
|
||||
typedef Order order_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
DrawingModeOver()
|
||||
: DrawingMode()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeOver::blend_pixel()\n");
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(cover) * int(c.a);
|
||||
int alpha = int(cover) * int(color.alpha);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("DrawingModeOver::blend_hline()\n");
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y))
|
||||
*p32 = v;
|
||||
p32++;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
x++;
|
||||
p += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("DrawingModeOver::blend_vline()\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeOver::blend_solid_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(*covers++) * c.a;
|
||||
int alpha = int(*covers) * color.alpha;
|
||||
//int alpha = int(*covers++);
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
covers++;
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("DrawingModeOver::blend_solid_vspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
if (fPatternHandler->IsHighColor(x, y)) {
|
||||
rgb_color color = fPatternHandler->ColorAt(x, y);
|
||||
// int alpha = int(*covers++) * c.a;
|
||||
int alpha = int(*covers) * color.alpha;
|
||||
//int alpha = int(*covers++);
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
// p[Order::R] = (int8u)c.r;
|
||||
// p[Order::G] = (int8u)c.g;
|
||||
// p[Order::B] = (int8u)c.b;
|
||||
// p[Order::A] = (int8u)c.a;
|
||||
p[Order::R] = color.red;
|
||||
p[Order::G] = color.green;
|
||||
p[Order::B] = color.blue;
|
||||
p[Order::A] = color.alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
// p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
// p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
// p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
// p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p[Order::R] = (int8u)((((color.red - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((color.green - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((color.blue - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
};
|
||||
covers++;
|
||||
p += m_rbuf->stride();
|
||||
y++;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
//printf("DrawingModeOver::blend_color_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)colors->r;
|
||||
p[Order::G] = (int8u)colors->g;
|
||||
p[Order::B] = (int8u)colors->b;
|
||||
p[Order::A] = (int8u)colors->a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
virtual void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("DrawingModeOver::blend_color_vspan()\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef DrawingModeOver<order_rgba32> DrawingModeRGBA32Over; //----DrawingModeRGBA32Over
|
||||
typedef DrawingModeOver<order_argb32> DrawingModeARGB32Over; //----DrawingModeARGB32Over
|
||||
typedef DrawingModeOver<order_abgr32> DrawingModeABGR32Over; //----DrawingModeABGR32Over
|
||||
typedef DrawingModeOver<order_bgra32> DrawingModeBGRA32Over; //----DrawingModeBGRA32Over
|
||||
}
|
||||
|
||||
#endif // DRAWING_MODE_OVER_H
|
||||
|
214
src/servers/app/server/Painter/drawing_modes/PatternHandler.cpp
Normal file
214
src/servers/app/server/Painter/drawing_modes/PatternHandler.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: PatternHandler.cpp
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Stephan Aßmus <superstippi@gmx.de>
|
||||
// Description: Class for easy calculation and use of patterns
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#include <Point.h>
|
||||
#include "PatternHandler.h"
|
||||
|
||||
const Pattern kSolidHigh(0xFFFFFFFFFFFFFFFFLL);
|
||||
const Pattern kSolidLow((uint64)0);
|
||||
const Pattern kMixedColors(0xAAAAAAAAAAAAAAAALL);
|
||||
|
||||
const rgb_color kBlack = (rgb_color){ 0, 0, 0, 255 };
|
||||
const rgb_color kWhite = (rgb_color){ 255, 255, 255, 255 };
|
||||
|
||||
/*!
|
||||
\brief Void constructor
|
||||
|
||||
The pattern is set to B_SOLID_HIGH, high color is set to black, and
|
||||
low color is set to white.
|
||||
*/
|
||||
PatternHandler::PatternHandler(void)
|
||||
: fPattern(kSolidHigh),
|
||||
fHighColor(kBlack),
|
||||
fLowColor(kWhite)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructor initializes to given pattern
|
||||
\param pat Pattern to use.
|
||||
|
||||
This initializes to the given pattern or B_SOLID_HIGH if the pattern
|
||||
is NULL. High color is set to black, and low color is set to white.
|
||||
*/
|
||||
PatternHandler::PatternHandler(const int8* pat)
|
||||
: fPattern(pat ? Pattern(pat) : Pattern(kSolidHigh)),
|
||||
fHighColor(kBlack),
|
||||
fLowColor(kWhite)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructor initializes to given pattern
|
||||
\param pat Pattern to use.
|
||||
|
||||
This initializes to the given pattern or B_SOLID_HIGH if the pattern
|
||||
is NULL. High color is set to black, and low color is set to white.
|
||||
*/
|
||||
PatternHandler::PatternHandler(const uint64& pat)
|
||||
: fPattern(pat),
|
||||
fHighColor(kBlack),
|
||||
fLowColor(kWhite)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructor initializes to given pattern
|
||||
\param pat Pattern to use.
|
||||
|
||||
This initializes to the given Pattern.
|
||||
High color is set to black, and low color is set to white.
|
||||
*/
|
||||
PatternHandler::PatternHandler(const Pattern& pat)
|
||||
: fPattern(pat),
|
||||
fHighColor(kBlack),
|
||||
fLowColor(kWhite)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructor initializes to given PatternHandler
|
||||
\param other PatternHandler to copy.
|
||||
|
||||
Copy constructor.
|
||||
*/
|
||||
PatternHandler::PatternHandler(const PatternHandler& other)
|
||||
: fPattern(other.fPattern),
|
||||
fHighColor(other.fHighColor),
|
||||
fLowColor(other.fLowColor)
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor does nothing
|
||||
PatternHandler::~PatternHandler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the pattern for the handler to the one given
|
||||
\param pat Pattern to use.
|
||||
|
||||
This initializes to the given pattern or B_SOLID_HIGH if the pattern
|
||||
is NULL.
|
||||
*/
|
||||
void PatternHandler::SetPattern(const int8* pat)
|
||||
{
|
||||
if (pat)
|
||||
fPattern.Set(pat);
|
||||
else
|
||||
fPattern = kSolidHigh;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the pattern for the handler to the one given
|
||||
\param pat Pattern to use.
|
||||
*/
|
||||
void PatternHandler::SetPattern(const uint64& pat)
|
||||
{
|
||||
fPattern = pat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the pattern for the handler to the one given
|
||||
\param pat Pattern to use.
|
||||
*/
|
||||
void PatternHandler::SetPattern(const Pattern& pat)
|
||||
{
|
||||
fPattern = pat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Sets the pattern for the handler to the one given
|
||||
\param pat R5 style pattern to use.
|
||||
*/
|
||||
void PatternHandler::SetPattern(const pattern& pat)
|
||||
{
|
||||
fPattern = pat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the colors for the pattern to use
|
||||
\param high High color for the handler
|
||||
\param low Low color for the handler
|
||||
*/
|
||||
void PatternHandler::SetColors(const rgb_color& high, const rgb_color& low)
|
||||
{
|
||||
fHighColor = high;
|
||||
fLowColor = low;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the high color for the pattern to use
|
||||
\param color High color for the handler
|
||||
*/
|
||||
void PatternHandler::SetHighColor(const rgb_color& color)
|
||||
{
|
||||
fHighColor = color;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set the low color for the pattern to use
|
||||
\param color Low color for the handler
|
||||
*/
|
||||
void PatternHandler::SetLowColor(const rgb_color& color)
|
||||
{
|
||||
fLowColor = color;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Obtains the color in the pattern at the specified coordinates
|
||||
\param pt Coordinates to get the color for
|
||||
\return Color for the coordinates
|
||||
*/
|
||||
rgb_color
|
||||
PatternHandler::ColorAt(const BPoint &pt) const
|
||||
{
|
||||
return ColorAt(pt.x, pt.y);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Obtains the color in the pattern at the specified coordinates
|
||||
\param x X coordinate to get the color for
|
||||
\param y Y coordinate to get the color for
|
||||
\return Color for the coordinates
|
||||
*/
|
||||
rgb_color
|
||||
PatternHandler::ColorAt(float x, float y) const
|
||||
{
|
||||
return ColorAt(int(x), int(y));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Obtains the value of the pattern at the specified coordinates
|
||||
\param pt Coordinates to get the value for
|
||||
\return Value for the coordinates - true if high, false if low.
|
||||
*/
|
||||
bool PatternHandler::IsHighColor(const BPoint &pt) const
|
||||
{
|
||||
return IsHighColor((int)pt.x, (int)pt.y);
|
||||
}
|
||||
|
158
src/servers/app/server/Painter/drawing_modes/PatternHandler.h
Normal file
158
src/servers/app/server/Painter/drawing_modes/PatternHandler.h
Normal file
@ -0,0 +1,158 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: PatternHandler.h
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Stephan Aßmus <superstippi@gmx.de>
|
||||
// Description: Class for easy calculation and use of patterns
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef PATTERNHADLER_H
|
||||
#define PATTERNHADLER_H
|
||||
|
||||
#include <string.h>
|
||||
//#include <SupportDefs.h>
|
||||
//#include "rgb_color.h"
|
||||
#include <GraphicsDefs.h>
|
||||
|
||||
class Pattern {
|
||||
public:
|
||||
|
||||
Pattern(void) {}
|
||||
|
||||
Pattern(const uint64& p)
|
||||
{ fPattern.type64 = p; }
|
||||
|
||||
Pattern(const int8* p)
|
||||
{ fPattern.type64 = *((const uint64*)p); }
|
||||
|
||||
Pattern(const Pattern& src)
|
||||
{ fPattern.type64 = src.fPattern.type64; }
|
||||
|
||||
const int8* GetInt8(void) const
|
||||
{ return fPattern.type8; }
|
||||
|
||||
uint64 GetInt64(void) const
|
||||
{ return fPattern.type64; }
|
||||
|
||||
void Set(const int8* p)
|
||||
{ fPattern.type64 = *((const uint64*)p); }
|
||||
|
||||
void Set(const uint64& p)
|
||||
{ fPattern.type64 = p; }
|
||||
|
||||
Pattern& operator=(const Pattern& from)
|
||||
{ fPattern.type64 = from.fPattern.type64; return *this; }
|
||||
|
||||
Pattern& operator=(const int64 &from)
|
||||
{ fPattern.type64 = from; return *this; }
|
||||
|
||||
Pattern& operator=(const pattern &from)
|
||||
{ memcpy(&fPattern.type64, &from, sizeof(pattern)); return *this; }
|
||||
private:
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint64 type64;
|
||||
int8 type8[8];
|
||||
} pattern_union;
|
||||
|
||||
pattern_union fPattern;
|
||||
};
|
||||
|
||||
extern const Pattern kSolidHigh;
|
||||
extern const Pattern kSolidLow;
|
||||
extern const Pattern kMixedColors;
|
||||
|
||||
/*!
|
||||
\brief Class for easy calculation and use of patterns
|
||||
|
||||
PatternHandlers are designed specifically for DisplayDriver subclasses.
|
||||
Pattern support can be easily added by setting the pattern to use via
|
||||
SetTarget, and then merely retrieving the value for the coordinates
|
||||
specified.
|
||||
*/
|
||||
class PatternHandler {
|
||||
public:
|
||||
PatternHandler(void);
|
||||
PatternHandler(const int8* p);
|
||||
PatternHandler(const uint64& p);
|
||||
PatternHandler(const Pattern& p);
|
||||
PatternHandler(const PatternHandler& other);
|
||||
virtual ~PatternHandler(void);
|
||||
|
||||
void SetPattern(const int8* p);
|
||||
void SetPattern(const uint64& p);
|
||||
void SetPattern(const Pattern& p);
|
||||
void SetPattern(const pattern& p);
|
||||
void SetColors(const rgb_color& high, const rgb_color& low);
|
||||
void SetHighColor(const rgb_color& color);
|
||||
void SetLowColor(const rgb_color& color);
|
||||
|
||||
rgb_color HighColor() const
|
||||
{ return fHighColor; }
|
||||
rgb_color LowColor() const
|
||||
{ return fLowColor; }
|
||||
|
||||
rgb_color ColorAt(const BPoint& pt) const;
|
||||
rgb_color ColorAt(float x, float y) const;
|
||||
inline rgb_color ColorAt(int x, int y) const;
|
||||
|
||||
bool IsHighColor(const BPoint& pt) const;
|
||||
inline bool IsHighColor(int x, int y) const;
|
||||
|
||||
const pattern* GetR5Pattern(void) const
|
||||
{ return (const pattern*)fPattern.GetInt8(); }
|
||||
private:
|
||||
Pattern fPattern;
|
||||
rgb_color fHighColor;
|
||||
rgb_color fLowColor;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Obtains the color in the pattern at the specified coordinates
|
||||
\param x X coordinate to get the color for
|
||||
\param y Y coordinate to get the color for
|
||||
\return Color for the coordinates
|
||||
*/
|
||||
inline rgb_color
|
||||
PatternHandler::ColorAt(int x, int y) const
|
||||
{
|
||||
return IsHighColor(x, y) ? fHighColor : fLowColor;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Obtains the value of the pattern at the specified coordinates
|
||||
\param pt Coordinates to get the value for
|
||||
\return Value for the coordinates - true if high, false if low.
|
||||
*/
|
||||
inline bool
|
||||
PatternHandler::IsHighColor(int x, int y) const
|
||||
{
|
||||
// TODO: Does this work correctly for
|
||||
// negative coordinates?!?
|
||||
const int8* ptr = fPattern.GetInt8();
|
||||
int32 value = ptr[y % 8] & (1 << (7 - (x % 8)) );
|
||||
|
||||
return (value == 0) ? false : true;
|
||||
}
|
||||
|
||||
#endif
|
461
src/servers/app/server/Painter/drawing_modes/_for_reference_.h
Normal file
461
src/servers/app/server/Painter/drawing_modes/_for_reference_.h
Normal file
@ -0,0 +1,461 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PIXFMT_RGBA32_OVER_H
|
||||
#define PIXFMT_RGBA32_OVER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <agg_basics.h>
|
||||
#include <agg_color_rgba8.h>
|
||||
#include <agg_rendering_buffer.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//====================================================pixel_formats_rgba32_over
|
||||
template<class Order> class pixel_formats_rgba32_over
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
pixel_formats_rgba32_over(rendering_buffer& rb)
|
||||
: m_rbuf(&rb)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return m_rbuf->width(); }
|
||||
unsigned height() const { return m_rbuf->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
printf("pixel()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
printf("span()\n");
|
||||
return row_data(x, width() - 1, m_rbuf->row(y) + (x << 2));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
printf("copy_pixel()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
printf("blend_pixel()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||
{
|
||||
printf("copy_hline()\n");
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||
do
|
||||
{
|
||||
*p32++ = v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||
{
|
||||
printf("copy_vline()\n");
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
*(int32u*)p = v;
|
||||
p += m_rbuf->stride();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("blend_hline()\n");
|
||||
int alpha = int(cover) * int(c.a);
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int32u* p32 = (int32u*)(m_rbuf->row(y)) + x;
|
||||
do
|
||||
{
|
||||
*p32++ = v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("blend_vline()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
int alpha = int(cover) * c.a;
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
do
|
||||
{
|
||||
*(int32u*)p = v;
|
||||
p += m_rbuf->stride();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
p += m_rbuf->stride();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
printf("copy_from()\n");
|
||||
memmove(m_rbuf->row(ydst) + xdst * 4,
|
||||
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
printf("blend_from()\n");
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
int8u* pdst = m_rbuf->row(ydst) + (xdst << 2);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
int alpha = psrc[src_order::A];
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = pdst[Order::R];
|
||||
int g = pdst[Order::G];
|
||||
int b = pdst[Order::B];
|
||||
int a = pdst[Order::A];
|
||||
pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("blend_solid_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int alpha = int(*covers++) * c.a;
|
||||
//int alpha = int(*covers++);
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
/*if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}*/
|
||||
}
|
||||
p += 4;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("blend_solid_vspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int alpha = int(*covers++) * c.a;
|
||||
//int alpha = int(*covers++);
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((c.r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((c.g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((c.b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
/*if(alpha > 127)
|
||||
{
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}*/
|
||||
}
|
||||
p += m_rbuf->stride();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("blend_color_hspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)colors->r;
|
||||
p[Order::G] = (int8u)colors->g;
|
||||
p[Order::B] = (int8u)colors->b;
|
||||
p[Order::A] = (int8u)colors->a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
p += 4;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("blend_color_vspan()\n");
|
||||
int8u* p = m_rbuf->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
int alpha = colors->a * (covers ? int(*covers++) : int(cover));
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255*255)
|
||||
{
|
||||
p[Order::R] = (int8u)colors->r;
|
||||
p[Order::G] = (int8u)colors->g;
|
||||
p[Order::B] = (int8u)colors->b;
|
||||
p[Order::A] = (int8u)colors->a;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = p[Order::R];
|
||||
int g = p[Order::G];
|
||||
int b = p[Order::B];
|
||||
int a = p[Order::A];
|
||||
p[Order::R] = (int8u)((((colors->r - r) * alpha) + (r << 16)) >> 16);
|
||||
p[Order::G] = (int8u)((((colors->g - g) * alpha) + (g << 16)) >> 16);
|
||||
p[Order::B] = (int8u)((((colors->b - b) * alpha) + (b << 16)) >> 16);
|
||||
p[Order::A] = (int8u)(((alpha + (a << 8)) - ((alpha * a) >> 8)) >> 8);
|
||||
}
|
||||
}
|
||||
p += m_rbuf->stride();
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
private:
|
||||
rendering_buffer* m_rbuf;
|
||||
};
|
||||
|
||||
typedef pixel_formats_rgba32_over<order_rgba32> pixfmt_rgba32_over; //----pixfmt_rgba32_over
|
||||
typedef pixel_formats_rgba32_over<order_argb32> pixfmt_argb32_over; //----pixfmt_argb32_over
|
||||
typedef pixel_formats_rgba32_over<order_abgr32> pixfmt_abgr32_over; //----pixfmt_abgr32_over
|
||||
typedef pixel_formats_rgba32_over<order_bgra32> pixfmt_bgra32_over; //----pixfmt_bgra32_over
|
||||
}
|
||||
|
||||
#endif // PIXFMT_RGBA32_OVER_H
|
||||
|
271
src/servers/app/server/Painter/drawing_modes/forwarding_pixfmt.h
Normal file
271
src/servers/app/server/Painter/drawing_modes/forwarding_pixfmt.h
Normal file
@ -0,0 +1,271 @@
|
||||
// forwarding_pixfmt.h
|
||||
|
||||
#ifndef FORWARDING_PIXFMT_H
|
||||
#define FORWARDING_PIXFMT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <agg_basics.h>
|
||||
#include <agg_color_rgba8.h>
|
||||
#include <agg_rendering_buffer.h>
|
||||
|
||||
#include "DrawingMode.h"
|
||||
#include "PatternHandler.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//====================================================forwarding_pixel_format
|
||||
template<class Order>
|
||||
class forwarding_pixel_format
|
||||
{
|
||||
public:
|
||||
typedef rgba8 color_type;
|
||||
typedef Order order_type;
|
||||
typedef rendering_buffer::row_data row_data;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
forwarding_pixel_format(rendering_buffer& rb, const PatternHandler* handler)
|
||||
: fBuffer(&rb),
|
||||
fDrawingMode(NULL),
|
||||
fPatternHandler(handler)
|
||||
{
|
||||
}
|
||||
|
||||
~forwarding_pixel_format()
|
||||
{
|
||||
delete fDrawingMode;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_drawing_mode(DrawingMode* mode)
|
||||
{
|
||||
//printf("forwarding_pixel_format::set_drawing_mode()\n");
|
||||
if (fDrawingMode != mode) {
|
||||
// delete old DrawingMode
|
||||
delete fDrawingMode;
|
||||
// attach new DrawingMode
|
||||
fDrawingMode = mode;
|
||||
if (fDrawingMode) {
|
||||
fDrawingMode->set_rendering_buffer(fBuffer);
|
||||
fDrawingMode->set_pattern_handler(fPatternHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void set_pattern(const PatternHandler* handler)
|
||||
{
|
||||
fPatternHandler = handler;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned width() const { return fBuffer->width(); }
|
||||
unsigned height() const { return fBuffer->height(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
color_type pixel(int x, int y) const
|
||||
{
|
||||
printf("forwarding_pixel_format::pixel()\n");
|
||||
int8u* p = fBuffer->row(y) + (x << 2);
|
||||
return color_type(p[Order::R], p[Order::G], p[Order::B], p[Order::A]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
row_data span(int x, int y) const
|
||||
{
|
||||
printf("forwarding_pixel_format::span()\n");
|
||||
return row_data(x, width() - 1, fBuffer->row(y) + (x << 2));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
printf("forwarding_pixel_format::copy_pixel()\n");
|
||||
int8u* p = fBuffer->row(y) + (x << 2);
|
||||
p[Order::R] = (int8u)c.r;
|
||||
p[Order::G] = (int8u)c.g;
|
||||
p[Order::B] = (int8u)c.b;
|
||||
p[Order::A] = (int8u)c.a;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_pixel(int x, int y, const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("forwarding_pixel_format::blend_pixel()\n");
|
||||
fDrawingMode->blend_pixel(x, y, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_hline(int x, int y, unsigned len, const color_type& c)
|
||||
{
|
||||
printf("forwarding_pixel_format::copy_hline()\n");
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int32u* p32 = (int32u*)(fBuffer->row(y)) + x;
|
||||
do
|
||||
{
|
||||
*p32++ = v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_vline(int x, int y, unsigned len, const color_type& c)
|
||||
{
|
||||
printf("forwarding_pixel_format::copy_vline()\n");
|
||||
int32u v;
|
||||
int8u* p8 = (int8u*)&v;
|
||||
p8[Order::R] = (int8u)c.r;
|
||||
p8[Order::G] = (int8u)c.g;
|
||||
p8[Order::B] = (int8u)c.b;
|
||||
p8[Order::A] = (int8u)c.a;
|
||||
int8u* p = fBuffer->row(y) + (x << 2);
|
||||
do
|
||||
{
|
||||
*(int32u*)p = v;
|
||||
p += fBuffer->stride();
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
//printf("forwarding_pixel_format::blend_hline()\n");
|
||||
fDrawingMode->blend_hline(x, y, len, c, cover);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y, unsigned len,
|
||||
const color_type& c, int8u cover)
|
||||
{
|
||||
printf("forwarding_pixel_format::blend_vline()\n");
|
||||
fDrawingMode->blend_vline(x, y, len, c, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_from(const rendering_buffer& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
printf("forwarding_pixel_format::copy_from()\n");
|
||||
memmove(fBuffer->row(ydst) + xdst * 4,
|
||||
(const void*)(from.row(ysrc) + xsrc * 4), len * 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from(const SrcPixelFormatRenderer& from,
|
||||
const int8u* psrc,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
printf("forwarding_pixel_format::blend_from()\n");
|
||||
typedef typename SrcPixelFormatRenderer::order_type src_order;
|
||||
|
||||
int8u* pdst = fBuffer->row(ydst) + (xdst << 2);
|
||||
int incp = 4;
|
||||
if(xdst > xsrc)
|
||||
{
|
||||
psrc += (len-1) << 2;
|
||||
pdst += (len-1) << 2;
|
||||
incp = -4;
|
||||
}
|
||||
do
|
||||
{
|
||||
int alpha = psrc[src_order::A];
|
||||
|
||||
if(alpha)
|
||||
{
|
||||
if(alpha == 255)
|
||||
{
|
||||
pdst[Order::R] = psrc[src_order::R];
|
||||
pdst[Order::G] = psrc[src_order::G];
|
||||
pdst[Order::B] = psrc[src_order::B];
|
||||
pdst[Order::A] = psrc[src_order::A];
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = pdst[Order::R];
|
||||
int g = pdst[Order::G];
|
||||
int b = pdst[Order::B];
|
||||
int a = pdst[Order::A];
|
||||
pdst[Order::R] = (int8u)((((psrc[src_order::R] - r) * alpha) + (r << 8)) >> 8);
|
||||
pdst[Order::G] = (int8u)((((psrc[src_order::G] - g) * alpha) + (g << 8)) >> 8);
|
||||
pdst[Order::B] = (int8u)((((psrc[src_order::B] - b) * alpha) + (b << 8)) >> 8);
|
||||
pdst[Order::A] = (int8u)((alpha + a) - ((alpha * a) >> 8));
|
||||
}
|
||||
}
|
||||
psrc += incp;
|
||||
pdst += incp;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("forwarding_pixel_format::blend_solid_hspan()\n");
|
||||
fDrawingMode->blend_solid_hspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y, unsigned len,
|
||||
const color_type& c, const int8u* covers)
|
||||
{
|
||||
//printf("forwarding_pixel_format::blend_solid_vspan()\n");
|
||||
fDrawingMode->blend_solid_vspan(x, y, len, c, covers);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
//printf("forwarding_pixel_format::blend_color_hspan()\n");
|
||||
fDrawingMode->blend_color_hspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y, unsigned len,
|
||||
const color_type* colors,
|
||||
const int8u* covers,
|
||||
int8u cover)
|
||||
{
|
||||
printf("forwarding_pixel_format::blend_color_vspan()\n");
|
||||
fDrawingMode->blend_color_vspan(x, y, len, colors, covers, cover);
|
||||
}
|
||||
|
||||
private:
|
||||
rendering_buffer* fBuffer;
|
||||
|
||||
DrawingMode* fDrawingMode;
|
||||
const PatternHandler* fPatternHandler;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FORWARDING_PIXFMT_H
|
||||
|
440
src/servers/app/server/Painter/font_support/AGGTextRenderer.cpp
Normal file
440
src/servers/app/server/Painter/font_support/AGGTextRenderer.cpp
Normal file
@ -0,0 +1,440 @@
|
||||
// AGGTextRenderer.cpp
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <Entry.h>
|
||||
#include <Message.h>
|
||||
#include <UTF8.h>
|
||||
|
||||
#include <agg_basics.h>
|
||||
#include <agg_bounding_rect.h>
|
||||
#include <agg_conv_segmentator.h>
|
||||
#include <agg_conv_transform.h>
|
||||
//#include <agg_rendering_buffer.h>
|
||||
#include <agg_scanline_u.h>
|
||||
#include <agg_scanline_bin.h>
|
||||
//#include <agg_renderer_mclip.h>
|
||||
//#include <agg_renderer_scanline.h>
|
||||
//#include <agg_renderer_primitives.h>
|
||||
//#include <agg_rasterizer_scanline_aa.h>
|
||||
//#include <agg_pixfmt_gray8.h>
|
||||
#include <agg_trans_affine.h>
|
||||
|
||||
//#include "support.h"
|
||||
|
||||
#include "FontManager.h"
|
||||
|
||||
#include "AGGTextRenderer.h"
|
||||
|
||||
// rect_to_int
|
||||
inline void
|
||||
rect_to_int(BRect r,
|
||||
int32& left, int32& top, int32& right, int32& bottom)
|
||||
{
|
||||
left = (int32)floorf(r.left);
|
||||
top = (int32)floorf(r.top);
|
||||
right = (int32)ceilf(r.right);
|
||||
bottom = (int32)ceilf(r.bottom);
|
||||
}
|
||||
|
||||
|
||||
// constructor
|
||||
AGGTextRenderer::AGGTextRenderer()
|
||||
: TextRenderer(),
|
||||
fFontEngine(),
|
||||
fFontManager(fFontEngine),
|
||||
fCurves(fFontManager.path_adaptor()),
|
||||
fContour(fCurves)
|
||||
{
|
||||
fCurves.approximation_scale(2.0);
|
||||
fContour.auto_detect_orientation(false);
|
||||
fFontEngine.flip_y(true);
|
||||
}
|
||||
|
||||
AGGTextRenderer::AGGTextRenderer(BMessage* archive)
|
||||
: TextRenderer(archive),
|
||||
fFontEngine(),
|
||||
fFontManager(fFontEngine),
|
||||
fCurves(fFontManager.path_adaptor()),
|
||||
fContour(fCurves)
|
||||
{
|
||||
//printf("AGGTextRenderer::AGGTextRenderer(BMessage*)\n");
|
||||
fCurves.approximation_scale(2.0);
|
||||
fContour.auto_detect_orientation(false);
|
||||
fFontEngine.flip_y(true);
|
||||
|
||||
if (fFontFilePath)
|
||||
SetFont(fFontFilePath);
|
||||
}
|
||||
|
||||
// constructor
|
||||
AGGTextRenderer::AGGTextRenderer(const AGGTextRenderer& from)
|
||||
: TextRenderer(from),
|
||||
fFontEngine(),
|
||||
fFontManager(fFontEngine),
|
||||
fCurves(fFontManager.path_adaptor()),
|
||||
fContour(fCurves)
|
||||
{
|
||||
fCurves.approximation_scale(2.0);
|
||||
fContour.auto_detect_orientation(false);
|
||||
fFontEngine.flip_y(true);
|
||||
|
||||
if (fFontFilePath)
|
||||
SetFont(fFontFilePath);
|
||||
}
|
||||
|
||||
// destructor
|
||||
AGGTextRenderer::~AGGTextRenderer()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
AGGTextRenderer::SetTo(const TextRenderer* other)
|
||||
{
|
||||
const AGGTextRenderer* casted = dynamic_cast<const AGGTextRenderer*>(other);
|
||||
if (casted) {
|
||||
TextRenderer::SetTo(other);
|
||||
}
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
AGGTextRenderer::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t status = TextRenderer::Archive(into, deep);
|
||||
if (status >= B_OK) {
|
||||
status = into->AddString("class", "AGGTextRenderer");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// SetFont
|
||||
bool
|
||||
AGGTextRenderer::SetFont(const char* pathToFontFile)
|
||||
{
|
||||
if (pathToFontFile) {
|
||||
if (fFontEngine.load_font(pathToFontFile, 0, agg::glyph_ren_outline)) {
|
||||
|
||||
return TextRenderer::SetFont(pathToFontFile);
|
||||
} else {
|
||||
fprintf(stderr, "%s : is not a font file or could not be opened\n",
|
||||
pathToFontFile);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
AGGTextRenderer::Unset()
|
||||
{
|
||||
}
|
||||
|
||||
// Family
|
||||
const char*
|
||||
AGGTextRenderer::Family() const
|
||||
{
|
||||
const char* family = NULL;
|
||||
if (fFontFilePath) {
|
||||
entry_ref ref;
|
||||
if (get_ref_for_path(fFontFilePath, &ref) >= B_OK) {
|
||||
FontManager* fm = FontManager::Default();
|
||||
if (fm->Lock()) {
|
||||
family = fm->FamilyFor(&ref);
|
||||
fm->Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return family;
|
||||
}
|
||||
|
||||
// Style
|
||||
const char*
|
||||
AGGTextRenderer::Style() const
|
||||
{
|
||||
const char* style = NULL;
|
||||
if (fFontFilePath) {
|
||||
entry_ref ref;
|
||||
if (get_ref_for_path(fFontFilePath, &ref) >= B_OK) {
|
||||
FontManager* fm = FontManager::Default();
|
||||
if (fm->Lock()) {
|
||||
style = fm->StyleFor(&ref);
|
||||
fm->Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
// PostScriptName
|
||||
const char*
|
||||
AGGTextRenderer::PostScriptName() const
|
||||
{
|
||||
const char* name = NULL;
|
||||
if (fFontFilePath) {
|
||||
entry_ref ref;
|
||||
if (get_ref_for_path(fFontFilePath, &ref) >= B_OK) {
|
||||
FontManager* fm = FontManager::Default();
|
||||
if (fm->Lock()) {
|
||||
name = fm->PostScriptNameFor(&ref);
|
||||
fm->Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
// RenderString
|
||||
void
|
||||
AGGTextRenderer::RenderString(const char* string,
|
||||
font_renderer_solid_type* solidRenderer,
|
||||
font_renderer_bin_type* binRenderer,
|
||||
const Transformable& transform)
|
||||
{
|
||||
fFontEngine.hinting(fHinted);
|
||||
fFontEngine.height((int32)(fPtSize/* * 16.0*/));
|
||||
|
||||
typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type;
|
||||
// typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type;
|
||||
// typedef agg::conv_transform<conv_font_segm_type, agg::trans_affine> conv_font_trans_type;
|
||||
typedef agg::conv_transform<conv_font_curve_type, agg::trans_affine> conv_font_trans_type;
|
||||
|
||||
agg::scanline_u8 sl;
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
|
||||
|
||||
conv_font_curve_type fcurves(fFontManager.path_adaptor());
|
||||
fcurves.approximation_scale(transform.scale());
|
||||
// conv_font_segm_type fsegm(fcurves);
|
||||
// conv_font_trans_type ftrans(fsegm, transform);
|
||||
conv_font_trans_type ftrans(fcurves, transform);
|
||||
|
||||
|
||||
int32 srcLength = strlen(string);
|
||||
int32 dstLength = srcLength * 4;
|
||||
|
||||
char* buffer = new char[dstLength];
|
||||
|
||||
int32 state = 0;
|
||||
status_t ret;
|
||||
if ((ret = convert_from_utf8(B_UNICODE_CONVERSION,
|
||||
string, &srcLength,
|
||||
buffer, &dstLength,
|
||||
&state, B_SUBSTITUTE)) >= B_OK
|
||||
&& (ret = swap_data(B_INT16_TYPE, buffer, dstLength,
|
||||
B_SWAP_BENDIAN_TO_HOST)) >= B_OK) {
|
||||
|
||||
uint16* p = (uint16*)buffer;
|
||||
|
||||
double x = 0.0;
|
||||
double y0 = 0.0;
|
||||
double y = y0;
|
||||
|
||||
double advanceX = 0.0;
|
||||
double advanceY = 0.0;
|
||||
|
||||
for (int32 i = 0; i < dstLength / 2; i++) {
|
||||
|
||||
// line break
|
||||
if (*p == '\n') {
|
||||
y0 += LineOffset();
|
||||
x = 0.0;
|
||||
y = y0;
|
||||
advanceX = 0.0;
|
||||
advanceY = 0.0;
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const agg::glyph_cache* glyph = fFontManager.glyph(*p);
|
||||
|
||||
if (glyph) {
|
||||
|
||||
if (fKerning) {
|
||||
// fFontManager.add_kerning(&x, &y);
|
||||
fFontManager.add_kerning(&advanceX, &advanceY);
|
||||
}
|
||||
|
||||
x += fAdvanceScale * advanceX;
|
||||
if (advanceX > 0.0 && fAdvanceScale > 1.0)
|
||||
x += (fAdvanceScale - 1.0) * fFontEngine.height();
|
||||
y += advanceY;
|
||||
|
||||
fFontManager.init_embedded_adaptors(glyph, x, y);
|
||||
|
||||
switch(glyph->data_type) {
|
||||
case agg::glyph_data_mono:
|
||||
// binRenderer->color(agg::gray8(fOpacity));
|
||||
agg::render_scanlines(fFontManager.mono_adaptor(),
|
||||
fFontManager.mono_scanline(),
|
||||
*binRenderer);
|
||||
break;
|
||||
|
||||
case agg::glyph_data_gray8:
|
||||
// solidRenderer->color(agg::gray8(fOpacity));
|
||||
agg::render_scanlines(fFontManager.gray8_adaptor(),
|
||||
fFontManager.gray8_scanline(),
|
||||
*solidRenderer);
|
||||
break;
|
||||
|
||||
case agg::glyph_data_outline:
|
||||
ras.reset();
|
||||
if(fabs(0.0) <= 0.01) {
|
||||
// For the sake of efficiency skip the
|
||||
// contour converter if the weight is about zero.
|
||||
//-----------------------
|
||||
// ras.add_path(fCurves);
|
||||
ras.add_path(ftrans);
|
||||
} else {
|
||||
// ras.add_path(fContour);
|
||||
ras.add_path(ftrans);
|
||||
}
|
||||
if (fAntialias) {
|
||||
// solidRenderer->color(agg::gray8(fOpacity));
|
||||
agg::render_scanlines(ras, sl, *solidRenderer);
|
||||
} else {
|
||||
// binRenderer->color(agg::gray8(fOpacity));
|
||||
agg::render_scanlines(ras, sl, *binRenderer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// increment pen position
|
||||
// x += glyph->advance_x + (fAdvanceScale - 1.0) * fFontEngine.height();
|
||||
// y += glyph->advance_y;
|
||||
advanceX = fHinted ? floorf(glyph->advance_x + 0.5) : glyph->advance_x;
|
||||
advanceY = fHinted ? floorf(glyph->advance_y + 0.5) : glyph->advance_y;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "UTF8 -> Unicode conversion failed: %s\n", strerror(ret));
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Bounds
|
||||
BRect
|
||||
AGGTextRenderer::Bounds(const char* string,
|
||||
const Transformable& transform)
|
||||
{
|
||||
fFontEngine.hinting(fHinted);
|
||||
fFontEngine.height((int32)(fPtSize/* * 16.0*/));
|
||||
|
||||
BRect bounds(0.0, 0.0, -1.0, -1.0);
|
||||
|
||||
// do a UTF8 -> Unicode conversion
|
||||
if (string) {
|
||||
|
||||
int32 srcLength = strlen(string);
|
||||
if (srcLength > 0) {
|
||||
|
||||
int32 dstLength = srcLength * 4;
|
||||
|
||||
char* buffer = new char[dstLength];
|
||||
|
||||
int32 state = 0;
|
||||
status_t ret;
|
||||
if ((ret = convert_from_utf8(B_UNICODE_CONVERSION,
|
||||
string, &srcLength,
|
||||
buffer, &dstLength,
|
||||
&state, B_SUBSTITUTE)) >= B_OK
|
||||
&& (ret = swap_data(B_INT16_TYPE, buffer, dstLength,
|
||||
B_SWAP_BENDIAN_TO_HOST)) >= B_OK) {
|
||||
|
||||
uint16* p = (uint16*)buffer;
|
||||
|
||||
double x = 0.0;
|
||||
double y0 = 0.0;
|
||||
double y = y0;
|
||||
|
||||
double advanceX = 0.0;
|
||||
double advanceY = 0.0;
|
||||
|
||||
for (int32 i = 0; i < dstLength / 2; i++) {
|
||||
|
||||
// line break
|
||||
if (*p == '\n') {
|
||||
y0 +=LineOffset();
|
||||
x = 0.0;
|
||||
y = y0;
|
||||
advanceX = 0.0;
|
||||
advanceY = 0.0;
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
||||
const agg::glyph_cache* glyph = fFontManager.glyph(*p);
|
||||
|
||||
if (glyph) {
|
||||
|
||||
if (fKerning) {
|
||||
// fFontManager.add_kerning(&x, &y);
|
||||
fFontManager.add_kerning(&advanceX, &advanceY);
|
||||
}
|
||||
|
||||
x += fAdvanceScale * advanceX;
|
||||
if (advanceX > 0.0 && fAdvanceScale > 1.0)
|
||||
x += (fAdvanceScale - 1.0) * fFontEngine.height();
|
||||
y += advanceY;
|
||||
|
||||
double left = 0.0;
|
||||
double top = 0.0;
|
||||
double right = -1.0;
|
||||
double bottom = -1.0;
|
||||
uint32 pathID[1];
|
||||
pathID[0] = 0;
|
||||
|
||||
fFontManager.init_embedded_adaptors(glyph, x, y);
|
||||
|
||||
switch(glyph->data_type) {
|
||||
case agg::glyph_data_mono:
|
||||
break;
|
||||
|
||||
case agg::glyph_data_gray8:
|
||||
break;
|
||||
|
||||
case agg::glyph_data_outline:
|
||||
if (fabs(0.0) <= 0.01) {
|
||||
// For the sake of efficiency skip the
|
||||
// contour converter if the weight is about zero.
|
||||
//-----------------------
|
||||
agg::bounding_rect(fContour, pathID, 0, 1, &left, &top, &right, &bottom);
|
||||
} else {
|
||||
agg::bounding_rect(fCurves, pathID, 0, 1, &left, &top, &right, &bottom);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BRect t(left, top, right, bottom);
|
||||
if (t.IsValid())
|
||||
bounds = bounds.IsValid() ? bounds | t : t;
|
||||
|
||||
// increment pen position
|
||||
// x += glyph->advance_x + (fAdvanceScale - 1.0) * fFontEngine.height();
|
||||
// y += glyph->advance_y;
|
||||
advanceX = fHinted ? floorf(glyph->advance_x + 0.5) : glyph->advance_x;
|
||||
advanceY = fHinted ? floorf(glyph->advance_y + 0.5) : glyph->advance_y;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
delete[] buffer;
|
||||
} else {
|
||||
fprintf(stderr, "UTF8 -> Unicode conversion failed: %s\n", strerror(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transform.TransformBounds(bounds);
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
// AGGTextRenderer.h
|
||||
|
||||
#ifndef AGG_TEXT_RENDERER_H
|
||||
#define AGG_TEXT_RENDERER_H
|
||||
|
||||
#include <agg_conv_curve.h>
|
||||
#include <agg_conv_contour.h>
|
||||
|
||||
#include "agg_font_freetype.h"
|
||||
#include "defines.h"
|
||||
|
||||
#include "TextRenderer.h"
|
||||
|
||||
class AGGTextRenderer : public TextRenderer {
|
||||
public:
|
||||
AGGTextRenderer();
|
||||
AGGTextRenderer(BMessage* archive);
|
||||
AGGTextRenderer(const AGGTextRenderer& from);
|
||||
virtual ~AGGTextRenderer();
|
||||
|
||||
virtual void SetTo(const TextRenderer* other);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
|
||||
virtual bool SetFont(const char* pathToFontFile);
|
||||
virtual void Unset();
|
||||
|
||||
virtual const char* Family() const;
|
||||
virtual const char* Style() const;
|
||||
virtual const char* PostScriptName() const;
|
||||
|
||||
virtual void RenderString(const char* utf8String,
|
||||
font_renderer_solid_type* solidRenderer,
|
||||
font_renderer_bin_type* binRenderer,
|
||||
const Transformable& transform);
|
||||
|
||||
virtual BRect Bounds(const char* utf8String,
|
||||
const Transformable& transform);
|
||||
|
||||
private:
|
||||
|
||||
typedef agg::font_engine_freetype_int32 font_engine_type;
|
||||
typedef agg::font_cache_manager<font_engine_type> font_manager_type;
|
||||
|
||||
font_engine_type fFontEngine;
|
||||
font_manager_type fFontManager;
|
||||
|
||||
// Pipeline to process the vectors glyph paths (curves + contour)
|
||||
agg::conv_curve<font_manager_type::path_adaptor_type>
|
||||
fCurves;
|
||||
agg::conv_contour<agg::conv_curve<font_manager_type::path_adaptor_type> >
|
||||
fContour;
|
||||
|
||||
BRect fBounds;
|
||||
};
|
||||
|
||||
#endif // AGG_TEXT_RENDERER_H
|
333
src/servers/app/server/Painter/font_support/FontManager.cpp
Normal file
333
src/servers/app/server/Painter/font_support/FontManager.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
// FontManager.cpp
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_SFNT_NAMES_H
|
||||
#include <freetype/ttnameid.h>
|
||||
|
||||
#include <FindDirectory.h>
|
||||
#include <Directory.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Path.h>
|
||||
#include <String.h>
|
||||
#include <UTF8.h>
|
||||
|
||||
#include "FontManager.h"
|
||||
|
||||
// static default instance
|
||||
FontManager*
|
||||
FontManager::fDefaultManager = NULL;
|
||||
|
||||
static const char* threadName = "font scanner";
|
||||
|
||||
// constructor
|
||||
FontManager::FontManager(bool scanFontsInline)
|
||||
: BLooper(threadName, B_LOW_PRIORITY),
|
||||
fLibrary(NULL),
|
||||
fFontFiles(1024)
|
||||
{
|
||||
// initialize engine
|
||||
FT_Error error = FT_Init_FreeType(&fLibrary);
|
||||
if (error)
|
||||
fprintf(stderr, "Could not initialise FreeType library\n");
|
||||
|
||||
if (scanFontsInline) {
|
||||
_update((void*)this);
|
||||
} else {
|
||||
// start thread to read keyfile
|
||||
thread_id fontScanner = spawn_thread(_update, threadName,
|
||||
B_LOW_PRIORITY, this);
|
||||
if (fontScanner >= B_OK)
|
||||
resume_thread(fontScanner);
|
||||
}
|
||||
|
||||
Run();
|
||||
}
|
||||
|
||||
// destructor
|
||||
FontManager::~FontManager()
|
||||
{
|
||||
_MakeEmpty();
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
FontManager::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_UPDATE: {
|
||||
// notify potential observes
|
||||
BMessage message(MSG_FONTS_CHANGED);
|
||||
SendNotices(FONTS_CHANGED, &message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// CreateDefault
|
||||
void
|
||||
FontManager::CreateDefault(bool scanFontsInline)
|
||||
{
|
||||
if (!fDefaultManager)
|
||||
fDefaultManager = new FontManager(scanFontsInline);
|
||||
}
|
||||
|
||||
// DeleteDefault
|
||||
void
|
||||
FontManager::DeleteDefault()
|
||||
{
|
||||
fDefaultManager->Lock();
|
||||
fDefaultManager->Quit();
|
||||
}
|
||||
|
||||
// Default
|
||||
FontManager*
|
||||
FontManager::Default()
|
||||
{
|
||||
if (!fDefaultManager)
|
||||
CreateDefault();
|
||||
return fDefaultManager;
|
||||
}
|
||||
|
||||
// FontFileAt
|
||||
const entry_ref*
|
||||
FontManager::FontFileAt(int32 index) const
|
||||
{
|
||||
if (font_file* ff = (font_file*)fFontFiles.ItemAt(index)) {
|
||||
return &ff->ref;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FontFileFor
|
||||
const entry_ref*
|
||||
FontManager::FontFileFor(const char* family, const char* style) const
|
||||
{
|
||||
if (family && style) {
|
||||
for (int32 i = 0; font_file* ff = (font_file*)fFontFiles.ItemAt(i); i++) {
|
||||
if (ff->family_name && strcmp(ff->family_name, family) == 0
|
||||
&& ff->style_name && strcmp(ff->style_name, style) == 0)
|
||||
return &ff->ref;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FamilyFor
|
||||
const char*
|
||||
FontManager::FamilyFor(const entry_ref* fontFile) const
|
||||
{
|
||||
if (font_file* ff = _FontFileFor(fontFile))
|
||||
return ff->family_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// StyleFor
|
||||
const char*
|
||||
FontManager::StyleFor(const entry_ref* fontFile) const
|
||||
{
|
||||
if (font_file* ff = _FontFileFor(fontFile))
|
||||
return ff->style_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FullFamilyFor
|
||||
const char*
|
||||
FontManager::FullFamilyFor(const entry_ref* fontFile) const
|
||||
{
|
||||
if (font_file* ff = _FontFileFor(fontFile))
|
||||
return ff->full_family_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// PostScriptNameFor
|
||||
const char*
|
||||
FontManager::PostScriptNameFor(const entry_ref* fontFile) const
|
||||
{
|
||||
if (font_file* ff = _FontFileFor(fontFile))
|
||||
return ff->ps_name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// CountFontFiles
|
||||
int32
|
||||
FontManager::CountFontFiles() const
|
||||
{
|
||||
return fFontFiles.CountItems();
|
||||
}
|
||||
|
||||
// _MakeEmpty
|
||||
void
|
||||
FontManager::_MakeEmpty()
|
||||
{
|
||||
int32 i = fFontFiles.CountItems() - 1;
|
||||
while (i >= 0) {
|
||||
if (font_file* ff = (font_file*)fFontFiles.ItemAt(i)) {
|
||||
if (ff->family_name)
|
||||
free(ff->family_name);
|
||||
if (ff->style_name)
|
||||
free(ff->style_name);
|
||||
if (ff->full_family_name)
|
||||
free(ff->full_family_name);
|
||||
if (ff->ps_name)
|
||||
free(ff->ps_name);
|
||||
delete ff;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
fFontFiles.MakeEmpty();
|
||||
}
|
||||
|
||||
int32
|
||||
FontManager::_update(void* cookie)
|
||||
{
|
||||
FontManager* fm = (FontManager*)cookie;
|
||||
if (fm && fm->Lock()) {
|
||||
//bigtime_t now = system_time();
|
||||
// update from system, common and user fonts folders
|
||||
BPath path;
|
||||
if (find_directory(B_BEOS_FONTS_DIRECTORY, &path) >= B_OK) {
|
||||
BDirectory fontFolder(path.Path());
|
||||
fm->_Update(&fontFolder);
|
||||
}
|
||||
if (find_directory(B_COMMON_FONTS_DIRECTORY, &path) >= B_OK) {
|
||||
BDirectory fontFolder(path.Path());
|
||||
fm->_Update(&fontFolder);
|
||||
}
|
||||
/* if (find_directory(B_USER_FONTS_DIRECTORY, &path) >= B_OK) {
|
||||
BDirectory fontFolder(path.Path());
|
||||
_Update(&fontFolder);
|
||||
}*/
|
||||
/*printf("scanning fonts: %lld µsecs\n", system_time() - now);
|
||||
for (int32 i = 0; font_file* ff = (font_file*)fFontFiles.ItemAt(i); i++) {
|
||||
printf("fond %ld: \"%s, %s\"\n", i, ff->family_name, ff->style_name);
|
||||
}*/
|
||||
fm->Unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//_Update
|
||||
void
|
||||
FontManager::_Update(BDirectory* fontFolder)
|
||||
{
|
||||
fontFolder->Rewind();
|
||||
// scan the entire folder for font files
|
||||
BEntry entry;
|
||||
while (fontFolder->GetNextEntry(&entry) >= B_OK) {
|
||||
if (entry.IsDirectory()) {
|
||||
// recursive scan of sub folders
|
||||
BDirectory subFolder(&entry);
|
||||
_Update(&subFolder);
|
||||
} else {
|
||||
// see if this is a usable font file
|
||||
BPath path;
|
||||
if (entry.GetPath(&path) >= B_OK) {
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face(fLibrary, path.Path(), 0, &face);
|
||||
if (!error && face->family_name && face->style_name) {
|
||||
// create font_file object and init it
|
||||
font_file* fontFile = new font_file;
|
||||
entry.GetRef(&fontFile->ref);
|
||||
fontFile->family_name = strdup(face->family_name);
|
||||
fontFile->style_name = strdup(face->style_name);
|
||||
fontFile->full_family_name = NULL;
|
||||
fontFile->ps_name = NULL;
|
||||
// iterate over the names we find for this font face
|
||||
int32 nameCount = FT_Get_Sfnt_Name_Count(face);
|
||||
FT_SfntName fontName;
|
||||
//printf("\n\nfont: '%s'/'%s':\n", fontFile->family_name, fontFile->style_name);
|
||||
for (int32 i = 0; (fontFile->full_family_name == NULL || fontFile->ps_name == NULL)
|
||||
&& i < nameCount; i++) {
|
||||
if (FT_Get_Sfnt_Name(face, i, &fontName ) == 0) {
|
||||
switch (fontName.platform_id) {
|
||||
case TT_PLATFORM_APPLE_UNICODE:
|
||||
//printf(" platform: TT_PLATFORM_APPLE_UNICODE\n");
|
||||
// TODO: implement
|
||||
break;
|
||||
case TT_PLATFORM_MACINTOSH:
|
||||
//printf(" platform: TT_PLATFORM_MACINTOSH\n");
|
||||
if (fontName.encoding_id == TT_MAC_ID_ROMAN) {
|
||||
if (fontName.name_id == TT_NAME_ID_FULL_NAME) {
|
||||
fontFile->full_family_name = (char*)malloc(fontName.string_len + 1);
|
||||
memcpy(fontFile->full_family_name, fontName.string, fontName.string_len);
|
||||
fontFile->full_family_name[fontName.string_len] = 0;
|
||||
} else if (fontName.name_id == TT_NAME_ID_PS_NAME) {
|
||||
fontFile->ps_name = (char*)malloc(fontName.string_len + 1);
|
||||
memcpy(fontFile->ps_name, fontName.string, fontName.string_len);
|
||||
fontFile->ps_name[fontName.string_len] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TT_PLATFORM_MICROSOFT:
|
||||
//printf(" platform: TT_PLATFORM_MICROSOFT\n");
|
||||
// TODO: implement
|
||||
if (fontName.encoding_id == TT_MS_ID_UNICODE_CS) {
|
||||
if (fontName.name_id == TT_NAME_ID_FULL_NAME
|
||||
|| fontName.name_id == TT_NAME_ID_PS_NAME) {
|
||||
int32 length = fontName.string_len + 1;
|
||||
char* buffer = (char*)malloc(length);
|
||||
memcpy(buffer, fontName.string, length - 1);
|
||||
buffer[length - 1] = 0;
|
||||
int32 state = 0;
|
||||
convert_to_utf8(B_UNICODE_CONVERSION,
|
||||
buffer,
|
||||
&length,
|
||||
buffer,
|
||||
&length,
|
||||
&state,
|
||||
B_SUBSTITUTE);
|
||||
if (fontName.name_id == TT_NAME_ID_FULL_NAME)
|
||||
fontFile->full_family_name = buffer;
|
||||
else if (fontName.name_id == TT_NAME_ID_PS_NAME)
|
||||
fontFile->ps_name = buffer;
|
||||
//printf("uni-code name: '%s' (orig-length: %d, length: %ld)\n", buffer, fontName.string_len, length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
char* name = (char*)malloc(fontName.string_len + 1);
|
||||
memcpy(name, fontName.string, fontName.string_len);
|
||||
name[fontName.string_len] = 0;
|
||||
printf(" %d, %d, ", fontName.encoding_id, fontName.name_id);
|
||||
printf("name: '%s'\n", name);
|
||||
free(name);
|
||||
*/
|
||||
}
|
||||
// find slot in sorted list and add it
|
||||
int32 i = 0;
|
||||
for (; font_file* ff = (font_file*)fFontFiles.ItemAt(i); i++) {
|
||||
if (strcmp(fontFile->family_name, ff->family_name) < 0
|
||||
&& strcmp(fontFile->style_name, ff->style_name) <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fFontFiles.AddItem((void*)fontFile, i);
|
||||
FT_Done_Face(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _FontFileFor
|
||||
FontManager::font_file*
|
||||
FontManager::_FontFileFor(const entry_ref* ref) const
|
||||
{
|
||||
if (ref) {
|
||||
for (int32 i = 0; font_file* ff = (font_file*)fFontFiles.ItemAt(i); i++) {
|
||||
if (ff->ref == *ref) {
|
||||
return ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
73
src/servers/app/server/Painter/font_support/FontManager.h
Normal file
73
src/servers/app/server/Painter/font_support/FontManager.h
Normal file
@ -0,0 +1,73 @@
|
||||
// FontManager.h
|
||||
|
||||
#ifndef FT_FONT_MANAGER_H
|
||||
#define FT_FONT_MANAGER_H
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
#include <Entry.h>
|
||||
#include <Looper.h>
|
||||
|
||||
class BMenu;
|
||||
|
||||
enum {
|
||||
MSG_FONTS_CHANGED = 'fnch',
|
||||
MSG_SET_FONT = 'stfn',
|
||||
MSG_UPDATE = 'updt',
|
||||
};
|
||||
|
||||
enum {
|
||||
FONTS_CHANGED = 0x01,
|
||||
};
|
||||
|
||||
class FontManager : public BLooper {
|
||||
public:
|
||||
FontManager(bool scanFontsInline);
|
||||
virtual ~FontManager();
|
||||
|
||||
// BLooper
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
// FontManager
|
||||
static void CreateDefault(bool scanFontsInline = false);
|
||||
static void DeleteDefault();
|
||||
static FontManager* Default();
|
||||
|
||||
// lock the object!
|
||||
virtual const entry_ref* FontFileAt(int32 index) const;
|
||||
virtual const entry_ref* FontFileFor(const char* family,
|
||||
const char* style) const;
|
||||
|
||||
virtual const char* FamilyFor(const entry_ref* fontFile) const;
|
||||
virtual const char* StyleFor(const entry_ref* fontFile) const;
|
||||
|
||||
virtual const char* FullFamilyFor(const entry_ref* fontFile) const;
|
||||
virtual const char* PostScriptNameFor(const entry_ref* fontFile) const;
|
||||
|
||||
virtual int32 CountFontFiles() const;
|
||||
|
||||
private:
|
||||
void _MakeEmpty();
|
||||
static int32 _update(void* cookie);
|
||||
void _Update(BDirectory* fontFolder);
|
||||
|
||||
struct font_file {
|
||||
char* family_name;
|
||||
char* style_name;
|
||||
char* full_family_name;
|
||||
char* ps_name;
|
||||
entry_ref ref;
|
||||
};
|
||||
|
||||
font_file* _FontFileFor(const entry_ref* ref) const;
|
||||
|
||||
FT_Library fLibrary; // the FreeType fLibrary
|
||||
|
||||
BList fFontFiles;
|
||||
|
||||
static FontManager* fDefaultManager;
|
||||
};
|
||||
|
||||
#endif // FT_FONT_MANAGER_H
|
293
src/servers/app/server/Painter/font_support/TextRenderer.cpp
Normal file
293
src/servers/app/server/Painter/font_support/TextRenderer.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
// TextRenderer.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "FontManager.h"
|
||||
|
||||
#include "TextRenderer.h"
|
||||
|
||||
#define MAXPTSIZE 5000
|
||||
|
||||
// constructor
|
||||
TextRenderer::TextRenderer()
|
||||
: fPtSize(12.0),
|
||||
fHinted(false),
|
||||
fAntialias(true),
|
||||
fKerning(true),
|
||||
fOpacity(255),
|
||||
fAdvanceScale(1.0),
|
||||
fLineSpacingScale(1.2)
|
||||
{
|
||||
fFontFilePath[0] = 0;
|
||||
}
|
||||
|
||||
TextRenderer::TextRenderer(BMessage* archive)
|
||||
: fPtSize(12.0),
|
||||
fHinted(false),
|
||||
fAntialias(true),
|
||||
fKerning(true),
|
||||
fOpacity(255),
|
||||
fAdvanceScale(1.0),
|
||||
fLineSpacingScale(1.2)
|
||||
{
|
||||
// backwards compatibility crap
|
||||
int32 size;
|
||||
if (archive->FindInt32("size", &size) < B_OK) {
|
||||
if (archive->FindFloat("size", &fPtSize) < B_OK)
|
||||
fPtSize = 12.0;
|
||||
} else {
|
||||
fPtSize = size / 16.0;
|
||||
}
|
||||
|
||||
int32 opacity;
|
||||
if (archive->FindInt32("gray levels", &opacity) < B_OK)
|
||||
fOpacity = 255;
|
||||
else
|
||||
fOpacity = max_c(0, min_c(255, opacity));
|
||||
|
||||
if (archive->FindFloat("advance scale", &fAdvanceScale) < B_OK)
|
||||
fAdvanceScale = 1.0;
|
||||
|
||||
if (archive->FindFloat("line spacing scale", &fLineSpacingScale) < B_OK)
|
||||
fLineSpacingScale = 1.2;
|
||||
|
||||
fFontFilePath[0] = 0;
|
||||
const char* family;
|
||||
const char* style;
|
||||
if (archive->FindString("family", &family) >= B_OK
|
||||
&& archive->FindString("style", &style) >= B_OK) {
|
||||
FontManager* fm = FontManager::Default();
|
||||
//printf("locking font manager, %s, %s\n", family, style);
|
||||
if (fm->Lock()) {
|
||||
//printf("setting font: %s, %s\n", family, style);
|
||||
SetFontRef(fm->FontFileFor(family, style));
|
||||
fm->Unlock();
|
||||
}
|
||||
} else {
|
||||
//printf("no family or style!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// constructor
|
||||
TextRenderer::TextRenderer(const TextRenderer& from)
|
||||
: fPtSize(12.0),
|
||||
fHinted(false),
|
||||
fAntialias(true),
|
||||
fKerning(true),
|
||||
fOpacity(255),
|
||||
fAdvanceScale(1.0),
|
||||
fLineSpacingScale(1.2)
|
||||
{
|
||||
fFontFilePath[0] = 0;
|
||||
SetTo(&from);
|
||||
}
|
||||
|
||||
// destructor
|
||||
TextRenderer::~TextRenderer()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
// SetTo
|
||||
void
|
||||
TextRenderer::SetTo(const TextRenderer* other)
|
||||
{
|
||||
Unset();
|
||||
|
||||
fFontFilePath[0] = 0;
|
||||
|
||||
fPtSize = other->fPtSize;
|
||||
fHinted = other->fHinted;
|
||||
fAntialias = other->fAntialias;
|
||||
fKerning = other->fKerning;
|
||||
fOpacity = other->fOpacity;
|
||||
fAdvanceScale = other->fAdvanceScale;
|
||||
fLineSpacingScale = other->fLineSpacingScale;
|
||||
|
||||
SetFont(other->fFontFilePath);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
// Archive
|
||||
status_t
|
||||
TextRenderer::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t status = BArchivable::Archive(into, deep);
|
||||
|
||||
if (status >= B_OK) {
|
||||
if (Family())
|
||||
status = into->AddString("family", Family());
|
||||
else
|
||||
fprintf(stderr, "no font family to put into message!\n");
|
||||
if (status >= B_OK && Style())
|
||||
status = into->AddString("style", Style());
|
||||
else
|
||||
fprintf(stderr, "no font style to put into message!\n");
|
||||
if (status >= B_OK)
|
||||
status = into->AddFloat("size", fPtSize);
|
||||
if (status >= B_OK)
|
||||
status = into->AddInt32("gray levels", fOpacity);
|
||||
if (status >= B_OK)
|
||||
status = into->AddFloat("advance scale", fAdvanceScale);
|
||||
if (status >= B_OK)
|
||||
status = into->AddFloat("line spacing scale", fLineSpacingScale);
|
||||
|
||||
// finish
|
||||
if (status >= B_OK)
|
||||
status = into->AddString("class", "TextRenderer");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// SetFontRef
|
||||
bool
|
||||
TextRenderer::SetFontRef(const entry_ref* ref)
|
||||
{
|
||||
//printf("TextRenderer::SetFontRef(%s)\n", ref ? ref->name : "no ref!");
|
||||
if (ref) {
|
||||
BPath path(ref);
|
||||
if (path.InitCheck() >= B_OK)
|
||||
return SetFont(path.Path());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// SetFont
|
||||
bool
|
||||
TextRenderer::SetFont(const char* pathToFontFile)
|
||||
{
|
||||
//printf("TextRenderer::SetFont(%s)\n", pathToFontFile ? pathToFontFile : "no path!");
|
||||
if (pathToFontFile) {
|
||||
sprintf(fFontFilePath, "%s", pathToFontFile);
|
||||
//printf("font: %s\n", fFontFilePath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unset
|
||||
void
|
||||
TextRenderer::Unset()
|
||||
{
|
||||
fFontFilePath[0] = 0;
|
||||
}
|
||||
|
||||
// SetFamilyAndStyle
|
||||
bool
|
||||
TextRenderer::SetFamilyAndStyle(const char* family, const char* style)
|
||||
{
|
||||
FontManager* fm = FontManager::Default();
|
||||
if (fm->Lock()) {
|
||||
const entry_ref* fontRef = fm->FontFileFor(family, style);
|
||||
fm->Unlock();
|
||||
|
||||
return SetFontRef(fontRef);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// SetRotation
|
||||
void
|
||||
TextRenderer::SetRotation(float angle)
|
||||
{
|
||||
}
|
||||
|
||||
// Rotation
|
||||
float
|
||||
TextRenderer::Rotation() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// SetPointSize
|
||||
void
|
||||
TextRenderer::SetPointSize(float size)
|
||||
{
|
||||
if (size < 0.0)
|
||||
size = 0.0;
|
||||
if (size * 16.0 > MAXPTSIZE)
|
||||
size = MAXPTSIZE / 16.0;
|
||||
if (size != fPtSize) {
|
||||
fPtSize = size;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
// PointSize
|
||||
float
|
||||
TextRenderer::PointSize() const
|
||||
{
|
||||
return fPtSize;
|
||||
}
|
||||
|
||||
// SetHinting
|
||||
void
|
||||
TextRenderer::SetHinting(bool hinting)
|
||||
{
|
||||
fHinted = hinting;
|
||||
Update();
|
||||
}
|
||||
|
||||
// SetAntialiasing
|
||||
void
|
||||
TextRenderer::SetAntialiasing(bool antialiasing)
|
||||
{
|
||||
fAntialias = antialiasing;
|
||||
Update();
|
||||
}
|
||||
|
||||
// SetOpacity
|
||||
void
|
||||
TextRenderer::SetOpacity(uint8 opacity)
|
||||
{
|
||||
fOpacity = opacity;
|
||||
}
|
||||
|
||||
// Opacity
|
||||
uint8
|
||||
TextRenderer::Opacity() const
|
||||
{
|
||||
return fOpacity;
|
||||
}
|
||||
|
||||
// SetAdvanceScale
|
||||
void
|
||||
TextRenderer::SetAdvanceScale(float scale)
|
||||
{
|
||||
fAdvanceScale = scale;
|
||||
Update();
|
||||
}
|
||||
|
||||
// AdvanceScale
|
||||
float
|
||||
TextRenderer::AdvanceScale() const
|
||||
{
|
||||
return fAdvanceScale;
|
||||
}
|
||||
|
||||
// SetLineSpacingScale
|
||||
void
|
||||
TextRenderer::SetLineSpacingScale(float scale)
|
||||
{
|
||||
fLineSpacingScale = scale;
|
||||
Update();
|
||||
}
|
||||
|
||||
// LineSpacingScale
|
||||
float
|
||||
TextRenderer::LineSpacingScale() const
|
||||
{
|
||||
return fLineSpacingScale;
|
||||
}
|
||||
|
||||
// LineOffset
|
||||
float
|
||||
TextRenderer::LineOffset() const
|
||||
{
|
||||
return fLineSpacingScale * fPtSize * 16.0;
|
||||
}
|
81
src/servers/app/server/Painter/font_support/TextRenderer.h
Normal file
81
src/servers/app/server/Painter/font_support/TextRenderer.h
Normal file
@ -0,0 +1,81 @@
|
||||
// TextRenderer.h
|
||||
|
||||
#ifndef TEXT_RENDERER_H
|
||||
#define TEXT_RENDERER_H
|
||||
|
||||
#include "Transformable.h"
|
||||
|
||||
struct entry_ref;
|
||||
|
||||
class BBitmap;
|
||||
|
||||
class TextRenderer : public BArchivable {
|
||||
public:
|
||||
TextRenderer();
|
||||
TextRenderer(BMessage* archive);
|
||||
TextRenderer(const TextRenderer& from);
|
||||
virtual ~TextRenderer();
|
||||
|
||||
virtual void SetTo(const TextRenderer* other);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
|
||||
bool SetFontRef(const entry_ref* ref);
|
||||
virtual bool SetFont(const char* pathToFontFile);
|
||||
virtual void Unset();
|
||||
|
||||
bool SetFamilyAndStyle(const char* family,
|
||||
const char* style);
|
||||
virtual const char* Family() const = 0;
|
||||
virtual const char* Style() const = 0;
|
||||
virtual const char* PostScriptName() const = 0;
|
||||
|
||||
virtual void SetRotation(float angle);
|
||||
virtual float Rotation() const;
|
||||
|
||||
virtual void SetPointSize(float size);
|
||||
float PointSize() const;
|
||||
|
||||
virtual void SetHinting(bool hinting);
|
||||
bool Hinting() const
|
||||
{ return fHinted; }
|
||||
|
||||
virtual void SetAntialiasing(bool antialiasing);
|
||||
bool Antialiasing() const
|
||||
{ return fAntialias; }
|
||||
|
||||
virtual void SetOpacity(uint8 opacity);
|
||||
uint8 Opacity() const;
|
||||
|
||||
virtual void SetAdvanceScale(float scale);
|
||||
float AdvanceScale() const;
|
||||
|
||||
virtual void SetLineSpacingScale(float scale);
|
||||
float LineSpacingScale() const;
|
||||
|
||||
float LineOffset() const;
|
||||
|
||||
/* virtual void RenderString(const char* utf8String,
|
||||
BBitmap* bitmap,
|
||||
BRect constrainRect,
|
||||
const Transformable& transform) = 0;*/
|
||||
|
||||
virtual BRect Bounds(const char* utf8String,
|
||||
const Transformable& transform) = 0;
|
||||
|
||||
virtual void Update() {};
|
||||
|
||||
protected:
|
||||
char fFontFilePath[B_PATH_NAME_LENGTH];
|
||||
|
||||
float fPtSize;
|
||||
|
||||
bool fHinted; // is glyph hinting active?
|
||||
bool fAntialias; // is anti-aliasing active?
|
||||
bool fKerning;
|
||||
uint8 fOpacity;
|
||||
float fAdvanceScale;
|
||||
float fLineSpacingScale;
|
||||
};
|
||||
|
||||
#endif // FT_TEXT_RENDER_H
|
1050
src/servers/app/server/Painter/font_support/agg_font_freetype.cpp
Normal file
1050
src/servers/app/server/Painter/font_support/agg_font_freetype.cpp
Normal file
File diff suppressed because it is too large
Load Diff
195
src/servers/app/server/Painter/font_support/agg_font_freetype.h
Normal file
195
src/servers/app/server/Painter/font_support/agg_font_freetype.h
Normal file
@ -0,0 +1,195 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.2
|
||||
// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// See implementation agg_font_freetype.cpp
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_FONT_FREETYPE_INCLUDED
|
||||
#define AGG_FONT_FREETYPE_INCLUDED
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
|
||||
#include "agg_scanline_storage_aa.h"
|
||||
#include "agg_scanline_storage_bin.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_scanline_bin.h"
|
||||
#include "agg_path_storage_integer.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_font_cache_manager.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------font_engine_freetype_base
|
||||
class font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type;
|
||||
typedef serialized_scanlines_adaptor_bin mono_adaptor_type;
|
||||
typedef scanline_storage_aa8 scanlines_aa_type;
|
||||
typedef scanline_storage_bin scanlines_bin_type;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
~font_engine_freetype_base();
|
||||
font_engine_freetype_base(bool flag32, unsigned max_faces = 32);
|
||||
|
||||
// Set font parameters
|
||||
//--------------------------------------------------------------------
|
||||
void resolution(unsigned dpi);
|
||||
bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type);
|
||||
bool attach(const char* file_name);
|
||||
bool char_map(FT_Encoding map);
|
||||
bool height(double h);
|
||||
bool width(double w);
|
||||
void transform(const trans_affine& mtx);
|
||||
void transform(double xx, double xy, double yx, double yy);
|
||||
void hinting(bool h);
|
||||
void flip_y(bool f);
|
||||
|
||||
// Set Gamma
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaF> void gamma(const GammaF& f)
|
||||
{
|
||||
m_rasterizer.gamma(f);
|
||||
}
|
||||
|
||||
// Accessors
|
||||
//--------------------------------------------------------------------
|
||||
int last_error() const { return m_last_error; }
|
||||
unsigned resolution() const { return m_resolution; }
|
||||
const char* name() const { return m_name; }
|
||||
unsigned num_faces() const;
|
||||
FT_Encoding char_map() const { return m_char_map; }
|
||||
double height() const { return double(m_height) / 64.0; }
|
||||
double width() const { return double(m_width) / 64.0; }
|
||||
bool hinting() const { return m_hinting; }
|
||||
bool flip_y() const { return m_flip_y; }
|
||||
|
||||
|
||||
// Interface mandatory to implement for font_cache_manager
|
||||
//--------------------------------------------------------------------
|
||||
const char* font_signature() const { return m_signature; }
|
||||
int change_stamp() const { return m_change_stamp; }
|
||||
|
||||
bool prepare_glyph(unsigned glyph_code);
|
||||
unsigned glyph_index() const { return m_glyph_index; }
|
||||
unsigned data_size() const { return m_data_size; }
|
||||
glyph_data_type data_type() const { return m_data_type; }
|
||||
const rect& bounds() const { return m_bounds; }
|
||||
double advance_x() const { return m_advance_x; }
|
||||
double advance_y() const { return m_advance_y; }
|
||||
void write_glyph_to(int8u* data) const;
|
||||
bool add_kerning(unsigned first, unsigned second,
|
||||
double* x, double* y);
|
||||
|
||||
private:
|
||||
font_engine_freetype_base(const font_engine_freetype_base&);
|
||||
const font_engine_freetype_base& operator = (const font_engine_freetype_base&);
|
||||
|
||||
void update_char_size();
|
||||
void update_signature();
|
||||
void update_transform();
|
||||
int find_face(const char* face_name) const;
|
||||
|
||||
bool m_flag32;
|
||||
int m_change_stamp;
|
||||
int m_last_error;
|
||||
char* m_name;
|
||||
unsigned m_name_len;
|
||||
unsigned m_face_index;
|
||||
FT_Encoding m_char_map;
|
||||
char* m_signature;
|
||||
unsigned m_height;
|
||||
unsigned m_width;
|
||||
FT_Matrix m_matrix;
|
||||
bool m_hinting;
|
||||
bool m_flip_y;
|
||||
bool m_library_initialized;
|
||||
FT_Library m_library; // handle to library
|
||||
FT_Face* m_faces; // A pool of font faces
|
||||
char** m_face_names;
|
||||
unsigned m_num_faces;
|
||||
unsigned m_max_faces;
|
||||
FT_Face m_cur_face; // handle to the current face object
|
||||
int m_resolution;
|
||||
glyph_rendering m_glyph_rendering;
|
||||
unsigned m_glyph_index;
|
||||
unsigned m_data_size;
|
||||
glyph_data_type m_data_type;
|
||||
rect m_bounds;
|
||||
double m_advance_x;
|
||||
double m_advance_y;
|
||||
|
||||
path_storage_integer<int16, 6> m_path16;
|
||||
path_storage_integer<int32, 6> m_path32;
|
||||
conv_curve<path_storage_integer<int16, 6> > m_curves16;
|
||||
conv_curve<path_storage_integer<int32, 6> > m_curves32;
|
||||
scanline_u8 m_scanline_aa;
|
||||
scanline_bin m_scanline_bin;
|
||||
scanlines_aa_type m_scanlines_aa;
|
||||
scanlines_bin_type m_scanlines_bin;
|
||||
rasterizer_scanline_aa<> m_rasterizer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------font_engine_freetype_int16
|
||||
// This class uses values of type int16 (10.6 format) for the vector cache.
|
||||
// The vector cache is compact, but when rendering glyphs of height
|
||||
// more that 200 there integer overflow can occur.
|
||||
//
|
||||
class font_engine_freetype_int16 : public font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type;
|
||||
typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_freetype_int16(unsigned max_faces = 32) :
|
||||
font_engine_freetype_base(false, max_faces) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------font_engine_freetype_int32
|
||||
// This class uses values of type int32 (26.6 format) for the vector cache.
|
||||
// The vector cache is twice larger than in font_engine_freetype_int16,
|
||||
// but it allows you to render glyphs of very large sizes.
|
||||
//
|
||||
class font_engine_freetype_int32 : public font_engine_freetype_base
|
||||
{
|
||||
public:
|
||||
typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type;
|
||||
typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type;
|
||||
typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type;
|
||||
typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type;
|
||||
typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type;
|
||||
|
||||
font_engine_freetype_int32(unsigned max_faces = 32) :
|
||||
font_engine_freetype_base(true, max_faces) {}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
270
src/servers/app/server/Painter/main.cpp
Normal file
270
src/servers/app/server/Painter/main.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
// main.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <GraphicsDefs.h>
|
||||
#include <Region.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "BitmapView.h"
|
||||
#include "BitmapBuffer.h"
|
||||
#include "FontManager.h"
|
||||
#include "Painter.h"
|
||||
|
||||
const pattern kStripes = (pattern){ { 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 } };
|
||||
const pattern kDotted = (pattern){ { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa } };
|
||||
const pattern kDottedBigger = (pattern){ { 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc } };
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
BApplication* app = new BApplication("application/x.vnd-YellowBites.TestApp");
|
||||
|
||||
// create the default instance of the FontManager
|
||||
// It takes a bit to scan through the font files;
|
||||
// "true" means to do the font scanning inline, not
|
||||
// in a separate thread.
|
||||
fprintf(stdout, "scanning font files...");
|
||||
fflush(stdout);
|
||||
FontManager::CreateDefault(true);
|
||||
fprintf(stdout, "done\n");
|
||||
|
||||
BRect bounds(0.0, 0.0, 319.0, 239.0);
|
||||
BRegion noClip(bounds);
|
||||
|
||||
// BRegion clip(BRect(50, 50, 100, 100));
|
||||
// clip.Include(BRect(20, 10, 80, 110));
|
||||
// clip.Include(BRect(120, -20, 180, 250));
|
||||
int32 clipCount = 5;
|
||||
BRegion clip;
|
||||
float h = bounds.Width() / clipCount;
|
||||
float v = bounds.Height() / clipCount;
|
||||
float hInset = (h / 2.0) * 0.5;
|
||||
float vInset = (v / 2.0) * 0.5;
|
||||
for (int32 i = 0; i < clipCount; i++) {
|
||||
/* BRect b(h * i, bounds.top, h * i, bounds.bottom);
|
||||
b.InsetBy(-hInset, 0.0);
|
||||
clip.Include(b);
|
||||
b.Set(bounds.left, v * i, bounds.right, v * i);
|
||||
b.InsetBy(0.0, -vInset);
|
||||
clip.Include(b);*/
|
||||
BRect b(bounds.left, v * i, bounds.right, v * i);
|
||||
b.InsetBy(0.0, -vInset);
|
||||
clip.Include(b);
|
||||
b.Set(h * i, bounds.top, h * i, bounds.bottom);
|
||||
b.InsetBy(-hInset, 0.0);
|
||||
clip.Include(b);
|
||||
}
|
||||
float penSize = 3.0;
|
||||
float scale = 1.0;
|
||||
// TODO: Painter behaves differently when origin has subpixel offset
|
||||
// BPoint origin(20.3, 10.8);
|
||||
BPoint origin(20, 10);
|
||||
BRect rect(20.2, 45.6, 219.0, 139.0);
|
||||
BRect rect2(40, 100, 250, 220.0);
|
||||
BPoint center(bounds.Width() / 2.0, bounds.Height() / 2.0);
|
||||
float xRadius = 30.0;
|
||||
float yRadius = 20.0;
|
||||
float angle = 40.0;
|
||||
float span = 230.0;
|
||||
const char* string = "The Quick Brown Fox...";
|
||||
BPoint stringLocation(50.0, 200.0);
|
||||
BFont font(be_plain_font);
|
||||
font.SetSize(20.0);
|
||||
font.SetRotation(15.0);
|
||||
// font.SetFamilyAndStyle(1);
|
||||
|
||||
BBitmap* testBitmap = new BBitmap(BRect(20, 5, 72, 46), 0, B_RGB32);
|
||||
// fill testBitmap with content
|
||||
uint8* bits = (uint8*)testBitmap->Bits();
|
||||
uint32 bitmapWidth = testBitmap->Bounds().IntegerWidth() + 1;
|
||||
uint32 bitmapHeight = testBitmap->Bounds().IntegerHeight() + 1;
|
||||
uint32 bpr = testBitmap->BytesPerRow();
|
||||
for (uint32 y = 0; y < bitmapHeight; y++) {
|
||||
uint8* h = bits;
|
||||
for (uint32 x = 0; x < bitmapWidth; x++) {
|
||||
h[0] = (uint8)((float)x / (float)bitmapWidth * 255.0);
|
||||
h[1] = (uint8)((float)y / (float)bitmapHeight * 255.0);
|
||||
h[2] = 255 - (uint8)((float)y / (float)bitmapHeight * 255.0);
|
||||
h[3] = 255;
|
||||
h += 4;
|
||||
}
|
||||
bits += bpr;
|
||||
}
|
||||
// make corners a black pixel for testing
|
||||
bits = (uint8*)testBitmap->Bits();
|
||||
*(uint32*)(&bits[0]) = 0;
|
||||
*(uint32*)(&bits[(bitmapWidth - 1) * 4]) = 0;
|
||||
*(uint32*)(&bits[(bitmapHeight - 1) * bpr]) = 0;
|
||||
*(uint32*)(&bits[(bitmapHeight - 1) * bpr + (bitmapWidth - 1) * 4]) = 0;
|
||||
|
||||
BRect testBitmapCrop(testBitmap->Bounds());
|
||||
// testBitmapCrop.left += 20.0;
|
||||
BRect testBitmapDestRect = testBitmapCrop;
|
||||
testBitmapDestRect.OffsetBy(200, 20);
|
||||
testBitmapDestRect.right = testBitmapDestRect.left + testBitmapDestRect.Width() * 2;
|
||||
testBitmapDestRect.bottom = testBitmapDestRect.top + testBitmapDestRect.Height() * 2;
|
||||
|
||||
// frame buffer
|
||||
BBitmap* bitmap = new BBitmap(bounds, B_RGB32);
|
||||
BitmapBuffer* buffer = new BitmapBuffer(bitmap);
|
||||
Painter painter;
|
||||
painter.AttachToBuffer(buffer);
|
||||
|
||||
uint32 width = buffer->Width();
|
||||
uint32 height = buffer->Height();
|
||||
|
||||
painter.ConstrainClipping(clip);
|
||||
painter.SetScale(scale);
|
||||
// painter.SetPenSize(penSize);
|
||||
painter.SetOrigin(origin);
|
||||
|
||||
bigtime_t painterNow = system_time();
|
||||
|
||||
painter.SetDrawingMode(B_OP_OVER);
|
||||
painter.SetHighColor(210, 210, 210);
|
||||
for (uint32 y = 0; y <= height / 2; y += 10)
|
||||
painter.StrokeLine(BPoint(0, 0), BPoint(width / 2, y));
|
||||
for (uint32 x = 0; x <= width; x += 10)
|
||||
painter.StrokeLine(BPoint(0, 0), BPoint(x, height));
|
||||
painter.SetPenSize(penSize * 5);
|
||||
painter.SetHighColor(255, 0, 0, 255);
|
||||
painter.SetLowColor(128, 0, 255, 255);
|
||||
// painter.SetScale(1.0);
|
||||
// painter.SetOrigin(B_ORIGIN);
|
||||
// painter.SetDrawingMode(B_OP_INVERT);
|
||||
painter.SetDrawingMode(B_OP_COPY);
|
||||
// painter.StrokeRect(rect);
|
||||
painter.StrokeRect(rect, kStripes);
|
||||
|
||||
// painter.ConstrainClipping(noClip);
|
||||
/* painter.SetPenLocation(BPoint(230.0, 30.0));
|
||||
painter.StrokeLine(BPoint(250.0, 30.0));
|
||||
painter.StrokeLine(BPoint(250.0, 50.0));
|
||||
painter.StrokeLine(BPoint(230.0, 50.0));
|
||||
painter.StrokeLine(BPoint(230.0, 30.0));*/
|
||||
|
||||
painter.SetHighColor(255, 255, 0, 255);
|
||||
painter.SetLowColor(128, 0, 50, 255);
|
||||
painter.SetDrawingMode(B_OP_OVER);
|
||||
painter.StrokeEllipse(center, xRadius, yRadius, kDottedBigger);
|
||||
painter.SetHighColor(255, 0, 0, 255);
|
||||
painter.SetDrawingMode(B_OP_INVERT);
|
||||
painter.FillArc(center, xRadius * 2, yRadius * 2, angle, span);
|
||||
// painter.StrokeArc(center, xRadius * 2, yRadius * 2, angle, span);
|
||||
painter.SetDrawingMode(B_OP_OVER);
|
||||
painter.SetPenSize(2.0);
|
||||
painter.StrokeEllipse(center, xRadius * 3, yRadius * 2);
|
||||
// painter.FillEllipse(center, xRadius * 3, yRadius * 2);
|
||||
// painter.StrokeLine(bounds.RightTop());
|
||||
// painter.FillRect(rect);
|
||||
painter.SetHighColor(0, 0, 255, 255);
|
||||
painter.SetPenSize(1.0);
|
||||
painter.StrokeRoundRect(rect2, 40, 40);
|
||||
// painter.FillRoundRect(rect2, 40, 40);
|
||||
|
||||
painter.SetFont(font);
|
||||
painter.SetHighColor(0, 20, 80, 255);
|
||||
painter.SetDrawingMode(B_OP_OVER);
|
||||
painter.DrawString(string, stringLocation);
|
||||
|
||||
// bitmap drawing
|
||||
// painter.SetScale(0.5);
|
||||
painter.DrawBitmap(testBitmap, testBitmapCrop, testBitmapDestRect);
|
||||
|
||||
|
||||
painterNow = system_time() - painterNow;
|
||||
printf("Painter: %lld µsecs\n", painterNow);
|
||||
|
||||
BitmapView* painterView = new BitmapView(bounds, "view", bitmap);
|
||||
|
||||
bitmap = new BBitmap(bounds, B_RGB32, true);
|
||||
BView* view = new BView(bounds, NULL, B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
bitmap->Lock();
|
||||
bitmap->AddChild(view);
|
||||
|
||||
view->ConstrainClippingRegion(&clip);
|
||||
view->SetScale(scale);
|
||||
// view->SetPenSize(penSize);
|
||||
view->SetOrigin(origin);
|
||||
|
||||
bigtime_t viewNow = system_time();
|
||||
|
||||
view->SetDrawingMode(B_OP_OVER);
|
||||
view->SetHighColor(210, 210, 210);
|
||||
for (uint32 y = 0; y <= height / 2; y += 10)
|
||||
view->StrokeLine(BPoint(0, 0), BPoint(width / 2, y));
|
||||
for (uint32 x = 0; x <= width; x += 10)
|
||||
view->StrokeLine(BPoint(0, 0), BPoint(x, height));
|
||||
view->SetPenSize(penSize * 5);
|
||||
view->SetHighColor(255, 0, 0, 255);
|
||||
view->SetLowColor(128, 0, 255, 255);
|
||||
// view->SetScale(1.0);
|
||||
// view->SetOrigin(B_ORIGIN);
|
||||
// view->SetDrawingMode(B_OP_INVERT);
|
||||
view->SetDrawingMode(B_OP_COPY);
|
||||
// view->StrokeRect(rect);
|
||||
view->StrokeRect(rect, kStripes);
|
||||
|
||||
// view->ConstrainClippingRegion(&noClip);
|
||||
/* view->MovePenTo(BPoint(230.0, 30.0));
|
||||
view->StrokeLine(BPoint(250.0, 30.0));
|
||||
view->StrokeLine(BPoint(250.0, 50.0));
|
||||
view->StrokeLine(BPoint(230.0, 50.0));
|
||||
view->StrokeLine(BPoint(230.0, 30.0));*/
|
||||
|
||||
view->SetHighColor(255, 255, 0, 255);
|
||||
view->SetLowColor(128, 0, 50, 255);
|
||||
view->SetDrawingMode(B_OP_OVER);
|
||||
view->StrokeEllipse(center, xRadius, yRadius, kDottedBigger);
|
||||
view->SetDrawingMode(B_OP_INVERT);
|
||||
view->SetHighColor(255, 0, 0, 255);
|
||||
view->FillArc(center, xRadius * 2, yRadius * 2, angle, span);
|
||||
// view->StrokeArc(center, xRadius * 2, yRadius * 2, angle, span);
|
||||
view->SetDrawingMode(B_OP_OVER);
|
||||
view->SetPenSize(2.0);
|
||||
view->StrokeEllipse(center, xRadius * 3, yRadius * 2);
|
||||
// view->FillEllipse(center, xRadius * 3, yRadius * 2);
|
||||
// view->StrokeLine(bounds.RightTop());
|
||||
// view->FillRect(rect);
|
||||
view->SetHighColor(0, 0, 255, 255);
|
||||
view->SetPenSize(1.0);
|
||||
view->StrokeRoundRect(rect2, 40, 40);
|
||||
// view->FillRoundRect(rect2, 40, 40);
|
||||
|
||||
// text drawing
|
||||
view->SetFont(&font);
|
||||
view->SetHighColor(0, 20, 80, 255);
|
||||
view->SetDrawingMode(B_OP_OVER);
|
||||
view->DrawString(string, stringLocation);
|
||||
|
||||
// bitmap drawing
|
||||
// view->SetScale(0.5);
|
||||
view->DrawBitmap(testBitmap, testBitmapCrop, testBitmapDestRect);
|
||||
|
||||
view->Sync();
|
||||
|
||||
viewNow = system_time() - viewNow;
|
||||
printf("BView: %lld µsecs\n", viewNow);
|
||||
printf("BView is %lld times faster.\n", painterNow / viewNow);
|
||||
|
||||
bitmap->Unlock();
|
||||
|
||||
BitmapView* bViewView = new BitmapView(bounds, "view", bitmap);
|
||||
bViewView->MoveTo(BPoint(bounds.left, bounds.bottom + 1));
|
||||
|
||||
BWindow* window = new BWindow(BRect(50.0, 50.0, 50.0 + bounds.Width(), 50.0 + bounds.Height() * 2 + 1), "Painter Test",
|
||||
B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
window->AddChild(painterView);
|
||||
window->AddChild(bViewView);
|
||||
|
||||
window->Show();
|
||||
app->Run();
|
||||
delete app;
|
||||
return 0;
|
||||
}
|
122
src/servers/app/server/Painter/makefile
Normal file
122
src/servers/app/server/Painter/makefile
Normal file
@ -0,0 +1,122 @@
|
||||
## BeOS Generic Makefile v2.1 ##
|
||||
|
||||
## Fill in this file to specify the project being created, and the referenced
|
||||
## makefile-engine will do all of the hard work for you. This handles both
|
||||
## Intel and PowerPC builds of the BeOS.
|
||||
|
||||
## Application Specific Settings ---------------------------------------------
|
||||
|
||||
# specify the name of the binary
|
||||
NAME= ../Painter
|
||||
|
||||
# specify the type of binary
|
||||
# APP: Application
|
||||
# SHARED: Shared library or add-on
|
||||
# STATIC: Static library archive
|
||||
# DRIVER: Kernel Driver
|
||||
TYPE= APP
|
||||
|
||||
# add support for new Pe and Eddie features
|
||||
# to fill in generic makefile
|
||||
|
||||
#%{
|
||||
# @src->@
|
||||
|
||||
# specify the source files to use
|
||||
# full paths or paths relative to the makefile can be included
|
||||
# all files, regardless of directory, will have their object
|
||||
# files created in the common object directory.
|
||||
# Note that this means this makefile will not work correctly
|
||||
# if two source files with the same name (source.c or source.cpp)
|
||||
# are included from different directories. Also note that spaces
|
||||
# in folder names do not work well with this makefile.
|
||||
SRCS= drawing_modes/DrawingModeFactory.cpp \
|
||||
drawing_modes/PatternHandler.cpp \
|
||||
font_support/agg_font_freetype.cpp \
|
||||
font_support/AGGTextRenderer.cpp \
|
||||
font_support/FontManager.cpp \
|
||||
font_support/TextRenderer.cpp \
|
||||
BitmapBuffer.cpp \
|
||||
BitmapView.cpp \
|
||||
main.cpp \
|
||||
Painter.cpp \
|
||||
ShapeConverter.cpp \
|
||||
Transformable.cpp \
|
||||
|
||||
# specify the resource files to use
|
||||
# full path or a relative path to the resource file can be used.
|
||||
RSRCS =
|
||||
|
||||
# @<-src@
|
||||
#%}
|
||||
|
||||
# end support for Pe and Eddie
|
||||
|
||||
# specify additional libraries to link against
|
||||
# there are two acceptable forms of library specifications
|
||||
# - if your library follows the naming pattern of:
|
||||
# libXXX.so or libXXX.a you can simply specify XXX
|
||||
# library: libbe.so entry: be
|
||||
#
|
||||
# - if your library does not follow the standard library
|
||||
# naming scheme you need to specify the path to the library
|
||||
# and it's name
|
||||
# library: my_lib.a entry: my_lib.a or path/my_lib.a
|
||||
LIBS= be agg freetype textencoding
|
||||
|
||||
# specify additional paths to directories following the standard
|
||||
# libXXX.so or libXXX.a naming scheme. You can specify full paths
|
||||
# or paths relative to the makefile. The paths included may not
|
||||
# be recursive, so include all of the paths where libraries can
|
||||
# be found. Directories where source files are found are
|
||||
# automatically included.
|
||||
LIBPATHS= /boot/home/config/lib
|
||||
|
||||
# additional paths to look for system headers
|
||||
# thes use the form: #include <header>
|
||||
# source file directories are NOT auto-included here
|
||||
SYSTEM_INCLUDE_PATHS = /boot/home/config/include/agg /boot/home/config/include/
|
||||
|
||||
# additional paths to look for local headers
|
||||
# thes use the form: #include "header"
|
||||
# source file directories are automatically included
|
||||
LOCAL_INCLUDE_PATHS =
|
||||
|
||||
# specify the level of optimization that you desire
|
||||
# NONE, SOME, FULL
|
||||
#OPTIMIZE= SOME
|
||||
OPTIMIZE= SOME
|
||||
|
||||
# specify any preprocessor symbols to be defined. The symbols will not
|
||||
# have their values set automatically; you must supply the value (if any)
|
||||
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
|
||||
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
|
||||
# would pass "-DDEBUG" on the compiler's command line.
|
||||
DEFINES=
|
||||
|
||||
# specify special warning levels
|
||||
# if unspecified default warnings will be used
|
||||
# NONE = supress all warnings
|
||||
# ALL = enable all warnings
|
||||
WARNINGS = ALL
|
||||
|
||||
# specify whether image symbols will be created
|
||||
# so that stack crawls in the debugger are meaningful
|
||||
# if TRUE symbols will be created
|
||||
SYMBOLS = TRUE
|
||||
|
||||
# specify debug settings
|
||||
# if TRUE will allow application to be run from a source-level
|
||||
# debugger. Note that this will disable all optimzation.
|
||||
DEBUGGER =
|
||||
|
||||
# specify additional compiler flags for all files
|
||||
COMPILER_FLAGS =
|
||||
|
||||
# specify additional linker flags
|
||||
LINKER_FLAGS =
|
||||
|
||||
|
||||
## include the makefile-engine
|
||||
include /boot/develop/etc/makefile-engine
|
||||
|
Loading…
x
Reference in New Issue
Block a user