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:
Stephan Aßmus 2005-01-07 01:58:36 +00:00
parent 4b0c008cc5
commit 4569b90da0
33 changed files with 6973 additions and 0 deletions

View 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;
}

View 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

View 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)
{
}

View 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

View 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(&lt);
_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(&lt, 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(&center);
_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(&center);
_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(&lt, 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(&center);
_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);
}

View 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

View 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.

View 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

View 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;
}

View 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

View 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(&lt);
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();
}
}

View 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

View 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

View 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

View 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

View File

@ -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();
}
}

View File

@ -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

View 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

View 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

View 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);
}

View 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

View 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

View 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

View 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);
}

View File

@ -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

View 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;
}

View 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

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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;
}

View 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