Bug Summary

File:/boot/home/haiku/haiku/src/servers/app/drawing/interface/html5/HTML5DrawingEngine.cpp
Location:line 1101, column 13
Description:Called C++ object pointer is null

Annotated Source Code

1/*
2 * Copyright 2009-2010, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 * François Revol <revol@free.fr>
8 */
9
10#include "HTML5DrawingEngine.h"
11#include "CanvasMessage.h"
12
13#include "BitmapDrawingEngine.h"
14#include "DrawState.h"
15
16#include <Bitmap.h>
17#include <utf8_functions.h>
18
19#include <new>
20
21
22HTML5DrawingEngine::HTML5DrawingEngine(HTML5HWInterface* interface)
23 :
24 DrawingEngine(interface),
25 fHWInterface(interface),
26 fToken((uint32)this), // TODO: need to redo that for 64 bit
27 fExtendWidth(0),
28 fCallbackAdded(false),
29 fResultNotify(-1),
30 fStringWidthResult(0.0f),
31 fReadBitmapResult(NULL__null),
32 fBitmapDrawingEngine(NULL__null)
33{
34 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
35 message.Start(RP_CREATE_STATE);
36 message.Add(fToken);
37}
38
39
40HTML5DrawingEngine::~HTML5DrawingEngine()
41{
42 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
43 message.Start(RP_DELETE_STATE);
44 message.Add(fToken);
45 message.Flush();
46
47 delete fBitmapDrawingEngine;
48
49 if (fCallbackAdded)
50 fHWInterface->RemoveCallback(fToken);
51 if (fResultNotify >= 0)
52 delete_sem(fResultNotify);
53}
54
55
56// #pragma mark -
57
58
59void
60HTML5DrawingEngine::FrameBufferChanged()
61{
62 // Not allowed
63}
64
65
66// #pragma mark -
67
68
69void
70HTML5DrawingEngine::SetCopyToFrontEnabled(bool enabled)
71{
72 DrawingEngine::SetCopyToFrontEnabled(enabled);
73
74 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
75 message.Start(enabled ? RP_ENABLE_SYNC_DRAWING : RP_DISABLE_SYNC_DRAWING);
76 message.Add(fToken);
77}
78
79
80// #pragma mark -
81
82
83//! the HTML5DrawingEngine needs to be locked!
84void
85HTML5DrawingEngine::ConstrainClippingRegion(const BRegion* region)
86{
87 if (fClippingRegion == *region)
88 return;
89
90 fClippingRegion = *region;
91
92 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
93 message.Start(RP_CONSTRAIN_CLIPPING_REGION);
94 message.Add(fToken);
95 message.AddRegion(*region);
96}
97
98
99void
100HTML5DrawingEngine::SetDrawState(const DrawState* state, int32 xOffset,
101 int32 yOffset)
102{
103 SetPenSize(state->PenSize());
104 SetDrawingMode(state->GetDrawingMode());
105 SetBlendingMode(state->AlphaSrcMode(), state->AlphaFncMode());
106 SetPattern(state->GetPattern().GetPattern());
107 SetStrokeMode(state->LineCapMode(), state->LineJoinMode(),
108 state->MiterLimit());
109 SetHighColor(state->HighColor());
110 SetLowColor(state->LowColor());
111 SetFont(state->Font());
112
113 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
114 message.Start(RP_SET_OFFSETS);
115 message.Add(fToken);
116 message.Add(xOffset);
117 message.Add(yOffset);
118}
119
120
121void
122HTML5DrawingEngine::SetHighColor(const rgb_color& color)
123{
124 if (fState.HighColor() == color)
125 return;
126
127 fState.SetHighColor(color);
128
129 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
130 message.Start(RP_SET_HIGH_COLOR);
131 message.Add(fToken);
132 message.Add(color);
133}
134
135
136void
137HTML5DrawingEngine::SetLowColor(const rgb_color& color)
138{
139 if (fState.LowColor() == color)
140 return;
141
142 fState.SetLowColor(color);
143
144 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
145 message.Start(RP_SET_LOW_COLOR);
146 message.Add(fToken);
147 message.Add(color);
148}
149
150
151void
152HTML5DrawingEngine::SetPenSize(float size)
153{
154 if (fState.PenSize() == size)
155 return;
156
157 fState.SetPenSize(size);
158 fExtendWidth = -(size / 2);
159
160 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
161 message.Start(RP_SET_PEN_SIZE);
162 message.Add(fToken);
163 message.Add(size);
164}
165
166
167void
168HTML5DrawingEngine::SetStrokeMode(cap_mode lineCap, join_mode joinMode,
169 float miterLimit)
170{
171 if (fState.LineCapMode() == lineCap && fState.LineJoinMode() == joinMode
172 && fState.MiterLimit() == miterLimit)
173 return;
174
175 fState.SetLineCapMode(lineCap);
176 fState.SetLineJoinMode(joinMode);
177 fState.SetMiterLimit(miterLimit);
178
179 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
180 message.Start(RP_SET_STROKE_MODE);
181 message.Add(fToken);
182 message.Add(lineCap);
183 message.Add(joinMode);
184 message.Add(miterLimit);
185}
186
187
188void
189HTML5DrawingEngine::SetBlendingMode(source_alpha sourceAlpha,
190 alpha_function alphaFunc)
191{
192 if (fState.AlphaSrcMode() == sourceAlpha
193 && fState.AlphaFncMode() == alphaFunc)
194 return;
195
196 fState.SetBlendingMode(sourceAlpha, alphaFunc);
197
198 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
199 message.Start(RP_SET_BLENDING_MODE);
200 message.Add(fToken);
201 message.Add(sourceAlpha);
202 message.Add(alphaFunc);
203}
204
205
206void
207HTML5DrawingEngine::SetPattern(const struct pattern& pattern)
208{
209 if (fState.GetPattern() == pattern)
210 return;
211
212 fState.SetPattern(pattern);
213
214 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
215 message.Start(RP_SET_PATTERN);
216 message.Add(fToken);
217 message.Add(pattern);
218}
219
220
221void
222HTML5DrawingEngine::SetDrawingMode(drawing_mode mode)
223{
224 if (fState.GetDrawingMode() == mode)
225 return;
226
227 fState.SetDrawingMode(mode);
228
229 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
230 message.Start(RP_SET_DRAWING_MODE);
231 message.Add(fToken);
232 message.Add(mode);
233}
234
235
236void
237HTML5DrawingEngine::SetDrawingMode(drawing_mode mode, drawing_mode& oldMode)
238{
239 oldMode = fState.GetDrawingMode();
240 SetDrawingMode(mode);
241}
242
243
244void
245HTML5DrawingEngine::SetFont(const ServerFont& font)
246{
247 if (fState.Font() == font)
248 return;
249
250 fState.SetFont(font);
251
252 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
253 message.Start(RP_SET_FONT);
254 message.Add(fToken);
255 message.AddFont(font);
256}
257
258
259void
260HTML5DrawingEngine::SetFont(const DrawState* state)
261{
262 SetFont(state->Font());
263}
264
265
266// #pragma mark -
267
268
269BRect
270HTML5DrawingEngine::CopyRect(BRect rect, int32 xOffset, int32 yOffset) const
271{
272 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
273 message.Start(RP_COPY_RECT_NO_CLIPPING);
274 message.Add(xOffset);
275 message.Add(yOffset);
276 message.Add(rect);
277 return rect.OffsetBySelf(xOffset, yOffset);
278}
279
280
281void
282HTML5DrawingEngine::InvertRect(BRect rect)
283{
284 if (!fClippingRegion.Intersects(rect))
285 return;
286
287 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
288 message.Start(RP_INVERT_RECT);
289 message.Add(fToken);
290 message.Add(rect);
291}
292
293
294void
295HTML5DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect,
296 const BRect& _viewRect, uint32 options)
297{
298 BRect bitmapRect = _bitmapRect;
299 BRect viewRect = _viewRect;
300 double xScale = (bitmapRect.Width() + 1) / (viewRect.Width() + 1);
301 double yScale = (bitmapRect.Height() + 1) / (viewRect.Height() + 1);
302
303 // constrain rect to passed bitmap bounds
304 // and transfer the changes to the viewRect with the right scale
305 BRect actualBitmapRect = bitmap->Bounds();
306 if (bitmapRect.left < actualBitmapRect.left) {
307 float diff = actualBitmapRect.left - bitmapRect.left;
308 viewRect.left += diff / xScale;
309 bitmapRect.left = actualBitmapRect.left;
310 }
311 if (bitmapRect.top < actualBitmapRect.top) {
312 float diff = actualBitmapRect.top - bitmapRect.top;
313 viewRect.top += diff / yScale;
314 bitmapRect.top = actualBitmapRect.top;
315 }
316 if (bitmapRect.right > actualBitmapRect.right) {
317 float diff = bitmapRect.right - actualBitmapRect.right;
318 viewRect.right -= diff / xScale;
319 bitmapRect.right = actualBitmapRect.right;
320 }
321 if (bitmapRect.bottom > actualBitmapRect.bottom) {
322 float diff = bitmapRect.bottom - actualBitmapRect.bottom;
323 viewRect.bottom -= diff / yScale;
324 bitmapRect.bottom = actualBitmapRect.bottom;
325 }
326
327 BRegion clippedRegion(viewRect);
328 clippedRegion.IntersectWith(&fClippingRegion);
329
330 int32 rectCount = clippedRegion.CountRects();
331 if (rectCount == 0)
332 return;
333
334 if (rectCount > 1 || (rectCount == 1 && clippedRegion.RectAt(0) != viewRect)
335 || viewRect.Width() < bitmapRect.Width()
336 || viewRect.Height() < bitmapRect.Height()) {
337 UtilityBitmap** bitmaps;
338 if (_ExtractBitmapRegions(*bitmap, options, bitmapRect, viewRect,
339 xScale, yScale, clippedRegion, bitmaps) != B_OK((int)0)) {
340 return;
341 }
342
343 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
344 message.Start(RP_DRAW_BITMAP_RECTS);
345 message.Add(fToken);
346 message.Add(options);
347 message.Add(bitmap->ColorSpace());
348 message.Add(bitmap->Flags());
349 message.Add(rectCount);
350
351 for (int32 i = 0; i < rectCount; i++) {
352 message.Add(clippedRegion.RectAt(i));
353 message.AddBitmap(*bitmaps[i], true);
354 delete bitmaps[i];
355 }
356
357 free(bitmaps);
358 return;
359 }
360
361 // TODO: we may want to cache/checksum bitmaps
362 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
363 message.Start(RP_DRAW_BITMAP);
364 message.Add(fToken);
365 message.Add(bitmapRect);
366 message.Add(viewRect);
367 message.Add(options);
368 message.AddBitmap(*bitmap);
369}
370
371
372void
373HTML5DrawingEngine::DrawArc(BRect rect, const float& angle, const float& span,
374 bool filled)
375{
376 BRect bounds = rect;
377 if (!filled)
378 bounds.InsetBy(fExtendWidth, fExtendWidth);
379
380 if (!fClippingRegion.Intersects(bounds))
381 return;
382
383 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
384 message.Start(filled ? RP_FILL_ARC : RP_STROKE_ARC);
385 message.Add(fToken);
386 message.Add(rect);
387 message.Add(angle);
388 message.Add(span);
389}
390
391void
392HTML5DrawingEngine::FillArc(BRect rect, const float& angle, const float& span,
393 const BGradient& gradient)
394{
395 if (!fClippingRegion.Intersects(rect))
396 return;
397
398 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
399 message.Start(RP_FILL_ARC_GRADIENT);
400 message.Add(fToken);
401 message.Add(rect);
402 message.Add(angle);
403 message.Add(span);
404 message.AddGradient(gradient);
405}
406
407
408void
409HTML5DrawingEngine::DrawBezier(BPoint* points, bool filled)
410{
411 BRect bounds = _BuildBounds(points, 4);
412 if (!filled)
413 bounds.InsetBy(fExtendWidth, fExtendWidth);
414
415 if (!fClippingRegion.Intersects(bounds))
416 return;
417
418 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
419 message.Start(filled ? RP_FILL_BEZIER : RP_STROKE_BEZIER);
420 message.Add(fToken);
421 message.AddList(points, 4);
422}
423
424
425void
426HTML5DrawingEngine::FillBezier(BPoint* points, const BGradient& gradient)
427{
428 BRect bounds = _BuildBounds(points, 4);
429 if (!fClippingRegion.Intersects(bounds))
430 return;
431
432 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
433 message.Start(RP_FILL_BEZIER_GRADIENT);
434 message.Add(fToken);
435 message.AddList(points, 4);
436 message.AddGradient(gradient);
437}
438
439
440void
441HTML5DrawingEngine::DrawEllipse(BRect rect, bool filled)
442{
443 BRect bounds = rect;
444 if (!filled)
445 bounds.InsetBy(fExtendWidth, fExtendWidth);
446
447 if (!fClippingRegion.Intersects(bounds))
448 return;
449
450 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
451 message.Start(filled ? RP_FILL_ELLIPSE : RP_STROKE_ELLIPSE);
452 message.Add(fToken);
453 message.Add(rect);
454}
455
456
457void
458HTML5DrawingEngine::FillEllipse(BRect rect, const BGradient& gradient)
459{
460 if (!fClippingRegion.Intersects(rect))
461 return;
462
463 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
464 message.Start(RP_FILL_ELLIPSE_GRADIENT);
465 message.Add(fToken);
466 message.Add(rect);
467 message.AddGradient(gradient);
468}
469
470
471void
472HTML5DrawingEngine::DrawPolygon(BPoint* pointList, int32 numPoints,
473 BRect bounds, bool filled, bool closed)
474{
475 BRect clipBounds = bounds;
476 if (!filled)
477 clipBounds.InsetBy(fExtendWidth, fExtendWidth);
478
479 if (!fClippingRegion.Intersects(clipBounds))
480 return;
481
482 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
483 message.Start(filled ? RP_FILL_POLYGON : RP_STROKE_POLYGON);
484 message.Add(fToken);
485 message.Add(bounds);
486 message.Add(closed);
487 message.Add(numPoints);
488 for (int32 i = 0; i < numPoints; i++)
489 message.Add(pointList[i]);
490}
491
492
493void
494HTML5DrawingEngine::FillPolygon(BPoint* pointList, int32 numPoints,
495 BRect bounds, const BGradient& gradient, bool closed)
496{
497 if (!fClippingRegion.Intersects(bounds))
498 return;
499
500 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
501 message.Start(RP_FILL_POLYGON_GRADIENT);
502 message.Add(fToken);
503 message.Add(bounds);
504 message.Add(closed);
505 message.Add(numPoints);
506 for (int32 i = 0; i < numPoints; i++)
507 message.Add(pointList[i]);
508 message.AddGradient(gradient);
509}
510
511
512// #pragma mark - rgb_color versions
513
514
515void
516HTML5DrawingEngine::StrokePoint(const BPoint& point, const rgb_color& color)
517{
518 BRect bounds(point, point);
519 bounds.InsetBy(fExtendWidth, fExtendWidth);
520
521 if (!fClippingRegion.Intersects(bounds))
522 return;
523
524 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
525 message.Start(RP_STROKE_POINT_COLOR);
526 message.Add(fToken);
527 message.Add(point);
528 message.Add(color);
529}
530
531
532void
533HTML5DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end,
534 const rgb_color& color)
535{
536 BPoint points[2] = { start, end };
537 BRect bounds = _BuildBounds(points, 2);
538
539 if (!fClippingRegion.Intersects(bounds))
540 return;
541
542 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
543 message.Start(RP_STROKE_LINE_1PX_COLOR);
544 message.Add(fToken);
545 message.AddList(points, 2);
546 message.Add(color);
547}
548
549
550void
551HTML5DrawingEngine::StrokeRect(BRect rect, const rgb_color &color)
552{
553 BRect bounds = rect;
554 bounds.InsetBy(fExtendWidth, fExtendWidth);
555
556 if (!fClippingRegion.Intersects(bounds))
557 return;
558
559 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
560 message.Start(RP_STROKE_RECT_1PX_COLOR);
561 message.Add(fToken);
562 message.Add(rect);
563 message.Add(color);
564}
565
566
567void
568HTML5DrawingEngine::FillRect(BRect rect, const rgb_color& color)
569{
570 if (!fClippingRegion.Intersects(rect))
571 return;
572
573 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
574 message.Start(RP_FILL_RECT_COLOR);
575 message.Add(fToken);
576 message.Add(rect);
577 message.Add(color);
578}
579
580
581void
582HTML5DrawingEngine::FillRegion(BRegion& region, const rgb_color& color)
583{
584 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
585 message.Start(RP_FILL_REGION_COLOR_NO_CLIPPING);
586 message.AddRegion(region);
587 message.Add(color);
588}
589
590
591// #pragma mark - DrawState versions
592
593
594void
595HTML5DrawingEngine::StrokeRect(BRect rect)
596{
597 BRect bounds = rect;
598 bounds.InsetBy(fExtendWidth, fExtendWidth);
599
600 if (!fClippingRegion.Intersects(bounds))
601 return;
602
603 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
604 message.Start(RP_STROKE_RECT);
605 message.Add(fToken);
606 message.Add(rect);
607}
608
609
610void
611HTML5DrawingEngine::FillRect(BRect rect)
612{
613 if (!fClippingRegion.Intersects(rect))
614 return;
615
616 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
617 message.Start(RP_FILL_RECT);
618 message.Add(fToken);
619 message.Add(rect);
620}
621
622
623void
624HTML5DrawingEngine::FillRect(BRect rect, const BGradient& gradient)
625{
626 if (!fClippingRegion.Intersects(rect))
627 return;
628
629 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
630 message.Start(RP_FILL_RECT_GRADIENT);
631 message.Add(fToken);
632 message.Add(rect);
633 message.AddGradient(gradient);
634}
635
636
637void
638HTML5DrawingEngine::FillRegion(BRegion& region)
639{
640 BRegion clippedRegion = region;
641 clippedRegion.IntersectWith(&fClippingRegion);
642 if (clippedRegion.CountRects() == 0)
643 return;
644
645 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
646 message.Start(RP_FILL_REGION);
647 message.Add(fToken);
648 message.AddRegion(clippedRegion.CountRects() < region.CountRects()
649 ? clippedRegion : region);
650}
651
652
653void
654HTML5DrawingEngine::FillRegion(BRegion& region, const BGradient& gradient)
655{
656 BRegion clippedRegion = region;
657 clippedRegion.IntersectWith(&fClippingRegion);
658 if (clippedRegion.CountRects() == 0)
659 return;
660
661 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
662 message.Start(RP_FILL_REGION_GRADIENT);
663 message.Add(fToken);
664 message.AddRegion(clippedRegion.CountRects() < region.CountRects()
665 ? clippedRegion : region);
666 message.AddGradient(gradient);
667}
668
669
670void
671HTML5DrawingEngine::DrawRoundRect(BRect rect, float xRadius, float yRadius,
672 bool filled)
673{
674 BRect bounds = rect;
675 if (!filled)
676 bounds.InsetBy(fExtendWidth, fExtendWidth);
677
678 if (!fClippingRegion.Intersects(bounds))
679 return;
680
681 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
682 message.Start(filled ? RP_FILL_ROUND_RECT : RP_STROKE_ROUND_RECT);
683 message.Add(fToken);
684 message.Add(rect);
685 message.Add(xRadius);
686 message.Add(yRadius);
687}
688
689
690void
691HTML5DrawingEngine::FillRoundRect(BRect rect, float xRadius, float yRadius,
692 const BGradient& gradient)
693{
694 if (!fClippingRegion.Intersects(rect))
695 return;
696
697 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
698 message.Start(RP_FILL_ROUND_RECT_GRADIENT);
699 message.Add(fToken);
700 message.Add(rect);
701 message.Add(xRadius);
702 message.Add(yRadius);
703 message.AddGradient(gradient);
704}
705
706
707void
708HTML5DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
709 const uint32* opList, int32 pointCount, const BPoint* pointList,
710 bool filled, const BPoint& viewToScreenOffset, float viewScale)
711{
712 BRect clipBounds = bounds;
713 if (!filled)
714 clipBounds.InsetBy(fExtendWidth, fExtendWidth);
715
716 if (!fClippingRegion.Intersects(clipBounds))
717 return;
718
719 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
720 message.Start(filled ? RP_FILL_SHAPE : RP_STROKE_SHAPE);
721 message.Add(fToken);
722 message.Add(bounds);
723 message.Add(opCount);
724 message.AddList(opList, opCount);
725 message.Add(pointCount);
726 message.AddList(pointList, pointCount);
727 message.Add(viewToScreenOffset);
728 message.Add(viewScale);
729}
730
731
732void
733HTML5DrawingEngine::FillShape(const BRect& bounds, int32 opCount,
734 const uint32* opList, int32 pointCount, const BPoint* pointList,
735 const BGradient& gradient, const BPoint& viewToScreenOffset,
736 float viewScale)
737{
738 if (!fClippingRegion.Intersects(bounds))
739 return;
740
741 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
742 message.Start(RP_FILL_SHAPE_GRADIENT);
743 message.Add(fToken);
744 message.Add(bounds);
745 message.Add(opCount);
746 message.AddList(opList, opCount);
747 message.Add(pointCount);
748 message.AddList(pointList, pointCount);
749 message.AddGradient(gradient);
750 message.Add(viewToScreenOffset);
751 message.Add(viewScale);
752}
753
754
755void
756HTML5DrawingEngine::DrawTriangle(BPoint* points, const BRect& bounds,
757 bool filled)
758{
759 BRect clipBounds = bounds;
760 if (!filled)
761 clipBounds.InsetBy(fExtendWidth, fExtendWidth);
762
763 if (!fClippingRegion.Intersects(clipBounds))
764 return;
765
766 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
767 message.Start(filled ? RP_FILL_TRIANGLE : RP_STROKE_TRIANGLE);
768 message.Add(fToken);
769 message.AddList(points, 3);
770 message.Add(bounds);
771}
772
773
774void
775HTML5DrawingEngine::FillTriangle(BPoint* points, const BRect& bounds,
776 const BGradient& gradient)
777{
778 if (!fClippingRegion.Intersects(bounds))
779 return;
780
781 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
782 message.Start(RP_FILL_TRIANGLE_GRADIENT);
783 message.Add(fToken);
784 message.Add(points[0]);
785 message.Add(points[1]);
786 message.Add(points[2]);
787 message.Add(bounds);
788 message.AddGradient(gradient);
789}
790
791
792void
793HTML5DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end)
794{
795 BPoint points[2] = { start, end };
796 BRect bounds = _BuildBounds(points, 2);
797
798 if (!fClippingRegion.Intersects(bounds))
799 return;
800
801 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
802 message.Start(RP_STROKE_LINE);
803 message.Add(fToken);
804 message.AddList(points, 2);
805}
806
807
808void
809HTML5DrawingEngine::StrokeLineArray(int32 numLines,
810 const ViewLineArrayInfo *lineData)
811{
812 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
813 message.Start(RP_STROKE_LINE_ARRAY);
814 message.Add(fToken);
815 message.Add(numLines);
816 for (int32 i = 0; i < numLines; i++)
817 message.AddArrayLine(lineData[i]);
818}
819
820
821// #pragma mark - string functions
822
823
824BPoint
825HTML5DrawingEngine::DrawString(const char* string, int32 length,
826 const BPoint& point, escapement_delta* delta)
827{
828 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
829
830 message.Start(RP_DRAW_STRING);
831 message.Add(fToken);
832 message.Add(point);
833 message.AddString(string, length);
834 message.Add(delta != NULL__null);
835 if (delta != NULL__null)
836 message.AddList(delta, length);
837
838 status_t result = _AddCallback();
839 if (message.Flush() != B_OK((int)0))
840 return point;
841
842 if (result != B_OK((int)0))
843 return point;
844
845 do {
846 result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
847 1 * 1000 * 1000);
848 } while (result == B_INTERRUPTED((-2147483647 - 1) + 10));
849
850 if (result != B_OK((int)0))
851 return point;
852
853 return fDrawStringResult;
854}
855
856
857BPoint
858HTML5DrawingEngine::DrawString(const char* string, int32 length,
859 const BPoint* offsets)
860{
861 // Guaranteed to have at least one point.
862 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
863
864 message.Start(RP_DRAW_STRING_WITH_OFFSETS);
865 message.Add(fToken);
866 message.AddString(string, length);
867 message.AddList(offsets, UTF8CountChars(string, length));
868
869 status_t result = _AddCallback();
870 if (message.Flush() != B_OK((int)0))
871 return offsets[0];
872
873 if (result != B_OK((int)0))
874 return offsets[0];
875
876 do {
877 result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
878 1 * 1000 * 1000);
879 } while (result == B_INTERRUPTED((-2147483647 - 1) + 10));
880
881 if (result != B_OK((int)0))
882 return offsets[0];
883
884 return fDrawStringResult;
885}
886
887
888float
889HTML5DrawingEngine::StringWidth(const char* string, int32 length,
890 escapement_delta* delta)
891{
892 // TODO: decide if really needed and use callback if so
893 return fState.Font().StringWidth(string, length, delta);
894}
895
896
897// #pragma mark -
898
899
900status_t
901HTML5DrawingEngine::ReadBitmap(ServerBitmap* bitmap, bool drawCursor,
902 BRect bounds)
903{
904 if (_AddCallback() != B_OK((int)0))
905 return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14);
906
907 CanvasMessage message(NULL__null, fHWInterface->SendBuffer());
908
909 message.Start(RP_READ_BITMAP);
910 message.Add(fToken);
911 message.Add(bounds);
912 message.Add(drawCursor);
913 if (message.Flush() != B_OK((int)0))
914 return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14);
915
916 status_t result;
917 do {
918 result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
919 100 * 1000 * 1000);
920 } while (result == B_INTERRUPTED((-2147483647 - 1) + 10));
921
922 if (result != B_OK((int)0))
923 return result;
924
925 BBitmap* read = fReadBitmapResult;
926 if (read == NULL__null)
927 return B_UNSUPPORTED(((-2147483647 - 1) + 0x6000) + 14);
928
929 result = bitmap->ImportBits(read->Bits(), read->BitsLength(),
930 read->BytesPerRow(), read->ColorSpace());
931 delete read;
932 return result;
933}
934
935
936// #pragma mark -
937
938
939status_t
940HTML5DrawingEngine::_AddCallback()
941{
942 if (fCallbackAdded)
943 return B_OK((int)0);
944
945 if (fResultNotify < 0)
946 fResultNotify = create_sem(0, "drawing engine result");
947 if (fResultNotify < 0)
948 return fResultNotify;
949
950 status_t result = fHWInterface->AddCallback(fToken, &_DrawingEngineResult,
951 this);
952
953 fCallbackAdded = result == B_OK((int)0);
954 return result;
955}
956
957
958bool
959HTML5DrawingEngine::_DrawingEngineResult(void* cookie, CanvasMessage& message)
960{
961 HTML5DrawingEngine* engine = (HTML5DrawingEngine*)cookie;
962
963 switch (message.Code()) {
964 case RP_DRAW_STRING_RESULT:
965 if (message.Read(engine->fDrawStringResult) != B_OK((int)0))
966 return false;
967 break;
968
969 case RP_STRING_WIDTH_RESULT:
970 if (message.Read(engine->fStringWidthResult) != B_OK((int)0))
971 return false;
972 break;
973
974 case RP_READ_BITMAP_RESULT:
975 if (message.ReadBitmap(&engine->fReadBitmapResult) != B_OK((int)0))
976 return false;
977 break;
978
979 default:
980 return false;
981 }
982
983 release_sem(engine->fResultNotify);
984 return true;
985}
986
987
988BRect
989HTML5DrawingEngine::_BuildBounds(BPoint* points, int32 pointCount)
990{
991 BRect bounds(1000000, 1000000, 0, 0);
992 for (int32 i = 0; i < pointCount; i++) {
993 bounds.left = min_c(bounds.left, points[i].x)((bounds.left)>(points[i].x)?(points[i].x):(bounds.left));
994 bounds.top = min_c(bounds.top, points[i].y)((bounds.top)>(points[i].y)?(points[i].y):(bounds.top));
995 bounds.right = max_c(bounds.right, points[i].x)((bounds.right)>(points[i].x)?(bounds.right):(points[i].x)
)
;
996 bounds.bottom = max_c(bounds.bottom, points[i].y)((bounds.bottom)>(points[i].y)?(bounds.bottom):(points[i].
y))
;
997 }
998
999 return bounds;
1000}
1001
1002
1003status_t
1004HTML5DrawingEngine::_ExtractBitmapRegions(ServerBitmap& bitmap, uint32 options,
1005 const BRect& bitmapRect, const BRect& viewRect, double xScale,
1006 double yScale, BRegion& region, UtilityBitmap**& bitmaps)
1007{
1008 int32 rectCount = region.CountRects();
1009 bitmaps = (UtilityBitmap**)malloc(rectCount * sizeof(UtilityBitmap*));
1010 if (bitmaps == NULL__null)
1
Taking false branch
1011 return B_NO_MEMORY((-2147483647 - 1) + 0);
1012
1013 for (int32 i = 0; i < rectCount; i++) {
2
Assuming 'i' is < 'rectCount'
3
Loop condition is true. Entering loop body
10
Assuming 'i' is < 'rectCount'
11
Loop condition is true. Entering loop body
1014 BRect sourceRect = region.RectAt(i).OffsetByCopy(-viewRect.LeftTop());
1015 int32 targetWidth = (int32)(sourceRect.Width() + 1.5);
1016 int32 targetHeight = (int32)(sourceRect.Height() + 1.5);
1017
1018 if (xScale != 1.0) {
4
Taking false branch
12
Taking false branch
1019 sourceRect.left = (int32)(sourceRect.left * xScale + 0.5);
1020 sourceRect.right = (int32)(sourceRect.right * xScale + 0.5);
1021 if (xScale < 1.0)
1022 targetWidth = (int32)(sourceRect.Width() + 1.5);
1023 }
1024
1025 if (yScale != 1.0) {
5
Taking false branch
13
Taking false branch
1026 sourceRect.top = (int32)(sourceRect.top * yScale + 0.5);
1027 sourceRect.bottom = (int32)(sourceRect.bottom * yScale + 0.5);
1028 if (yScale < 1.0)
1029 targetHeight = (int32)(sourceRect.Height() + 1.5);
1030 }
1031
1032 sourceRect.OffsetBy(bitmapRect.LeftTop());
1033 // sourceRect is now the part of the bitmap we want copied
1034
1035 status_t result = B_OK((int)0);
1036 if ((xScale > 1.0 || yScale > 1.0)
1037 && (targetWidth * targetHeight < (int32)(sourceRect.Width() + 1.5)
1038 * (int32)(sourceRect.Height() + 1.5))) {
1039 // the target bitmap is smaller than the source, scale it locally
1040 // and send over the smaller version to avoid sending any extra data
1041 if (fBitmapDrawingEngine == NULL__null) {
1042 fBitmapDrawingEngine
1043 = new(std::nothrow) BitmapDrawingEngine(B_RGBA32);
1044 if (fBitmapDrawingEngine == NULL__null)
1045 result = B_NO_MEMORY((-2147483647 - 1) + 0);
1046 }
1047
1048 if (result == B_OK((int)0)) {
1049 result = fBitmapDrawingEngine->SetSize(targetWidth,
1050 targetHeight);
1051 }
1052
1053 if (result == B_OK((int)0)) {
1054 fBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
1055
1056 switch (bitmap.ColorSpace()) {
1057 case B_RGBA32:
1058 case B_RGBA32_BIG:
1059 case B_RGBA15:
1060 case B_RGBA15_BIG:
1061 break;
1062
1063 default:
1064 {
1065 // we need to clear the background if there may be
1066 // transparency through transparent magic (we use
1067 // B_OP_COPY when we draw alpha enabled bitmaps, so we
1068 // don't need to clear there)
1069 // TODO: this is not actually correct, as we're going to
1070 // loose the transparency with the conversion to the
1071 // original non-alpha colorspace happening in
1072 // ExportToBitmap
1073 rgb_color background = { 0, 0, 0, 0 };
1074 fBitmapDrawingEngine->FillRect(
1075 BRect(0, 0, targetWidth - 1, targetHeight -1),
1076 background);
1077 fBitmapDrawingEngine->SetDrawingMode(B_OP_OVER);
1078 break;
1079 }
1080 }
1081
1082 fBitmapDrawingEngine->DrawBitmap(&bitmap, sourceRect,
1083 BRect(0, 0, targetWidth - 1, targetHeight - 1), options);
1084 bitmaps[i] = fBitmapDrawingEngine->ExportToBitmap(targetWidth,
1085 targetHeight, bitmap.ColorSpace());
1086 if (bitmaps[i] == NULL__null)
1087 result = B_NO_MEMORY((-2147483647 - 1) + 0);
1088 }
1089 } else {
1090 // source is smaller or equal target, extract the relevant rects
1091 // directly without any scaling and conversion
1092 targetWidth = (int32)(sourceRect.Width() + 1.5);
1093 targetHeight = (int32)(sourceRect.Height() + 1.5);
1094
1095 bitmaps[i] = new(std::nothrow) UtilityBitmap(
1096 BRect(0, 0, targetWidth - 1, targetHeight - 1),
1097 bitmap.ColorSpace(), 0);
1098 if (bitmaps[i] == NULL__null)
6
Taking false branch
14
Taking true branch
1099 result = B_NO_MEMORY((-2147483647 - 1) + 0);
1100
1101 result = bitmaps[i]->ImportBits(bitmap.Bits(), bitmap.BitsLength(),
15
Called C++ object pointer is null
1102 bitmap.BytesPerRow(), bitmap.ColorSpace(), sourceRect.LeftTop(),
1103 BPoint(0, 0), targetWidth, targetHeight);
1104 if (result != B_OK((int)0))
7
Assuming 'result' is equal to 0
8
Taking false branch
1105 delete bitmaps[i];
1106 }
1107
1108 if (result != B_OK((int)0)) {
9
Taking false branch
1109 for (int32 j = 0; j < i; j++)
1110 delete bitmaps[j];
1111 free(bitmaps);
1112 return result;
1113 }
1114 }
1115
1116 return B_OK((int)0);
1117}