1 /*
2  * Copyright 2008 François Revol <mmu_man@users.sourceforge.net>
3  * Copyright 2006 Rob Kendrick <rjek@rjek.com>
4  * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
5  *
6  * This file is part of NetSurf, http://www.netsurf-browser.org/
7  *
8  * NetSurf is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * NetSurf is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /**
22  * \file
23  * BeOS/Haiku implementation target independent plotting.
24  */
25 
26 #define __STDBOOL_H__	1
27 #include <math.h>
28 #include <BeBuild.h>
29 #include <Bitmap.h>
30 #include <GraphicsDefs.h>
31 #include <Region.h>
32 #include <View.h>
33 #include <Shape.h>
34 extern "C" {
35 #include "utils/log.h"
36 #include "utils/utils.h"
37 #include "utils/nsoption.h"
38 #include "utils/nsurl.h"
39 #include "netsurf/plotters.h"
40 }
41 #include "beos/font.h"
42 #include "beos/gui.h"
43 #include "beos/plotters.h"
44 #include "beos/bitmap.h"
45 
46 #warning MAKE ME static
47 /*static*/ BView *current_view;
48 
49 /*
50  * NOTE: BeOS rects differ from NetSurf ones:
51  * the right-bottom pixel is actually part of the BRect!
52  */
53 
54 #warning make patterns nicer
55 static const pattern kDottedPattern = {
56         0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa
57 };
58 static const pattern kDashedPattern = {
59         0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0x33, 0x33
60 };
61 
62 static const rgb_color kBlackColor = {
63         0, 0, 0, 255
64 };
65 
66 //struct plotter_table plot;
67 
68 // #pragma mark - implementation
69 
nsbeos_current_gc(void)70 BView *nsbeos_current_gc(void)
71 {
72         return current_view;
73 }
74 
75 
nsbeos_current_gc_lock(void)76 BView *nsbeos_current_gc_lock(void)
77 {
78         BView *view = current_view;
79         if (view && view->LockLooper())
80                 return view;
81         return NULL;
82 }
83 
84 
nsbeos_current_gc_unlock(void)85 void nsbeos_current_gc_unlock(void)
86 {
87         if (current_view) {
88                 current_view->UnlockLooper();
89         }
90 }
91 
92 
nsbeos_current_gc_set(BView * view)93 void nsbeos_current_gc_set(BView *view)
94 {
95         // XXX: (un)lock previous ?
96         current_view = view;
97 }
98 
99 
100 static nserror
nsbeos_plot_bbitmap(int x,int y,int width,int height,BBitmap * b,colour bg)101 nsbeos_plot_bbitmap(int x, int y, int width, int height, BBitmap *b, colour bg)
102 {
103         /* XXX: This currently ignores the background colour supplied.
104          * Does this matter?
105          */
106 
107         if (width == 0 || height == 0) {
108                 return NSERROR_OK;
109         }
110 
111         BView *view;
112 
113         view = nsbeos_current_gc/*_lock*/();
114         if (view == NULL) {
115                 beos_warn_user("No GC", 0);
116                 return NSERROR_INVALID;
117         }
118 
119         drawing_mode oldmode = view->DrawingMode();
120         source_alpha alpha;
121         alpha_function func;
122         view->GetBlendingMode(&alpha, &func);
123         //view->SetDrawingMode(B_OP_OVER);
124         view->SetDrawingMode(B_OP_ALPHA);
125         view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
126 
127         // XXX DrawBitmap() resamples if rect doesn't match,
128         // but doesn't do any filtering
129         // XXX: use Zeta API if available ?
130 
131         BRect rect(x, y, x + width - 1, y + height - 1);
132         /*
133           rgb_color old = view->LowColor();
134           if (bg != NS_TRANSPARENT) {
135           view->SetLowColor(nsbeos_rgb_colour(bg));
136           view->FillRect(rect, B_SOLID_LOW);
137           }
138         */
139         view->DrawBitmap(b, rect);
140         // maybe not needed?
141         //view->SetLowColor(old);
142         view->SetBlendingMode(alpha, func);
143         view->SetDrawingMode(oldmode);
144 
145         //nsbeos_current_gc_unlock();
146 
147         return NSERROR_OK;
148 }
149 
150 
transform_pt(float x,float y,const float transform[6])151 static BPoint transform_pt(float x, float y, const float transform[6])
152 {
153 #warning XXX: verify
154         //return BPoint(x, y);
155         BPoint pt;
156         pt.x = x * transform[0] + y * transform[1] + transform[4];
157         pt.y = x * transform[2] + y * transform[3] + transform[5];
158         /*
159           printf("TR: {%f, %f} { %f, %f, %f, %f, %f, %f} = { %f, %f }\n",
160           x, y,
161           transform[0], transform[1], transform[2],
162           transform[3], transform[4], transform[5],
163           pt.x, pt.y);
164         */
165         return pt;
166 }
167 
168 
nsbeos_rgb_colour(colour c)169 rgb_color nsbeos_rgb_colour(colour c)
170 {
171         rgb_color color;
172         if (c == NS_TRANSPARENT)
173                 return B_TRANSPARENT_32_BIT;
174         color.red = c & 0x0000ff;
175         color.green = (c & 0x00ff00) >> 8;
176         color.blue = (c & 0xff0000) >> 16;
177         return color;
178 }
179 
180 
nsbeos_set_colour(colour c)181 void nsbeos_set_colour(colour c)
182 {
183         rgb_color color = nsbeos_rgb_colour(c);
184         BView *view = nsbeos_current_gc();
185         view->SetHighColor(color);
186 }
187 
188 
189 /**
190  * Plot a caret.
191  *
192  * It is assumed that the plotters have been set up.
193  */
nsbeos_plot_caret(int x,int y,int h)194 void nsbeos_plot_caret(int x, int y, int h)
195 {
196         BView *view;
197 
198         view = nsbeos_current_gc/*_lock*/();
199         if (view == NULL)
200                 /* TODO: report an error here */
201                 return;
202 
203         BPoint start(x, y);
204         BPoint end(x, y + h - 1);
205 #if defined(__HAIKU__) || defined(B_BEOS_VERSION_DANO)
206         view->SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
207 #else
208         view->SetHighColor(kBlackColor);
209 #endif
210         view->StrokeLine(start, end);
211 
212         //nsbeos_current_gc_unlock();
213 }
214 
215 
216 /**
217  * \brief Sets a clip rectangle for subsequent plot operations.
218  *
219  * \param ctx The current redraw context.
220  * \param ns_clip The rectangle to limit all subsequent plot
221  *              operations within.
222  * \return NSERROR_OK on success else error code.
223  */
224 static nserror
nsbeos_plot_clip(const struct redraw_context * ctx,const struct rect * ns_clip)225 nsbeos_plot_clip(const struct redraw_context *ctx, const struct rect *ns_clip)
226 {
227         BView *view;
228         //fprintf(stderr, "%s(%d, %d, %d, %d)\n", __FUNCTION__, clip_x0, clip_y0, clip_x1, clip_y1);
229 
230         view = nsbeos_current_gc/*_lock*/();
231         if (view == NULL) {
232                 beos_warn_user("No GC", 0);
233                 return NSERROR_INVALID;
234         }
235 
236         BRect rect(ns_clip->x0, ns_clip->y0, ns_clip->x1 - 1, ns_clip->y1 - 1);
237         BRegion clip(rect);
238         view->ConstrainClippingRegion(NULL);
239         if (view->Bounds() != rect) {
240                 view->ConstrainClippingRegion(&clip);
241         }
242 
243         //nsbeos_current_gc_unlock();
244 
245         return NSERROR_OK;
246 }
247 
248 
249 /**
250  * Plots an arc
251  *
252  * plot an arc segment around (x,y), anticlockwise from angle1
253  *  to angle2. Angles are measured anticlockwise from
254  *  horizontal, in degrees.
255  *
256  * \param ctx The current redraw context.
257  * \param style Style controlling the arc plot.
258  * \param x The x coordinate of the arc.
259  * \param y The y coordinate of the arc.
260  * \param radius The radius of the arc.
261  * \param angle1 The start angle of the arc.
262  * \param angle2 The finish angle of the arc.
263  * \return NSERROR_OK on success else error code.
264  */
265 static nserror
nsbeos_plot_arc(const struct redraw_context * ctx,const plot_style_t * style,int x,int y,int radius,int angle1,int angle2)266 nsbeos_plot_arc(const struct redraw_context *ctx,
267                 const plot_style_t *style,
268                 int x, int y, int radius, int angle1, int angle2)
269 {
270         BView *view;
271 
272         view = nsbeos_current_gc/*_lock*/();
273         if (view == NULL) {
274                 beos_warn_user("No GC", 0);
275                 return NSERROR_INVALID;
276         }
277 
278         nsbeos_set_colour(style->fill_colour);
279 
280         BPoint center(x, y);
281         float angle = angle1; // in degree
282         float span = angle2 - angle1; // in degree
283         view->StrokeArc(center, radius, radius, angle, span);
284 
285         //nsbeos_current_gc_unlock();
286 
287         return NSERROR_OK;
288 }
289 
290 
291 /**
292  * Plots a circle
293  *
294  * Plot a circle centered on (x,y), which is optionally filled.
295  *
296  * \param ctx The current redraw context.
297  * \param style Style controlling the circle plot.
298  * \param x x coordinate of circle centre.
299  * \param y y coordinate of circle centre.
300  * \param radius circle radius.
301  * \return NSERROR_OK on success else error code.
302  */
303 static nserror
nsbeos_plot_disc(const struct redraw_context * ctx,const plot_style_t * style,int x,int y,int radius)304 nsbeos_plot_disc(const struct redraw_context *ctx,
305                  const plot_style_t *style,
306                  int x, int y, int radius)
307 {
308         BView *view;
309 
310         view = nsbeos_current_gc/*_lock*/();
311         if (view == NULL) {
312                 beos_warn_user("No GC", 0);
313                 return NSERROR_INVALID;
314         }
315 
316         nsbeos_set_colour(style->fill_colour);
317 
318         BPoint center(x, y);
319         if (style->fill_type != PLOT_OP_TYPE_NONE)
320                 view->FillEllipse(center, radius, radius);
321         else
322                 view->StrokeEllipse(center, radius, radius);
323 
324         //nsbeos_current_gc_unlock();
325 
326         return NSERROR_OK;
327 }
328 
329 
330 /**
331  * Plots a line
332  *
333  * plot a line from (x0,y0) to (x1,y1). Coordinates are at
334  *  centre of line width/thickness.
335  *
336  * \param ctx The current redraw context.
337  * \param style Style controlling the line plot.
338  * \param line A rectangle defining the line to be drawn
339  * \return NSERROR_OK on success else error code.
340  */
341 static nserror
nsbeos_plot_line(const struct redraw_context * ctx,const plot_style_t * style,const struct rect * line)342 nsbeos_plot_line(const struct redraw_context *ctx,
343                  const plot_style_t *style,
344                  const struct rect *line)
345 {
346         pattern pat;
347         BView *view;
348 
349         switch (style->stroke_type) {
350         case PLOT_OP_TYPE_SOLID: /**< Solid colour */
351         default:
352                 pat = B_SOLID_HIGH;
353                 break;
354 
355         case PLOT_OP_TYPE_DOT: /**< Doted plot */
356                 pat = kDottedPattern;
357                 break;
358 
359         case PLOT_OP_TYPE_DASH: /**< dashed plot */
360                 pat = kDashedPattern;
361                 break;
362         }
363 
364         view = nsbeos_current_gc/*_lock*/();
365         if (view == NULL) {
366                 beos_warn_user("No GC", 0);
367                 return NSERROR_OK;
368         }
369 
370         nsbeos_set_colour(style->stroke_colour);
371 
372         float pensize = view->PenSize();
373         view->SetPenSize(plot_style_fixed_to_float(style->stroke_width));
374 
375         BPoint start(line->x0, line->y0);
376         BPoint end(line->x1, line->y1);
377         view->StrokeLine(start, end, pat);
378 
379         view->SetPenSize(pensize);
380 
381         //nsbeos_current_gc_unlock();
382 
383         return NSERROR_OK;
384 }
385 
386 
387 /**
388  * Plots a rectangle.
389  *
390  * The rectangle can be filled an outline or both controlled
391  *  by the plot style The line can be solid, dotted or
392  *  dashed. Top left corner at (x0,y0) and rectangle has given
393  *  width and height.
394  *
395  * \param ctx The current redraw context.
396  * \param style Style controlling the rectangle plot.
397  * \param nsrect A rectangle defining the line to be drawn
398  * \return NSERROR_OK on success else error code.
399  */
400 static nserror
nsbeos_plot_rectangle(const struct redraw_context * ctx,const plot_style_t * style,const struct rect * nsrect)401 nsbeos_plot_rectangle(const struct redraw_context *ctx,
402                       const plot_style_t *style,
403                       const struct rect *nsrect)
404 {
405         if (style->fill_type != PLOT_OP_TYPE_NONE) {
406                 BView *view;
407 
408                 view = nsbeos_current_gc/*_lock*/();
409                 if (view == NULL) {
410                         beos_warn_user("No GC", 0);
411                         return NSERROR_INVALID;
412                 }
413 
414                 nsbeos_set_colour(style->fill_colour);
415 
416                 BRect rect(nsrect->x0, nsrect->y0, nsrect->x1 - 1, nsrect->y1 - 1);
417                 view->FillRect(rect);
418 
419                 //nsbeos_current_gc_unlock();
420         }
421 
422         if (style->stroke_type != PLOT_OP_TYPE_NONE) {
423                 pattern pat;
424                 BView *view;
425 
426                 switch (style->stroke_type) {
427                 case PLOT_OP_TYPE_SOLID: /**< Solid colour */
428                 default:
429                         pat = B_SOLID_HIGH;
430                         break;
431 
432                 case PLOT_OP_TYPE_DOT: /**< Doted plot */
433                         pat = kDottedPattern;
434                         break;
435 
436                 case PLOT_OP_TYPE_DASH: /**< dashed plot */
437                         pat = kDashedPattern;
438                         break;
439                 }
440 
441                 view = nsbeos_current_gc/*_lock*/();
442                 if (view == NULL) {
443                         beos_warn_user("No GC", 0);
444                         return NSERROR_INVALID;
445                 }
446 
447                 nsbeos_set_colour(style->stroke_colour);
448 
449                 float pensize = view->PenSize();
450                 view->SetPenSize(plot_style_fixed_to_float(style->stroke_width));
451 
452                 BRect rect(nsrect->x0, nsrect->y0, nsrect->x1, nsrect->y1);
453                 view->StrokeRect(rect, pat);
454 
455                 view->SetPenSize(pensize);
456 
457                 //nsbeos_current_gc_unlock();
458         }
459 
460         return NSERROR_OK;
461 }
462 
463 
464 /**
465  * Plot a polygon
466  *
467  * Plots a filled polygon with straight lines between
468  * points. The lines around the edge of the ploygon are not
469  * plotted. The polygon is filled with the non-zero winding
470  * rule.
471  *
472  * \param ctx The current redraw context.
473  * \param style Style controlling the polygon plot.
474  * \param p verticies of polygon
475  * \param n number of verticies.
476  * \return NSERROR_OK on success else error code.
477  */
478 static nserror
nsbeos_plot_polygon(const struct redraw_context * ctx,const plot_style_t * style,const int * p,unsigned int n)479 nsbeos_plot_polygon(const struct redraw_context *ctx,
480                     const plot_style_t *style,
481                     const int *p,
482                     unsigned int n)
483 {
484         unsigned int i;
485         BView *view;
486 
487         view = nsbeos_current_gc/*_lock*/();
488         if (view == NULL) {
489                 beos_warn_user("No GC", 0);
490                 return NSERROR_INVALID;
491         }
492 
493         nsbeos_set_colour(style->fill_colour);
494 
495         BPoint points[n];
496 
497         for (i = 0; i < n; i++) {
498                 points[i] = BPoint(p[2 * i] - 0.5, p[2 * i + 1] - 0.5);
499         }
500 
501         if (style->fill_colour == NS_TRANSPARENT) {
502                 view->StrokePolygon(points, (int32)n);
503         } else {
504                 view->FillPolygon(points, (int32)n);
505         }
506 
507         return NSERROR_OK;
508 }
509 
510 
511 /**
512  * Plots a path.
513  *
514  * Path plot consisting of cubic Bezier curves. Line and fill colour is
515  *  controlled by the plot style.
516  *
517  * \param ctx The current redraw context.
518  * \param pstyle Style controlling the path plot.
519  * \param p elements of path
520  * \param n nunber of elements on path
521  * \param transform A transform to apply to the path.
522  * \return NSERROR_OK on success else error code.
523  */
524 static nserror
nsbeos_plot_path(const struct redraw_context * ctx,const plot_style_t * pstyle,const float * p,unsigned int n,const float transform[6])525 nsbeos_plot_path(const struct redraw_context *ctx,
526                  const plot_style_t *pstyle,
527                  const float *p,
528                  unsigned int n,
529                  const float transform[6])
530 {
531         unsigned int i;
532         BShape shape;
533 
534         if (n == 0) {
535                 return NSERROR_OK;
536         }
537 
538         if (p[0] != PLOTTER_PATH_MOVE) {
539                 NSLOG(netsurf, INFO, "path doesn't start with a move");
540                 return NSERROR_INVALID;
541         }
542 
543         for (i = 0; i < n; ) {
544                 if (p[i] == PLOTTER_PATH_MOVE) {
545                         BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
546                         shape.MoveTo(pt);
547                         i += 3;
548                 } else if (p[i] == PLOTTER_PATH_CLOSE) {
549                         shape.Close();
550                         i++;
551                 } else if (p[i] == PLOTTER_PATH_LINE) {
552                         BPoint pt(transform_pt(p[i + 1], p[i + 2], transform));
553                         shape.LineTo(pt);
554                         i += 3;
555                 } else if (p[i] == PLOTTER_PATH_BEZIER) {
556                         BPoint pt[3] = {
557                                 transform_pt(p[i + 1], p[i + 2], transform),
558                                 transform_pt(p[i + 3], p[i + 4], transform),
559                                 transform_pt(p[i + 5], p[i + 6], transform)
560                         };
561                         shape.BezierTo(pt);
562                         i += 7;
563                 } else {
564                         NSLOG(netsurf, INFO, "bad path command %f", p[i]);
565                         return NSERROR_INVALID;
566                 }
567         }
568         shape.Close();
569 
570         BView *view;
571 
572         view = nsbeos_current_gc/*_lock*/();
573         if (view == NULL) {
574                 return NSERROR_INVALID;
575         }
576 
577         rgb_color old_high = view->HighColor();
578         float old_pen = view->PenSize();
579         view->SetPenSize(plot_style_fixed_to_float(pstyle->stroke_width));
580         view->MovePenTo(0, 0);
581         if (pstyle->fill_colour != NS_TRANSPARENT) {
582                 view->SetHighColor(nsbeos_rgb_colour(pstyle->fill_colour));
583                 view->FillShape(&shape);
584         }
585         if (pstyle->stroke_colour != NS_TRANSPARENT) {
586                 view->SetHighColor(nsbeos_rgb_colour(pstyle->stroke_colour));
587                 view->StrokeShape(&shape);
588         }
589         // restore
590         view->SetPenSize(old_pen);
591         view->SetHighColor(old_high);
592 
593         //nsbeos_current_gc_unlock();
594 
595         return NSERROR_OK;
596 }
597 
598 
599 /**
600  * Plot a bitmap
601  *
602  * Tiled plot of a bitmap image. (x,y) gives the top left
603  * coordinate of an explicitly placed tile. From this tile the
604  * image can repeat in all four directions -- up, down, left
605  * and right -- to the extents given by the current clip
606  * rectangle.
607  *
608  * The bitmap_flags say whether to tile in the x and y
609  * directions. If not tiling in x or y directions, the single
610  * image is plotted. The width and height give the dimensions
611  * the image is to be scaled to.
612  *
613  * \param ctx The current redraw context.
614  * \param bitmap The bitmap to plot
615  * \param x The x coordinate to plot the bitmap
616  * \param y The y coordiante to plot the bitmap
617  * \param width The width of area to plot the bitmap into
618  * \param height The height of area to plot the bitmap into
619  * \param bg the background colour to alpha blend into
620  * \param flags the flags controlling the type of plot operation
621  * \return NSERROR_OK on success else error code.
622  */
623 static nserror
nsbeos_plot_bitmap(const struct redraw_context * ctx,struct bitmap * bitmap,int x,int y,int width,int height,colour bg,bitmap_flags_t flags)624 nsbeos_plot_bitmap(const struct redraw_context *ctx,
625                    struct bitmap *bitmap,
626                    int x, int y,
627                    int width,
628                    int height,
629                    colour bg,
630                    bitmap_flags_t flags)
631 {
632         int doneheight = 0, donewidth = 0;
633         BBitmap *primary;
634         BBitmap *pretiled;
635         bool repeat_x = (flags & BITMAPF_REPEAT_X);
636         bool repeat_y = (flags & BITMAPF_REPEAT_Y);
637 
638         if (!(repeat_x || repeat_y)) {
639                 /* Not repeating at all, so just plot it */
640                 primary = nsbeos_bitmap_get_primary(bitmap);
641                 return nsbeos_plot_bbitmap(x, y, width, height, primary, bg);
642         }
643 
644         if (repeat_x && !repeat_y)
645                 pretiled = nsbeos_bitmap_get_pretile_x(bitmap);
646         if (repeat_x && repeat_y)
647                 pretiled = nsbeos_bitmap_get_pretile_xy(bitmap);
648         if (!repeat_x && repeat_y)
649                 pretiled = nsbeos_bitmap_get_pretile_y(bitmap);
650         primary = nsbeos_bitmap_get_primary(bitmap);
651 
652         /* use the primary and pretiled widths to scale the w/h provided */
653         width *= pretiled->Bounds().Width() + 1;
654         width /= primary->Bounds().Width() + 1;
655         height *= pretiled->Bounds().Height() + 1;
656         height /= primary->Bounds().Height() + 1;
657 
658         BView *view;
659 
660         view = nsbeos_current_gc/*_lock*/();
661         if (view == NULL) {
662                 beos_warn_user("No GC", 0);
663                 return NSERROR_INVALID;
664         }
665 
666         // XXX: do we really need to use clipping reg ?
667         // I guess it's faster to not draw clipped out stuff...
668 
669         BRect cliprect;
670         BRegion clipreg;
671         view->GetClippingRegion(&clipreg);
672         cliprect = clipreg.Frame();
673 
674         //XXX: FIXME
675 
676         if (y > cliprect.top) {
677                 doneheight = ((int)cliprect.top - height) + ((y - (int)cliprect.top) % height);
678         } else {
679                 doneheight = y;
680         }
681 
682         while (doneheight < ((int)cliprect.bottom)) {
683                 if (x > cliprect.left) {
684                         donewidth = ((int)cliprect.left - width) + ((x - (int)cliprect.left) % width);
685                 } else {
686                         donewidth = x;
687                 }
688 
689                 while (donewidth < (cliprect.right)) {
690                         nsbeos_plot_bbitmap(donewidth, doneheight,
691                                             width, height, pretiled, bg);
692                         donewidth += width;
693                         if (!repeat_x) {
694                                 break;
695                         }
696                 }
697                 doneheight += height;
698                 if (!repeat_y) {
699                         break;
700                 }
701         }
702 
703 #warning WRITEME
704 
705         return NSERROR_OK;
706 }
707 
708 
709 /**
710  * Text plotting.
711  *
712  * \param ctx The current redraw context.
713  * \param fstyle plot style for this text
714  * \param x x coordinate
715  * \param y y coordinate
716  * \param text UTF-8 string to plot
717  * \param length length of string, in bytes
718  * \return NSERROR_OK on success else error code.
719  */
720 static nserror
nsbeos_plot_text(const struct redraw_context * ctx,const struct plot_font_style * fstyle,int x,int y,const char * text,size_t length)721 nsbeos_plot_text(const struct redraw_context *ctx,
722                  const struct plot_font_style *fstyle,
723                  int x,
724                  int y,
725                  const char *text,
726                  size_t length)
727 {
728         if (!nsfont_paint(fstyle, text, length, x, y)) {
729                 return NSERROR_INVALID;
730         }
731 
732         return NSERROR_OK;
733 }
734 
735 
736 /**
737  * beos plotter operation table
738  */
739 const struct plotter_table nsbeos_plotters = {
740         nsbeos_plot_clip,
741         nsbeos_plot_arc,
742         nsbeos_plot_disc,
743         nsbeos_plot_line,
744         nsbeos_plot_rectangle,
745         nsbeos_plot_polygon,
746         nsbeos_plot_path,
747         nsbeos_plot_bitmap,
748         nsbeos_plot_text,
749         NULL, // Group Start
750         NULL, // Group End
751         NULL, // Flush
752         true // option_knockout
753 };
754 
755 
756 #ifdef TEST_PLOTTERS
757 //
test_plotters(void)758 static void test_plotters(void)
759 {
760         int x0, y0;
761         int x1, y1;
762         struct rect r;
763 
764         x0 = 5;
765         y0 = 5;
766         x1 = 35;
767         y1 = 6;
768 
769         plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, false);
770         y0+=2; y1+=2;
771         plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, false);
772         y0+=2; y1+=2;
773         plot.line(x0, y0, x1, y1, 1, 0x0000ff00, false, true);
774         y0+=2; y1+=2;
775         plot.line(x0, y0, x1, y1, 1, 0x0000ff00, true, true);
776         y0+=10; y1+=20;
777 
778         plot.fill(x0, y0, x1, y1, 0x00ff0000);
779         plot.rectangle(x0+10, y0+10, x1-x0+1, y1-y0+1, 2, 0x00ffff00, true, false);
780         y0+=30; y1+=30;
781 
782         r.x0 = x0 + 2;
783         r.y0 = y0 + 2;
784         r.x1 = x1 - 2;
785         r.y1 = y1 - 2;
786         plot.clip(&r);
787 
788         plot.fill(x0, y0, x1, y1, 0x00000000);
789         plot.disc(x1, y1, 8, 0x000000ff, false);
790 
791         r.x0 = 0;
792         r.y0 = 0;
793         r.x1 = 300;
794         r.y1 = 300;
795         plot.clip(&r);
796 
797         y0+=30; y1+=30;
798 
799 }
800 
801 #include <Application.h>
802 #include <View.h>
803 #include <Window.h>
804 class PTView : public BView {
805 public:
PTView(BRect frame)806         PTView(BRect frame) : BView(frame, "view", B_FOLLOW_NONE, B_WILL_DRAW) {};
~PTView()807         virtual ~PTView() {};
Draw(BRect update)808         virtual void Draw(BRect update)
809         {
810                 test_plotters();
811         };
812 
813 };
814 
815 extern "C" void test_plotters_main(void);
test_plotters_main(void)816 void test_plotters_main(void)
817 {
818         BApplication app("application/x-vnd.NetSurf");
819         memcpy(&plot, &nsbeos_plotters, sizeof(plot));
820         BRect frame(0,0,300,300);
821         PTView *view = new PTView(frame);
822         frame.OffsetBySelf(100,100);
823         BWindow *win = new BWindow(frame, "NetSurfPlotterTest", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
824         win->AddChild(view);
825         nsbeos_current_gc_set(view);
826         win->Show();
827         app.Run();
828 }
829 #endif /* TEST_PLOTTERS */
830