1 // Painter.cpp
2
3 #include <stdio.h>
4 #include <string.h>
5
6 #include <Bitmap.h>
7 #include <GraphicsDefs.h>
8 #include <Region.h>
9
10 #include <agg_bezier_arc.h>
11 #include <agg_bounding_rect.h>
12 #include <agg_conv_curve.h>
13 #include <agg_conv_stroke.h>
14 #include <agg_ellipse.h>
15 #include <agg_path_storage.h>
16 #include <agg_rounded_rect.h>
17 #include <agg_span_image_filter_rgba32.h>
18 #include <agg_span_interpolator_linear.h>
19
20 #include "LayerData.h"
21
22 #include "AGGTextRenderer.h"
23 #include "DrawingMode.h"
24 #include "DrawingModeFactory.h"
25 #include "FontManager.h"
26 #include "PatternHandler.h"
27 #include "RenderingBuffer.h"
28 #include "ShapeConverter.h"
29 #include "ServerBitmap.h"
30 #include "ServerFont.h"
31
32 #include "Painter.h"
33
34 int
roundf(float v)35 roundf(float v)
36 {
37 if (v >= 0.0)
38 return (int)floorf(v + 0.5);
39 else
40 return (int)floorf(v - 0.5);
41 }
42
43 // constructor
Painter()44 Painter::Painter()
45 : fBuffer(NULL),
46 fPixelFormat(NULL),
47 fBaseRenderer(NULL),
48 fOutlineRenderer(NULL),
49 fOutlineRasterizer(NULL),
50 fScanline(NULL),
51 fRasterizer(NULL),
52 fRenderer(NULL),
53 fFontRendererSolid(NULL),
54 fFontRendererBin(NULL),
55 fLineProfile(),
56 fSubpixelPrecise(false),
57 fScale(1.0),
58 fPenSize(1.0),
59 fOrigin(0.0, 0.0),
60 fClippingRegion(NULL),
61 fDrawingMode(B_OP_COPY),
62 fAlphaSrcMode(B_PIXEL_ALPHA),
63 // fAlphaSrcMode(B_CONSTANT_ALPHA),
64 fAlphaFncMode(B_ALPHA_OVERLAY),
65 fPenLocation(0.0, 0.0),
66 fPatternHandler(new PatternHandler()),
67 fTextRenderer(new AGGTextRenderer()),
68 fLastFamilyAndStyle(0)
69 {
70 if (fontserver)
71 fFont = *fontserver->GetSystemPlain();
72
73 _UpdateFont();
74 _UpdateLineWidth();
75 }
76
77 // destructor
~Painter()78 Painter::~Painter()
79 {
80 _MakeEmpty();
81
82 delete fClippingRegion;
83 delete fPatternHandler;
84 delete fTextRenderer;
85 }
86
87 // #pragma mark -
88
89 // AttachToBuffer
90 void
AttachToBuffer(RenderingBuffer * buffer)91 Painter::AttachToBuffer(RenderingBuffer* buffer)
92 {
93 if (buffer && buffer->InitCheck() >= B_OK) {
94 // clean up previous stuff
95 _MakeEmpty();
96
97 fBuffer = new agg::rendering_buffer();
98 fBuffer->attach((uint8*)buffer->Bits(),
99 buffer->Width(),
100 buffer->Height(),
101 buffer->BytesPerRow());
102
103 fPixelFormat = new pixfmt(*fBuffer, fPatternHandler);
104 fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode,
105 fAlphaSrcMode,
106 fAlphaFncMode,
107 false));
108
109 fBaseRenderer = new renderer_base(*fPixelFormat);
110
111 // These are the AGG renderes and rasterizes which
112 // will be used for stroking paths
113 rgb_color color = fPatternHandler->HighColor().GetColor32();
114 #if ALIASED_DRAWING
115 fOutlineRenderer = new outline_renderer_type(*fBaseRenderer);
116 fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
117 #else
118 fOutlineRenderer = new outline_renderer_type(*fBaseRenderer, fLineProfile);
119 fOutlineRasterizer = new outline_rasterizer_type(*fOutlineRenderer);
120
121 // attach our line profile to the renderer, it keeps a pointer
122 fOutlineRenderer->profile(fLineProfile);
123 #endif
124 // the renderer used for filling paths
125 fRenderer = new renderer_type(*fBaseRenderer);
126 fRasterizer = new rasterizer_type();
127 fScanline = new scanline_type();
128
129 #if ALIASED_DRAWING
130 fRasterizer->gamma(agg::gamma_threshold(0.5));
131 #endif
132
133 // These are renderers needed for drawing text
134 fFontRendererSolid = new font_renderer_solid_type(*fBaseRenderer);
135 fFontRendererBin = new font_renderer_bin_type(*fBaseRenderer);
136
137 _SetRendererColor(fPatternHandler->HighColor().GetColor32());
138 _RebuildClipping();
139 }
140 }
141
142 // DetachFromBuffer
143 void
DetachFromBuffer()144 Painter::DetachFromBuffer()
145 {
146 _MakeEmpty();
147 }
148
149 // SetDrawData
150 void
SetDrawData(const DrawData * data)151 Painter::SetDrawData(const DrawData* data)
152 {
153 // for now...
154 SetHighColor(data->highcolor.GetColor32());
155 SetLowColor(data->lowcolor.GetColor32());
156 SetScale(data->scale);
157 SetPenSize(data->pensize);
158 // fOrigin = data->coordOrigin;
159 SetDrawingMode(data->draw_mode);
160 SetBlendingMode(data->alphaSrcMode, data->alphaFncMode);
161 SetPenLocation(data->penlocation);
162 SetFont(data->font);
163 // if (data->clipReg) {
164 // ConstrainClipping(*data->clipReg);
165 // }
166 fPatternHandler->SetPattern(data->patt);
167 }
168
169 // #pragma mark -
170
171 // ConstrainClipping
172 void
ConstrainClipping(const BRegion & region)173 Painter::ConstrainClipping(const BRegion& region)
174 {
175 // The idea is that if the clipping region was
176 // never constrained, there is *no* clipping.
177 // This is of course different from having
178 // an *empty* clipping region.
179 if (!fClippingRegion)
180 fClippingRegion = new BRegion(region);
181 else
182 *fClippingRegion = region;
183 _RebuildClipping();
184 }
185
186 // SetHighColor
187 void
SetHighColor(const rgb_color & color)188 Painter::SetHighColor(const rgb_color& color)
189 {
190 fPatternHandler->SetHighColor(color);
191 }
192
193 // SetLowColor
194 void
SetLowColor(const rgb_color & color)195 Painter::SetLowColor(const rgb_color& color)
196 {
197 fPatternHandler->SetLowColor(color);;
198 }
199
200 // SetScale
201 void
SetScale(float scale)202 Painter::SetScale(float scale)
203 {
204 if (fScale != scale) {
205 fScale = scale;
206 _RebuildClipping();
207 _UpdateLineWidth();
208 }
209 }
210
211 // SetPenSize
212 void
SetPenSize(float size)213 Painter::SetPenSize(float size)
214 {
215 if (fPenSize != size) {
216 fPenSize = size;
217 _UpdateLineWidth();
218 }
219 }
220
221 // SetOrigin
222 void
SetOrigin(const BPoint & origin)223 Painter::SetOrigin(const BPoint& origin)
224 {
225 // NOTE: The BeBook says that the coordinate system
226 // of a view cannot be changed during an update, because
227 // it would mess up the clipping, and this is indeed
228 // what would happen in this implementation as well.
229 // I don't know yet what actually happens if you still
230 // try to call SetOrigin() from within BView::Draw()
231 fOrigin = origin;
232 _RebuildClipping();
233 }
234
235 // SetDrawingMode
236 void
SetDrawingMode(drawing_mode mode)237 Painter::SetDrawingMode(drawing_mode mode)
238 {
239 if (fDrawingMode != mode) {
240 fDrawingMode = mode;
241 if (fPixelFormat) {
242 fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode,
243 fAlphaSrcMode,
244 fAlphaFncMode));
245 }
246 }
247 }
248
249 // SetBlendingMode
250 void
SetBlendingMode(source_alpha alphaSrcMode,alpha_function alphaFncMode)251 Painter::SetBlendingMode(source_alpha alphaSrcMode, alpha_function alphaFncMode)
252 {
253 if (fAlphaSrcMode != alphaSrcMode || fAlphaFncMode != alphaFncMode) {
254 fAlphaSrcMode = alphaSrcMode;
255 fAlphaFncMode = alphaFncMode;
256 if (fDrawingMode == B_OP_ALPHA && fPixelFormat) {
257 fPixelFormat->set_drawing_mode(DrawingModeFactory::DrawingModeFor(fDrawingMode,
258 fAlphaSrcMode,
259 fAlphaFncMode));
260 }
261 }
262 }
263
264 // SetPenLocation
265 void
SetPenLocation(const BPoint & location)266 Painter::SetPenLocation(const BPoint& location)
267 {
268 fPenLocation = location;
269 }
270
271 // SetFont
272 void
SetFont(const BFont & font)273 Painter::SetFont(const BFont& font)
274 {
275 //fFont.SetFamilyAndStyle(font.GetFamily(), font.GetStyle());
276 fFont.SetSpacing(font.Spacing());
277 fFont.SetShear(font.Shear());
278 fFont.SetRotation(font.Rotation());
279 fFont.SetSize(font.Size());
280
281 _UpdateFont();
282 }
283
284 // SetFont
285 void
SetFont(const ServerFont & font)286 Painter::SetFont(const ServerFont& font)
287 {
288 fFont = font;
289 _UpdateFont();
290 }
291
292 // #pragma mark -
293
294 // StrokeLine
295 BRect
StrokeLine(BPoint a,BPoint b,const pattern & p)296 Painter::StrokeLine(BPoint a, BPoint b, const pattern& p)
297 {
298 _Transform(&a);
299 _Transform(&b);
300
301 BRect touched(a, b);
302
303 // first, try an optimized version
304 float penSize = _Transform(fPenSize);
305 if (penSize == 1.0 &&
306 (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) {
307 pattern pat = *fPatternHandler->GetR5Pattern();
308 if (pat == B_SOLID_HIGH &&
309 StraightLine(a, b, fPatternHandler->HighColor().GetColor32())) {
310 SetPenLocation(b);
311 return _Clipped(touched);
312 } else if (pat == B_SOLID_LOW &&
313 StraightLine(a, b, fPatternHandler->LowColor().GetColor32())) {
314 SetPenLocation(b);
315 return _Clipped(touched);
316 }
317 }
318
319 agg::path_storage path;
320 path.move_to(a.x, a.y);
321 path.line_to(b.x, b.y);
322
323 touched = _StrokePath(path, p);
324
325 SetPenLocation(b);
326
327 return _Clipped(touched);
328 }
329
330 // StrokeLine
331 BRect
StrokeLine(BPoint b,const pattern & p)332 Painter::StrokeLine(BPoint b, const pattern& p)
333 {
334 // TODO: move this function elsewhere
335 return StrokeLine(fPenLocation, b);
336 }
337
338 // StraightLine
339 bool
StraightLine(BPoint a,BPoint b,const rgb_color & c) const340 Painter::StraightLine(BPoint a, BPoint b, const rgb_color& c) const
341 {
342 if (fBuffer) {
343 if (a.x == b.x) {
344 // vertical
345 uint8* dst = fBuffer->row(0);
346 uint32 bpr = fBuffer->stride();
347 int32 x = (int32)a.x;
348 dst += x * 4;
349 int32 y1 = (int32)min_c(a.y, b.y);
350 int32 y2 = (int32)max_c(a.y, b.y);
351 // draw a line, iterate over clipping boxes
352 fBaseRenderer->first_clip_box();
353 do {
354 if (fBaseRenderer->xmin() <= x &&
355 fBaseRenderer->xmax() >= x) {
356 int32 i = max_c(fBaseRenderer->ymin(), y1);
357 int32 end = min_c(fBaseRenderer->ymax(), y2);
358 uint8* handle = dst + i * bpr;
359 for (; i <= end; i++) {
360 handle[0] = c.blue;
361 handle[1] = c.green;
362 handle[2] = c.red;
363 handle += bpr;
364 }
365 }
366 } while (fBaseRenderer->next_clip_box());
367
368 return true;
369
370 } else if (a.y == b.y) {
371 // horizontal
372 uint8* dst = fBuffer->row(0);
373 uint32 bpr = fBuffer->stride();
374 int32 y = (int32)a.y;
375 dst += y * bpr;
376 int32 x1 = (int32)min_c(a.x, b.x);
377 int32 x2 = (int32)max_c(a.x, b.x);
378 // draw a line, iterate over clipping boxes
379 fBaseRenderer->first_clip_box();
380 do {
381 if (fBaseRenderer->ymin() <= y &&
382 fBaseRenderer->ymax() >= y) {
383 int32 i = max_c(fBaseRenderer->xmin(), x1);
384 int32 end = min_c(fBaseRenderer->xmax(), x2);
385 uint8* handle = dst + i * 4;
386 for (; i <= end; i++) {
387 handle[0] = c.blue;
388 handle[1] = c.green;
389 handle[2] = c.red;
390 handle += 4;
391 }
392 }
393 } while (fBaseRenderer->next_clip_box());
394
395 return true;
396 }
397 }
398 return false;
399 }
400
401 // #pragma mark -
402
403 // StrokeTriangle
404 void
StrokeTriangle(BPoint pt1,BPoint pt2,BPoint pt3,const pattern & p) const405 Painter::StrokeTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const pattern& p) const
406 {
407 _DrawTriangle(pt1, pt2, pt3, p, false);
408 }
409
410 // FillTriangle
411 void
FillTriangle(BPoint pt1,BPoint pt2,BPoint pt3,const pattern & p) const412 Painter::FillTriangle(BPoint pt1, BPoint pt2, BPoint pt3, const pattern& p) const
413 {
414 _DrawTriangle(pt1, pt2, pt3, p, true);
415 }
416
417 // StrokePolygon
418 void
StrokePolygon(const BPoint * ptArray,int32 numPts,bool closed,const pattern & p) const419 Painter::StrokePolygon(const BPoint* ptArray, int32 numPts,
420 bool closed, const pattern& p) const
421 {
422 _DrawPolygon(ptArray, numPts, closed, p, false);
423 }
424
425 // FillPolygon
426 void
FillPolygon(const BPoint * ptArray,int32 numPts,bool closed,const pattern & p) const427 Painter::FillPolygon(const BPoint* ptArray, int32 numPts,
428 bool closed, const pattern& p) const
429 {
430 _DrawPolygon(ptArray, numPts, closed, p, true);
431 }
432
433 // StrokeBezier
434 void
StrokeBezier(const BPoint * controlPoints,const pattern & p) const435 Painter::StrokeBezier(const BPoint* controlPoints, const pattern& p) const
436 {
437 agg::path_storage curve;
438
439 BPoint p1(controlPoints[0]);
440 BPoint p2(controlPoints[1]);
441 BPoint p3(controlPoints[2]);
442 BPoint p4(controlPoints[3]);
443 _Transform(&p1);
444 _Transform(&p2);
445 _Transform(&p3);
446 _Transform(&p4);
447
448 curve.move_to(p1.x, p1.y);
449 curve.curve4(p1.x, p1.y,
450 p2.x, p2.y,
451 p3.x, p3.y);
452
453
454 agg::conv_curve<agg::path_storage> path(curve);
455
456 _StrokePath(path, p);
457 }
458
459 // FillBezier
460 void
FillBezier(const BPoint * controlPoints,const pattern & p) const461 Painter::FillBezier(const BPoint* controlPoints, const pattern& p) const
462 {
463 agg::path_storage curve;
464
465 BPoint p1(controlPoints[0]);
466 BPoint p2(controlPoints[1]);
467 BPoint p3(controlPoints[2]);
468 BPoint p4(controlPoints[3]);
469 _Transform(&p1);
470 _Transform(&p2);
471 _Transform(&p3);
472 _Transform(&p4);
473
474 curve.move_to(p1.x, p1.y);
475 curve.curve4(p1.x, p1.y,
476 p2.x, p2.y,
477 p3.x, p3.y);
478 curve.close_polygon();
479
480 agg::conv_curve<agg::path_storage> path(curve);
481
482 _FillPath(path, p);
483 }
484
485 // StrokeShape
486 void
StrokeShape(BShape * shape,const pattern & p) const487 Painter::StrokeShape(/*const */BShape* shape, const pattern& p) const
488 {
489 _DrawShape(shape, p, false);
490 }
491
492 // FillShape
493 void
FillShape(BShape * shape,const pattern & p) const494 Painter::FillShape(/*const */BShape* shape, const pattern& p) const
495 {
496 _DrawShape(shape, p, true);
497 }
498
499 // StrokeRect
500 BRect
StrokeRect(const BRect & r,const pattern & p) const501 Painter::StrokeRect(const BRect& r, const pattern& p) const
502 {
503 BPoint a(r.left, r.top);
504 BPoint b(r.right, r.bottom);
505 _Transform(&a);
506 _Transform(&b);
507
508 // first, try an optimized version
509 float penSize = _Transform(fPenSize);
510 if (penSize == 1.0 &&
511 (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) {
512 // TODO: fix me
513 // pattern p = *fPatternHandler->GetR5Pattern();
514 if (p == B_SOLID_HIGH) {
515 BRect rect(a, b);
516 StrokeRect(rect,
517 fPatternHandler->HighColor().GetColor32());
518 return _Clipped(rect);
519 } else if (p == B_SOLID_LOW) {
520 BRect rect(a, b);
521 StrokeRect(rect,
522 fPatternHandler->LowColor().GetColor32());
523 return _Clipped(rect);
524 }
525 }
526
527 agg::path_storage path;
528 path.move_to(a.x, a.y);
529 path.line_to(b.x, a.y);
530 path.line_to(b.x, b.y);
531 path.line_to(a.x, b.y);
532 path.close_polygon();
533
534 return _StrokePath(path, p);
535 }
536
537 // StrokeRect
538 void
StrokeRect(const BRect & r,const rgb_color & c) const539 Painter::StrokeRect(const BRect& r, const rgb_color& c) const
540 {
541 StraightLine(BPoint(r.left, r.top),
542 BPoint(r.right - 1, r.top), c);
543 StraightLine(BPoint(r.right, r.top),
544 BPoint(r.right, r.bottom - 1), c);
545 StraightLine(BPoint(r.right, r.bottom),
546 BPoint(r.left + 1, r.bottom), c);
547 StraightLine(BPoint(r.left, r.bottom),
548 BPoint(r.left, r.top + 1), c);
549 }
550
551 // FillRect
552 BRect
FillRect(const BRect & r,const pattern & p) const553 Painter::FillRect(const BRect& r, const pattern& p) const
554 {
555 BPoint a(r.left, r.top);
556 BPoint b(r.right, r.bottom);
557 _Transform(&a, false);
558 _Transform(&b, false);
559
560 // first, try an optimized version
561 if (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER) {
562 pattern pat = *fPatternHandler->GetR5Pattern();
563 if (pat == B_SOLID_HIGH) {
564 BRect rect(a, b);
565 FillRect(rect, fPatternHandler->HighColor().GetColor32());
566 return _Clipped(rect);
567 } else if (pat == B_SOLID_LOW) {
568 BRect rect(a, b);
569 FillRect(rect, fPatternHandler->LowColor().GetColor32());
570 return _Clipped(rect);
571 }
572 }
573
574 // account for stricter interpretation of coordinates in AGG
575 // the rectangle ranges from the top-left (.0, .0)
576 // to the bottom-right (.9999, .9999) corner of pixels
577 b.x += 1.0;
578 b.y += 1.0;
579
580 agg::path_storage path;
581 path.move_to(a.x, a.y);
582 path.line_to(b.x, a.y);
583 path.line_to(b.x, b.y);
584 path.line_to(a.x, b.y);
585 path.close_polygon();
586
587 return _FillPath(path, p);
588 }
589
590 // FillRect
591 void
FillRect(const BRect & r,const rgb_color & c) const592 Painter::FillRect(const BRect& r, const rgb_color& c) const
593 {
594 if (fBuffer) {
595 uint8* dst = fBuffer->row(0);
596 uint32 bpr = fBuffer->stride();
597 int32 left = (int32)r.left;
598 int32 top = (int32)r.top;
599 int32 right = (int32)r.right;
600 int32 bottom = (int32)r.bottom;
601 // fill rects, iterate over clipping boxes
602 fBaseRenderer->first_clip_box();
603 do {
604 int32 x1 = max_c(fBaseRenderer->xmin(), left);
605 int32 x2 = min_c(fBaseRenderer->xmax(), right);
606 if (x1 <= x2) {
607 int32 y1 = max_c(fBaseRenderer->ymin(), top);
608 int32 y2 = min_c(fBaseRenderer->ymax(), bottom);
609 uint8* offset = dst + x1 * 4;
610 for (; y1 <= y2; y1++) {
611 uint8* handle = offset + y1 * bpr;
612 for (int32 x = x1; x <= x2; x++) {
613 handle[0] = c.blue;
614 handle[1] = c.green;
615 handle[2] = c.red;
616 handle += 4;
617 }
618 }
619 }
620 } while (fBaseRenderer->next_clip_box());
621 }
622 }
623
624 // StrokeRoundRect
625 void
StrokeRoundRect(const BRect & r,float xRadius,float yRadius,const pattern & p) const626 Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius,
627 const pattern& p) const
628 {
629 BPoint lt(r.left, r.top);
630 BPoint rb(r.right, r.bottom);
631 _Transform(<);
632 _Transform(&rb);
633
634 _Transform(&xRadius);
635 _Transform(&yRadius);
636
637 agg::rounded_rect rect;
638 rect.rect(lt.x, lt.y, rb.x, rb.y);
639 rect.radius(xRadius, yRadius);
640
641 _StrokePath(rect, p);
642 }
643
644 // FillRoundRect
645 void
FillRoundRect(const BRect & r,float xRadius,float yRadius,const pattern & p) const646 Painter::FillRoundRect(const BRect& r, float xRadius, float yRadius,
647 const pattern& p) const
648 {
649 BPoint lt(r.left, r.top);
650 BPoint rb(r.right, r.bottom);
651 _Transform(<, false);
652 _Transform(&rb, false);
653
654 // account for stricter interpretation of coordinates in AGG
655 // the rectangle ranges from the top-left (.0, .0)
656 // to the bottom-right (.9999, .9999) corner of pixels
657 rb.x += 1.0;
658 rb.y += 1.0;
659
660 _Transform(&xRadius);
661 _Transform(&yRadius);
662
663 agg::rounded_rect rect;
664 rect.rect(lt.x, lt.y, rb.x, rb.y);
665 rect.radius(xRadius, yRadius);
666
667 _FillPath(rect, p);
668 }
669
670 // StrokeEllipse
671 void
StrokeEllipse(BPoint center,float xRadius,float yRadius,const pattern & p) const672 Painter::StrokeEllipse(BPoint center, float xRadius, float yRadius,
673 const pattern& p) const
674 {
675 _DrawEllipse(center, xRadius, yRadius, p, false);
676 }
677
678 // FillEllipse
679 void
FillEllipse(BPoint center,float xRadius,float yRadius,const pattern & p) const680 Painter::FillEllipse(BPoint center, float xRadius, float yRadius,
681 const pattern& p) const
682 {
683 _DrawEllipse(center, xRadius, yRadius, p, true);
684 }
685
686 // StrokeArc
687 void
StrokeArc(BPoint center,float xRadius,float yRadius,float angle,float span,const pattern & p) const688 Painter::StrokeArc(BPoint center, float xRadius, float yRadius,
689 float angle, float span, const pattern& p) const
690 {
691 _Transform(¢er);
692 _Transform(&xRadius);
693 _Transform(&yRadius);
694
695 double angleRad = (angle * PI) / 180.0;
696 double spanRad = (span * PI) / 180.0;
697 agg::bezier_arc arc(center.x, center.y, xRadius, yRadius,
698 -angleRad, -spanRad);
699
700 agg::conv_curve<agg::bezier_arc> path(arc);
701
702 _StrokePath(path, p);
703 }
704
705 // FillArc
706 void
FillArc(BPoint center,float xRadius,float yRadius,float angle,float span,const pattern & p) const707 Painter::FillArc(BPoint center, float xRadius, float yRadius,
708 float angle, float span, const pattern& p) const
709 {
710 _Transform(¢er);
711 _Transform(&xRadius);
712 _Transform(&yRadius);
713
714 double angleRad = (angle * PI) / 180.0;
715 double spanRad = (span * PI) / 180.0;
716 agg::bezier_arc arc(center.x, center.y, xRadius, yRadius,
717 -angleRad, -spanRad);
718
719 agg::conv_curve<agg::bezier_arc> segmentedArc(arc);
720
721 agg::path_storage path;
722
723 // build a new path by starting at the center point,
724 // then traversing the arc, then going back to the center
725 path.move_to(center.x, center.y);
726
727 segmentedArc.rewind(0);
728 double x;
729 double y;
730 unsigned cmd = segmentedArc.vertex(&x, &y);
731 while (!agg::is_stop(cmd)) {
732 path.line_to(x, y);
733 cmd = segmentedArc.vertex(&x, &y);
734 }
735
736 path.close_polygon();
737
738 _FillPath(path, p);
739 }
740
741 // #pragma mark -
742
743 // DrawChar
744 BRect
DrawChar(char aChar)745 Painter::DrawChar(char aChar)
746 {
747 // TODO: to be moved elsewhere
748 return DrawChar(aChar, fPenLocation);
749 }
750
751 // DrawChar
752 BRect
DrawChar(char aChar,BPoint baseLine)753 Painter::DrawChar(char aChar, BPoint baseLine)
754 {
755 // TODO: to be moved elsewhere
756 char wrapper[2];
757 wrapper[0] = aChar;
758 wrapper[1] = 0;
759 return DrawString(wrapper, 1, baseLine);
760 }
761
762 // DrawString
763 BRect
DrawString(const char * utf8String,uint32 length,const escapement_delta * delta)764 Painter::DrawString(const char* utf8String, uint32 length,
765 const escapement_delta* delta)
766 {
767 // TODO: to be moved elsewhere
768 return DrawString(utf8String, length, fPenLocation, delta);
769 }
770
771 // DrawString
772 BRect
DrawString(const char * utf8String,uint32 length,BPoint baseLine,const escapement_delta * delta)773 Painter::DrawString(const char* utf8String, uint32 length,
774 BPoint baseLine, const escapement_delta* delta)
775 {
776 BRect bounds(0.0, 0.0, -1.0, -1.0);
777 fPatternHandler->SetPattern(B_SOLID_HIGH);
778
779 if (fBuffer) {
780
781 Transformable transform;
782 transform.ShearBy(B_ORIGIN, (90.0 - fFont.Shear()) * PI / 180.0, 0.0);
783 transform.RotateBy(B_ORIGIN, -fFont.Rotation() * PI / 180.0);
784 transform.TranslateBy(baseLine);
785 transform.ScaleBy(B_ORIGIN, fScale, fScale);
786 transform.TranslateBy(fOrigin);
787
788 BRect clippingFrame;
789 if (fClippingRegion)
790 clippingFrame = _Transform(fClippingRegion->Frame());
791
792 bounds = fTextRenderer->RenderString(utf8String,
793 length,
794 fFontRendererSolid,
795 fFontRendererBin,
796 transform,
797 clippingFrame,
798 false,
799 &fPenLocation);
800 // pen location is not transformed in quite the same way,
801 // or transformations would add up
802 transform.Reset();
803 transform.RotateBy(B_ORIGIN, -fFont.Rotation());
804 transform.TranslateBy(baseLine);
805 transform.Transform(&fPenLocation);
806 }
807 return _Clipped(bounds);
808 }
809
810 // DrawString
811 BRect
DrawString(const char * utf8String,const escapement_delta * delta)812 Painter::DrawString(const char* utf8String, const escapement_delta* delta)
813 {
814 // TODO: to be moved elsewhere
815 return DrawString(utf8String, strlen(utf8String), fPenLocation, delta);
816 }
817
818 // DrawString
819 BRect
DrawString(const char * utf8String,BPoint baseLine,const escapement_delta * delta)820 Painter::DrawString(const char* utf8String, BPoint baseLine,
821 const escapement_delta* delta)
822 {
823 // TODO: to be moved elsewhere
824 return DrawString(utf8String, strlen(utf8String), baseLine, delta);
825 }
826
827 // #pragma mark -
828
829 // DrawBitmap
830 void
DrawBitmap(const BBitmap * bitmap,BRect bitmapRect,BRect viewRect) const831 Painter::DrawBitmap(const BBitmap* bitmap,
832 BRect bitmapRect, BRect viewRect) const
833 {
834 if (bitmap && bitmap->IsValid()) {
835 // the native bitmap coordinate system
836 // (can have left top corner offset)
837 BRect actualBitmapRect(bitmap->Bounds());
838
839 agg::rendering_buffer srcBuffer;
840 srcBuffer.attach((uint8*)bitmap->Bits(),
841 (uint32)actualBitmapRect.IntegerWidth() + 1,
842 (uint32)actualBitmapRect.IntegerHeight() + 1,
843 bitmap->BytesPerRow());
844
845 _DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect);
846 }
847 }
848
849 // DrawBitmap
850 void
DrawBitmap(const ServerBitmap * bitmap,BRect bitmapRect,BRect viewRect) const851 Painter::DrawBitmap(const ServerBitmap* bitmap,
852 BRect bitmapRect, BRect viewRect) const
853 {
854 if (bitmap && bitmap->InitCheck()) {
855 // the native bitmap coordinate system
856 BRect actualBitmapRect(bitmap->Bounds());
857
858 agg::rendering_buffer srcBuffer;
859 srcBuffer.attach(bitmap->Bits(),
860 bitmap->Width(),
861 bitmap->Height(),
862 bitmap->BytesPerRow());
863
864 _DrawBitmap(srcBuffer, bitmap->ColorSpace(), actualBitmapRect, bitmapRect, viewRect);
865 }
866 }
867
868 // #pragma mark -
869
870 // FillRegion
871 void
FillRegion(const BRegion * region,const pattern & p=B_SOLID_HIGH) const872 Painter::FillRegion(const BRegion* region, const pattern& p = B_SOLID_HIGH) const
873 {
874 BRegion copy(*region);
875 int32 count = copy.CountRects();
876 for (int32 i = 0; i < count; i++) {
877 FillRect(copy.RectAt(i), p);
878 }
879 }
880
881 // InvertRect
882 void
InvertRect(const BRect & r) const883 Painter::InvertRect(const BRect& r) const
884 {
885 BRegion region(r);
886 if (fClippingRegion) {
887 region.IntersectWith(fClippingRegion);
888 }
889 // implementation only for B_RGB32 at the moment
890 int32 count = region.CountRects();
891 for (int32 i = 0; i < count; i++) {
892 BRect r = region.RectAt(i);
893 _Transform(&r);
894 _InvertRect32(r);
895 }
896 }
897
898 // BoundingBox
899 BRect
BoundingBox(const char * utf8String,uint32 length,const BPoint & baseLine) const900 Painter::BoundingBox(const char* utf8String, uint32 length,
901 const BPoint& baseLine) const
902 {
903 Transformable transform;
904 transform.TranslateBy(baseLine);
905
906 BRect dummy;
907 return fTextRenderer->RenderString(utf8String,
908 length,
909 fFontRendererSolid,
910 fFontRendererBin,
911 transform, dummy, true);
912 }
913
914 // #pragma mark -
915
916 // _MakeEmpty
917 void
_MakeEmpty()918 Painter::_MakeEmpty()
919 {
920 delete fBuffer;
921 fBuffer = NULL;
922
923 delete fPixelFormat;
924 fPixelFormat = NULL;
925
926 delete fBaseRenderer;
927 fBaseRenderer = NULL;
928
929 delete fOutlineRenderer;
930 fOutlineRenderer = NULL;
931
932 delete fOutlineRasterizer;
933 fOutlineRasterizer = NULL;
934
935 delete fScanline;
936 fScanline = NULL;
937
938 delete fRasterizer;
939 fRasterizer = NULL;
940
941 delete fRenderer;
942 fRenderer = NULL;
943
944 delete fFontRendererSolid;
945 fFontRendererSolid = NULL;
946
947 delete fFontRendererBin;
948 fFontRendererBin = NULL;
949 }
950
951 // _Transform
952 void
_Transform(BPoint * point,bool centerOffset) const953 Painter::_Transform(BPoint* point, bool centerOffset) const
954 {
955 *point += fOrigin;
956 // rounding
957 if (!fSubpixelPrecise) {
958 // TODO: validate usage of floor() for values < 0
959 point->x = floorf(point->x);
960 point->y = floorf(point->y);
961 }
962 // apply the scale
963 point->x *= fScale;
964 point->y *= fScale;
965 // this code is supposed to move coordinates to the center of pixels,
966 // as AGG considers (0,0) to be the "upper left corner" of a pixel,
967 // but BViews are less strict on those details
968 if (centerOffset) {
969 point->x += 0.5;
970 point->y += 0.5;
971 }
972 }
973
974 // _Transform
975 BPoint
_Transform(const BPoint & point,bool centerOffset) const976 Painter::_Transform(const BPoint& point, bool centerOffset) const
977 {
978 BPoint ret = point;
979 _Transform(&ret, centerOffset);
980 return ret;
981 }
982
983 // _Transform
984 void
_Transform(float * width) const985 Painter::_Transform(float* width) const
986 {
987 *width *= fScale;
988 if (*width < 1)
989 *width = 1;
990 }
991
992 // _Transform
993 float
_Transform(const float & width) const994 Painter::_Transform(const float& width) const
995 {
996 float w = width * fScale;
997 if (w < 1)
998 w = 1;
999 return w;
1000 }
1001
1002 // _Transform
1003 void
_Transform(BRect * rect) const1004 Painter::_Transform(BRect* rect) const
1005 {
1006 // TODO integrate this function more
1007 rect->right++;
1008 rect->bottom++;
1009 rect->left += fOrigin.x;
1010 rect->top += fOrigin.y;
1011 rect->right += fOrigin.x;
1012 rect->bottom += fOrigin.y;
1013 rect->left *= fScale;
1014 rect->top *= fScale;
1015 rect->right *= fScale;
1016 rect->bottom *= fScale;
1017 rect->right--;
1018 rect->bottom--;
1019 }
1020
1021 // _Transform
1022 BRect
_Transform(const BRect & rect) const1023 Painter::_Transform(const BRect& rect) const
1024 {
1025 BRect ret = rect;
1026 _Transform(&ret);
1027 return ret;
1028 }
1029
1030 // _Clipped
1031 BRect
_Clipped(const BRect & rect) const1032 Painter::_Clipped(const BRect& rect) const
1033 {
1034 if (rect.IsValid() && fClippingRegion)
1035 return rect & _Transform(fClippingRegion->Frame());
1036 return rect;
1037 }
1038
1039 // #pragma mark -
1040
1041 // _RebuildClipping
1042 void
_RebuildClipping()1043 Painter::_RebuildClipping()
1044 {
1045 if (fBaseRenderer) {
1046 fBaseRenderer->reset_clipping(!fClippingRegion);
1047 if (fClippingRegion) {
1048 int32 count = fClippingRegion->CountRects();
1049 for (int32 i = 0; i < count; i++) {
1050 BRect r = fClippingRegion->RectAt(i);
1051 // NOTE: The rounding here appears to give somewhat
1052 // different results compared to Be's implementation,
1053 // though I was unable to figure out the difference
1054 BPoint lt(r.LeftTop());
1055 BPoint rb(r.RightBottom());
1056 // offset to bottom right corner of pixel before transformation
1057 rb += BPoint(1.0, 1.0);
1058 // apply transformation
1059 lt += fOrigin;
1060 lt.x *= fScale;
1061 lt.y *= fScale;
1062 rb += fOrigin;
1063 rb.x *= fScale;
1064 rb.y *= fScale;
1065 // undo offset to bottom right corner after transformation
1066 rb -= BPoint(1.0, 1.0);
1067 // fBaseRenderer->add_clip_box(floorf(lt.x),
1068 // floorf(lt.y),
1069 // ceilf(rb.x),
1070 // ceilf(rb.y));
1071 fBaseRenderer->add_clip_box(roundf(lt.x),
1072 roundf(lt.y),
1073 roundf(rb.x),
1074 roundf(rb.y));
1075 }
1076 }
1077 }
1078 }
1079
1080 // _UpdateFont
1081 void
_UpdateFont()1082 Painter::_UpdateFont()
1083 {
1084 if (fLastFamilyAndStyle != fFont.GetFamilyAndStyle()) {
1085 fLastFamilyAndStyle = fFont.GetFamilyAndStyle();
1086
1087 bool success = false;
1088 success = fTextRenderer->SetFont(fFont);
1089 if (!success)
1090 fprintf(stderr, "unable to set font\n");
1091 }
1092
1093 fTextRenderer->SetPointSize(fFont.Size());
1094 }
1095
1096 // _UpdateLineWidth
1097 void
_UpdateLineWidth()1098 Painter::_UpdateLineWidth()
1099 {
1100 float width = fPenSize;
1101 _Transform(&width);
1102
1103 fLineProfile.width(width);
1104 }
1105
1106 // #pragma mark -
1107
1108 // _DrawTriangle
1109 inline void
_DrawTriangle(BPoint pt1,BPoint pt2,BPoint pt3,const pattern & p,bool fill) const1110 Painter::_DrawTriangle(BPoint pt1, BPoint pt2, BPoint pt3,
1111 const pattern& p, bool fill) const
1112 {
1113 _Transform(&pt1);
1114 _Transform(&pt2);
1115 _Transform(&pt3);
1116
1117 agg::path_storage path;
1118
1119 path.move_to(pt1.x, pt1.y);
1120 path.line_to(pt2.x, pt2.y);
1121 path.line_to(pt3.x, pt3.y);
1122
1123 path.close_polygon();
1124
1125 if (fill)
1126 _FillPath(path, p);
1127 else
1128 _StrokePath(path, p);
1129 }
1130
1131 // _DrawEllipse
1132 inline void
_DrawEllipse(BPoint center,float xRadius,float yRadius,const pattern & p,bool fill) const1133 Painter::_DrawEllipse(BPoint center, float xRadius, float yRadius,
1134 const pattern& p, bool fill) const
1135 {
1136 // TODO: I think the conversion and the offset of
1137 // pixel centers might not be correct here, and it
1138 // might even be necessary to treat Fill and Stroke
1139 // differently, as with Fill-/StrokeRect().
1140 _Transform(¢er);
1141 _Transform(&xRadius);
1142 _Transform(&yRadius);
1143
1144 float width = fPenSize;
1145 _Transform(&width);
1146
1147 int32 divisions = (int32)max_c(12, ((xRadius + yRadius) * PI) / 2 * (int32)width);
1148
1149 agg::ellipse path(center.x, center.y, xRadius, yRadius, divisions);
1150
1151 if (fill)
1152 _FillPath(path, p);
1153 else
1154 _StrokePath(path, p);
1155 }
1156
1157 // _DrawShape
1158 inline void
_DrawShape(BShape * shape,const pattern & p,bool fill) const1159 Painter::_DrawShape(/*const */BShape* shape, const pattern& p, bool fill) const
1160 {
1161 // TODO: untested
1162 agg::path_storage path;
1163 ShapeConverter converter(&path);
1164
1165 // account for our view coordinate system
1166 converter.ScaleBy(B_ORIGIN, fScale, fScale);
1167 converter.TranslateBy(fOrigin);
1168 // offset locations to center of pixels
1169 converter.TranslateBy(BPoint(0.5, 0.5));
1170
1171 converter.Iterate(shape);
1172
1173 if (fill)
1174 _FillPath(path, p);
1175 else
1176 _StrokePath(path, p);
1177 }
1178
1179 // _DrawPolygon
1180 inline void
_DrawPolygon(const BPoint * ptArray,int32 numPts,bool closed,const pattern & p,bool fill) const1181 Painter::_DrawPolygon(const BPoint* ptArray, int32 numPts,
1182 bool closed, const pattern& p, bool fill) const
1183 {
1184 if (numPts > 0) {
1185
1186 agg::path_storage path;
1187 BPoint point = _Transform(*ptArray);
1188 path.move_to(point.x, point.y);
1189
1190 for (int32 i = 1; i < numPts; i++) {
1191 ptArray++;
1192 point = _Transform(*ptArray);
1193 path.line_to(point.x, point.y);
1194 }
1195
1196 if (closed)
1197 path.close_polygon();
1198
1199 if (fill)
1200 _FillPath(path, p);
1201 else
1202 _StrokePath(path, p);
1203 }
1204 }
1205
1206 // _DrawBitmap
1207 void
_DrawBitmap(const agg::rendering_buffer & srcBuffer,color_space format,BRect actualBitmapRect,BRect bitmapRect,BRect viewRect) const1208 Painter::_DrawBitmap(const agg::rendering_buffer& srcBuffer, color_space format,
1209 BRect actualBitmapRect, BRect bitmapRect, BRect viewRect) const
1210 {
1211 switch (format) {
1212 case B_RGB32:
1213 case B_RGBA32:
1214 _DrawBitmap32(srcBuffer, actualBitmapRect, bitmapRect, viewRect);
1215 break;
1216 default:
1217 fprintf(stderr, "Painter::_DrawBitmap() - non-native colorspace: %d\n", format);
1218 #ifdef __HAIKU__
1219 // TODO: this is only a temporary implementation,
1220 // to really handle other colorspaces, one would
1221 // rather do the conversion with much less overhead,
1222 // for example in the nn filter (hm), or in the
1223 // scanline generator
1224 BBitmap temp(actualBitmapRect, 0, B_RGB32);
1225 status_t err = temp.ImportBits(srcBuffer.buf(),
1226 srcBuffer.height() * srcBuffer.stride(),
1227 srcBuffer.stride(),
1228 0, format);
1229 if (err >= B_OK) {
1230 agg::rendering_buffer convertedBuffer;
1231 convertedBuffer.attach((uint8*)temp.Bits(),
1232 (uint32)actualBitmapRect.IntegerWidth() + 1,
1233 (uint32)actualBitmapRect.IntegerHeight() + 1,
1234 temp.BytesPerRow());
1235 _DrawBitmap32(convertedBuffer, actualBitmapRect, bitmapRect, viewRect);
1236 } else {
1237 fprintf(stderr, "Painter::_DrawBitmap() - colorspace conversion failed: %s\n", strerror(err));
1238 }
1239 #endif // __HAIKU__
1240 break;
1241 }
1242 }
1243
1244 // _DrawBitmap32
1245 void
_DrawBitmap32(const agg::rendering_buffer & srcBuffer,BRect actualBitmapRect,BRect bitmapRect,BRect viewRect) const1246 Painter::_DrawBitmap32(const agg::rendering_buffer& srcBuffer,
1247 BRect actualBitmapRect, BRect bitmapRect, BRect viewRect) const
1248 {
1249 typedef agg::span_allocator<agg::rgba8> span_alloc_type;
1250 typedef agg::span_interpolator_linear<> interpolator_type;
1251 typedef agg::span_image_filter_rgba32_nn<agg::order_bgra32,
1252 interpolator_type> span_gen_type;
1253 typedef agg::renderer_scanline_aa<renderer_base, span_gen_type> image_renderer_type;
1254
1255 if (bitmapRect.IsValid() && bitmapRect.Intersects(actualBitmapRect)
1256 && viewRect.IsValid()) {
1257
1258 // compensate for the lefttop offset the actualBitmapRect might have
1259 // NOTE: I have no clue why enabling the next call gives a wrong result!
1260 // According to the BeBook, bitmapRect is supposed to be in native
1261 // bitmap space!
1262 // bitmapRect.OffsetBy(-actualBitmapRect.left, -actualBitmapRect.top);
1263 actualBitmapRect.OffsetBy(-actualBitmapRect.left, -actualBitmapRect.top);
1264
1265 // calculate the scaling
1266 double xScale = (viewRect.Width() + 1) / (bitmapRect.Width() + 1);
1267 double yScale = (viewRect.Height() + 1) / (bitmapRect.Height() + 1);
1268
1269 // constrain rect to passed bitmap bounds
1270 // and transfer the changes to the viewRect
1271 if (bitmapRect.left < actualBitmapRect.left) {
1272 float diff = actualBitmapRect.left - bitmapRect.left;
1273 viewRect.left += diff * xScale;
1274 bitmapRect.left = actualBitmapRect.left;
1275 }
1276 if (bitmapRect.top < actualBitmapRect.top) {
1277 float diff = actualBitmapRect.top - bitmapRect.top;
1278 viewRect.top += diff;
1279 bitmapRect.top = actualBitmapRect.top;
1280 }
1281 if (bitmapRect.right > actualBitmapRect.right) {
1282 float diff = bitmapRect.right - actualBitmapRect.right;
1283 viewRect.right -= diff;
1284 bitmapRect.right = actualBitmapRect.right;
1285 }
1286 if (bitmapRect.bottom > actualBitmapRect.bottom) {
1287 float diff = bitmapRect.right - actualBitmapRect.bottom;
1288 viewRect.bottom -= diff;
1289 bitmapRect.bottom = actualBitmapRect.bottom;
1290 }
1291
1292 float xOffset = viewRect.left - (bitmapRect.left * xScale);
1293 float yOffset = viewRect.top - (bitmapRect.top * yScale);
1294
1295 agg::trans_affine srcMatrix;
1296 // srcMatrix *= agg::trans_affine_translation(-actualBitmapRect.left, -actualBitmapRect.top);
1297 srcMatrix *= agg::trans_affine_scaling(fScale, fScale);
1298 srcMatrix *= agg::trans_affine_translation(fOrigin.x, fOrigin.y);
1299
1300 agg::trans_affine imgMatrix;
1301 imgMatrix *= agg::trans_affine_scaling(xScale, yScale);
1302 imgMatrix *= agg::trans_affine_translation(xOffset, yOffset);
1303 imgMatrix *= agg::trans_affine_scaling(fScale, fScale);
1304 imgMatrix *= agg::trans_affine_translation(fOrigin.x, fOrigin.y);
1305 imgMatrix.invert();
1306
1307 span_alloc_type sa;
1308 interpolator_type interpolator(imgMatrix);
1309
1310 span_gen_type sg(sa, srcBuffer, agg::rgba(0, 0, 0, 0), interpolator);
1311
1312 image_renderer_type ri(*fBaseRenderer, sg);
1313
1314 agg::rasterizer_scanline_aa<> pf;
1315 agg::scanline_u8 sl;
1316
1317 // path encloses image
1318 agg::path_storage path;
1319 path.move_to(viewRect.left, viewRect.top);
1320 path.line_to(viewRect.right + 1, viewRect.top);
1321 path.line_to(viewRect.right + 1, viewRect.bottom + 1);
1322 path.line_to(viewRect.left, viewRect.bottom + 1);
1323 path.close_polygon();
1324
1325 agg::conv_transform<agg::path_storage> tr(path, srcMatrix);
1326
1327 pf.add_path(tr);
1328 agg::render_scanlines(pf, sl, ri);
1329 }
1330 }
1331
1332 // _InvertRect32
1333 void
_InvertRect32(BRect r) const1334 Painter::_InvertRect32(BRect r) const
1335 {
1336 if (fBuffer) {
1337 int32 width = r.IntegerWidth() + 1;
1338 for (int32 y = (int32)r.top; y <= (int32)r.bottom; y++) {
1339 uint8* dst = fBuffer->row(y);
1340 dst += (int32)r.left * 4;
1341 for (int32 i = 0; i < width; i++) {
1342 dst[0] = 255 - dst[0];
1343 dst[1] = 255 - dst[1];
1344 dst[2] = 255 - dst[2];
1345 dst += 4;
1346 }
1347 }
1348 }
1349 }
1350
1351 // #pragma mark -
1352
1353 template<class VertexSource>
1354 BRect
_BoundingBox(VertexSource & path) const1355 Painter::_BoundingBox(VertexSource& path) const
1356 {
1357 double left = 0.0;
1358 double top = 0.0;
1359 double right = -1.0;
1360 double bottom = -1.0;
1361 uint32 pathID[1];
1362 pathID[0] = 0;
1363 agg::bounding_rect(path, pathID, 0, 1, &left, &top, &right, &bottom);
1364 return BRect(left, top, right, bottom);
1365 }
1366
1367
1368 // _StrokePath
1369 template<class VertexSource>
1370 BRect
_StrokePath(VertexSource & path,const pattern & p) const1371 Painter::_StrokePath(VertexSource& path, const pattern& p) const
1372 {
1373 // We're now used by app_server and SetDrawData() was called prior to
1374 // this and it means the pattern is already set
1375 // fPatternHandler->SetPattern(p);
1376 // _SetPattern(p);
1377
1378 #if ALIASED_DRAWING
1379 float width = fPenSize;
1380 _Transform(&width);
1381 if (width > 1.0) {
1382 agg::conv_stroke<VertexSource> stroke(path);
1383 stroke.width(width);
1384
1385 fRasterizer->add_path(stroke);
1386 agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
1387 } else {
1388 fOutlineRasterizer->add_path(path);
1389 }
1390 #else
1391 fOutlineRasterizer->add_path(path);
1392 #endif
1393
1394 return _Clipped(_BoundingBox(path));
1395 }
1396
1397 // _FillPath
1398 template<class VertexSource>
1399 BRect
_FillPath(VertexSource & path,const pattern & p) const1400 Painter::_FillPath(VertexSource& path, const pattern& p) const
1401 {
1402 // We're now used by app_server and SetDrawData() was called prior to
1403 // this and it means the pattern is already set
1404 // fPatternHandler->SetPattern(p);
1405 // _SetPattern(p);
1406
1407 fRasterizer->add_path(path);
1408 agg::render_scanlines(*fRasterizer, *fScanline, *fRenderer);
1409
1410 return _Clipped(_BoundingBox(path));
1411 }
1412
1413 // _SetPattern
1414 void
_SetPattern(const pattern & p) const1415 Painter::_SetPattern(const pattern& p) const
1416 {
1417 if (!(p == *fPatternHandler->GetR5Pattern())) {
1418 printf("Painter::_SetPattern()\n");
1419 fPatternHandler->SetPattern(p);
1420 DrawingMode* mode = NULL;
1421 if (p == B_SOLID_HIGH) {
1422 _SetRendererColor(fPatternHandler->HighColor().GetColor32());
1423 mode = DrawingModeFactory::DrawingModeFor(fDrawingMode,
1424 fAlphaSrcMode,
1425 fAlphaFncMode,
1426 true);
1427 } else if (p == B_SOLID_LOW) {
1428 _SetRendererColor(fPatternHandler->LowColor().GetColor32());
1429 mode = DrawingModeFactory::DrawingModeFor(fDrawingMode,
1430 fAlphaSrcMode,
1431 fAlphaFncMode,
1432 true);
1433 } else {
1434 mode = DrawingModeFactory::DrawingModeFor(fDrawingMode,
1435 fAlphaSrcMode,
1436 fAlphaFncMode,
1437 false);
1438 }
1439 fPixelFormat->set_drawing_mode(mode);
1440 }
1441 }
1442
1443 // _SetRendererColor
1444 void
_SetRendererColor(const rgb_color & color) const1445 Painter::_SetRendererColor(const rgb_color& color) const
1446 {
1447
1448 if (fOutlineRenderer)
1449 #if ALIASED_DRAWING
1450 fOutlineRenderer->line_color(agg::rgba(color.red / 255.0,
1451 color.green / 255.0,
1452 color.blue / 255.0));
1453 #else
1454 fOutlineRenderer->color(agg::rgba(color.red / 255.0,
1455 color.green / 255.0,
1456 color.blue / 255.0));
1457 #endif
1458 if (fRenderer)
1459 fRenderer->color(agg::rgba(color.red / 255.0,
1460 color.green / 255.0,
1461 color.blue / 255.0));
1462 if (fFontRendererSolid)
1463 fFontRendererSolid->color(agg::rgba(color.red / 255.0,
1464 color.green / 255.0,
1465 color.blue / 255.0));
1466 if (fFontRendererBin)
1467 fFontRendererBin->color(agg::rgba(color.red / 255.0,
1468 color.green / 255.0,
1469 color.blue / 255.0));
1470
1471 }
1472