xref: /haiku/src/servers/app/DrawState.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2001-2018, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Adi Oanca <adioanca@mymail.ro>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  *		Axel Dörfler, axeld@pinc-software.de
10  *		Michael Pfeiffer <laplace@users.sourceforge.net>
11  *		Julian Harnath <julian.harnath@rwth-aachen.de>
12  *		Joseph Groover <looncraz@looncraz.net>
13  */
14 
15 //!	Data classes for working with BView states and draw parameters
16 
17 #include "DrawState.h"
18 
19 #include <new>
20 #include <stdio.h>
21 
22 #include <Region.h>
23 #include <ShapePrivate.h>
24 
25 #include "AlphaMask.h"
26 #include "LinkReceiver.h"
27 #include "LinkSender.h"
28 #include "ServerProtocolStructs.h"
29 
30 
31 using std::nothrow;
32 
33 
34 DrawState::DrawState()
35 	:
36 	fOrigin(0.0f, 0.0f),
37 	fCombinedOrigin(0.0f, 0.0f),
38 	fScale(1.0f),
39 	fCombinedScale(1.0f),
40 	fTransform(),
41 	fCombinedTransform(),
42 	fClippingRegion(NULL),
43 	fAlphaMask(NULL),
44 
45 	fHighColor((rgb_color){ 0, 0, 0, 255 }),
46 	fLowColor((rgb_color){ 255, 255, 255, 255 }),
47 	fWhichHighColor(B_NO_COLOR),
48 	fWhichLowColor(B_NO_COLOR),
49 	fWhichHighColorTint(B_NO_TINT),
50 	fWhichLowColorTint(B_NO_TINT),
51 	fPattern(kSolidHigh),
52 
53 	fDrawingMode(B_OP_COPY),
54 	fAlphaSrcMode(B_PIXEL_ALPHA),
55 	fAlphaFncMode(B_ALPHA_OVERLAY),
56 	fDrawingModeLocked(false),
57 
58 	fPenLocation(0.0f, 0.0f),
59 	fPenSize(1.0f),
60 
61 	fFontAliasing(false),
62 	fSubPixelPrecise(false),
63 	fLineCapMode(B_BUTT_CAP),
64 	fLineJoinMode(B_MITER_JOIN),
65 	fMiterLimit(B_DEFAULT_MITER_LIMIT),
66 	fFillRule(B_NONZERO),
67 	fPreviousState(NULL)
68 {
69 	fUnscaledFontSize = fFont.Size();
70 }
71 
72 
73 DrawState::DrawState(const DrawState& other)
74 	:
75 	fOrigin(other.fOrigin),
76 	fCombinedOrigin(other.fCombinedOrigin),
77 	fScale(other.fScale),
78 	fCombinedScale(other.fCombinedScale),
79 	fTransform(other.fTransform),
80 	fCombinedTransform(other.fCombinedTransform),
81 	fClippingRegion(NULL),
82 	fAlphaMask(NULL),
83 
84 	fHighColor(other.fHighColor),
85 	fLowColor(other.fLowColor),
86 	fWhichHighColor(other.fWhichHighColor),
87 	fWhichLowColor(other.fWhichLowColor),
88 	fWhichHighColorTint(other.fWhichHighColorTint),
89 	fWhichLowColorTint(other.fWhichLowColorTint),
90 	fPattern(other.fPattern),
91 
92 	fDrawingMode(other.fDrawingMode),
93 	fAlphaSrcMode(other.fAlphaSrcMode),
94 	fAlphaFncMode(other.fAlphaFncMode),
95 	fDrawingModeLocked(other.fDrawingModeLocked),
96 
97 	fPenLocation(other.fPenLocation),
98 	fPenSize(other.fPenSize),
99 
100 	fFont(other.fFont),
101 	fFontAliasing(other.fFontAliasing),
102 
103 	fSubPixelPrecise(other.fSubPixelPrecise),
104 
105 	fLineCapMode(other.fLineCapMode),
106 	fLineJoinMode(other.fLineJoinMode),
107 	fMiterLimit(other.fMiterLimit),
108 	fFillRule(other.fFillRule),
109 
110 	// Since fScale is reset to 1.0, the unscaled
111 	// font size is the current size of the font
112 	// (which is from->fUnscaledFontSize * from->fCombinedScale)
113 	fUnscaledFontSize(other.fUnscaledFontSize),
114 	fPreviousState(NULL)
115 {
116 }
117 
118 
119 DrawState::~DrawState()
120 {
121 	delete fClippingRegion;
122 	delete fPreviousState;
123 }
124 
125 
126 DrawState*
127 DrawState::PushState()
128 {
129 	DrawState* next = new (nothrow) DrawState(*this);
130 
131 	if (next != NULL) {
132 		// Prepare state as derived from this state
133 		next->fOrigin = BPoint(0.0, 0.0);
134 		next->fScale = 1.0;
135 		next->fTransform.Reset();
136 		next->fPreviousState = this;
137 		next->SetAlphaMask(fAlphaMask);
138 	}
139 
140 	return next;
141 }
142 
143 
144 DrawState*
145 DrawState::PopState()
146 {
147 	DrawState* previous = PreviousState();
148 
149 	fPreviousState = NULL;
150 	delete this;
151 
152 	return previous;
153 }
154 
155 
156 uint16
157 DrawState::ReadFontFromLink(BPrivate::LinkReceiver& link)
158 {
159 	uint16 mask;
160 	link.Read<uint16>(&mask);
161 
162 	if ((mask & B_FONT_FAMILY_AND_STYLE) != 0) {
163 		uint32 fontID;
164 		link.Read<uint32>(&fontID);
165 		fFont.SetFamilyAndStyle(fontID);
166 	}
167 
168 	if ((mask & B_FONT_SIZE) != 0) {
169 		float size;
170 		link.Read<float>(&size);
171 		fUnscaledFontSize = size;
172 		fFont.SetSize(fUnscaledFontSize * fCombinedScale);
173 	}
174 
175 	if ((mask & B_FONT_SHEAR) != 0) {
176 		float shear;
177 		link.Read<float>(&shear);
178 		fFont.SetShear(shear);
179 	}
180 
181 	if ((mask & B_FONT_ROTATION) != 0) {
182 		float rotation;
183 		link.Read<float>(&rotation);
184 		fFont.SetRotation(rotation);
185 	}
186 
187 	if ((mask & B_FONT_FALSE_BOLD_WIDTH) != 0) {
188 		float falseBoldWidth;
189 		link.Read<float>(&falseBoldWidth);
190 		fFont.SetFalseBoldWidth(falseBoldWidth);
191 	}
192 
193 	if ((mask & B_FONT_SPACING) != 0) {
194 		uint8 spacing;
195 		link.Read<uint8>(&spacing);
196 		fFont.SetSpacing(spacing);
197 	}
198 
199 	if ((mask & B_FONT_ENCODING) != 0) {
200 		uint8 encoding;
201 		link.Read<uint8>(&encoding);
202 		fFont.SetEncoding(encoding);
203 	}
204 
205 	if ((mask & B_FONT_FACE) != 0) {
206 		uint16 face;
207 		link.Read<uint16>(&face);
208 		fFont.SetFace(face);
209 	}
210 
211 	if ((mask & B_FONT_FLAGS) != 0) {
212 		uint32 flags;
213 		link.Read<uint32>(&flags);
214 		fFont.SetFlags(flags);
215 	}
216 
217 	return mask;
218 }
219 
220 
221 void
222 DrawState::ReadFromLink(BPrivate::LinkReceiver& link)
223 {
224 	ViewSetStateInfo info;
225 
226 	link.Read<ViewSetStateInfo>(&info);
227 
228 	// BAffineTransform is transmitted as a double array
229 	double transform[6];
230 	link.Read<double[6]>(&transform);
231 	if (fTransform.Unflatten(B_AFFINE_TRANSFORM_TYPE, transform,
232 		sizeof(transform)) != B_OK) {
233 		return;
234 	}
235 
236 	fPenLocation = info.penLocation;
237 	fPenSize = info.penSize;
238 	fHighColor = info.highColor;
239 	fLowColor = info.lowColor;
240 	fWhichHighColor = info.whichHighColor;
241 	fWhichLowColor = info.whichLowColor;
242 	fWhichHighColorTint = info.whichHighColorTint;
243 	fWhichLowColorTint = info.whichLowColorTint;
244 	fPattern = info.pattern;
245 	fDrawingMode = info.drawingMode;
246 	fOrigin = info.origin;
247 	fScale = info.scale;
248 	fLineJoinMode = info.lineJoin;
249 	fLineCapMode = info.lineCap;
250 	fMiterLimit = info.miterLimit;
251 	fFillRule = info.fillRule;
252 	fAlphaSrcMode = info.alphaSourceMode;
253 	fAlphaFncMode = info.alphaFunctionMode;
254 	fFontAliasing = info.fontAntialiasing;
255 
256 	if (fPreviousState != NULL) {
257 		fCombinedOrigin = fPreviousState->fCombinedOrigin + fOrigin;
258 		fCombinedScale = fPreviousState->fCombinedScale * fScale;
259 		fCombinedTransform = fPreviousState->fCombinedTransform * fTransform;
260 	} else {
261 		fCombinedOrigin = fOrigin;
262 		fCombinedScale = fScale;
263 		fCombinedTransform = fTransform;
264 	}
265 
266 
267 	// read clipping
268 	// TODO: This could be optimized, but the user clipping regions are rarely
269 	// used, so it's low priority...
270 	int32 clipRectCount;
271 	link.Read<int32>(&clipRectCount);
272 
273 	if (clipRectCount >= 0) {
274 		BRegion region;
275 		BRect rect;
276 		for (int32 i = 0; i < clipRectCount; i++) {
277 			link.Read<BRect>(&rect);
278 			region.Include(rect);
279 		}
280 		SetClippingRegion(&region);
281 	} else {
282 		// No user clipping used
283 		SetClippingRegion(NULL);
284 	}
285 }
286 
287 
288 void
289 DrawState::WriteToLink(BPrivate::LinkSender& link) const
290 {
291 	// Attach font state
292 	ViewGetStateInfo info;
293 	info.fontID = fFont.GetFamilyAndStyle();
294 	info.fontSize = fFont.Size();
295 	info.fontShear = fFont.Shear();
296 	info.fontRotation = fFont.Rotation();
297 	info.fontFalseBoldWidth = fFont.FalseBoldWidth();
298 	info.fontSpacing = fFont.Spacing();
299 	info.fontEncoding = fFont.Encoding();
300 	info.fontFace = fFont.Face();
301 	info.fontFlags = fFont.Flags();
302 
303 	// Attach view state
304 	info.viewStateInfo.penLocation = fPenLocation;
305 	info.viewStateInfo.penSize = fPenSize;
306 	info.viewStateInfo.highColor = fHighColor;
307 	info.viewStateInfo.lowColor = fLowColor;
308 	info.viewStateInfo.whichHighColor = fWhichHighColor;
309 	info.viewStateInfo.whichLowColor = fWhichLowColor;
310 	info.viewStateInfo.whichHighColorTint = fWhichHighColorTint;
311 	info.viewStateInfo.whichLowColorTint = fWhichLowColorTint;
312 	info.viewStateInfo.pattern = (::pattern)fPattern.GetPattern();
313 	info.viewStateInfo.drawingMode = fDrawingMode;
314 	info.viewStateInfo.origin = fOrigin;
315 	info.viewStateInfo.scale = fScale;
316 	info.viewStateInfo.lineJoin = fLineJoinMode;
317 	info.viewStateInfo.lineCap = fLineCapMode;
318 	info.viewStateInfo.miterLimit = fMiterLimit;
319 	info.viewStateInfo.fillRule = fFillRule;
320 	info.viewStateInfo.alphaSourceMode = fAlphaSrcMode;
321 	info.viewStateInfo.alphaFunctionMode = fAlphaFncMode;
322 	info.viewStateInfo.fontAntialiasing = fFontAliasing;
323 
324 
325 	link.Attach<ViewGetStateInfo>(info);
326 
327 	// BAffineTransform is transmitted as a double array
328 	double transform[6];
329 	if (fTransform.Flatten(transform, sizeof(transform)) != B_OK)
330 		return;
331 	link.Attach<double[6]>(transform);
332 
333 	// TODO: Could be optimized, but is low prio, since most views do not
334 	// use a custom clipping region...
335 	if (fClippingRegion != NULL) {
336 		int32 clippingRectCount = fClippingRegion->CountRects();
337 		link.Attach<int32>(clippingRectCount);
338 		for (int i = 0; i < clippingRectCount; i++)
339 			link.Attach<BRect>(fClippingRegion->RectAt(i));
340 	} else {
341 		// no client clipping
342 		link.Attach<int32>(-1);
343 	}
344 }
345 
346 
347 void
348 DrawState::SetOrigin(BPoint origin)
349 {
350 	fOrigin = origin;
351 
352 	// NOTE: the origins of earlier states are never expected to
353 	// change, only the topmost state ever changes
354 	if (fPreviousState != NULL) {
355 		fCombinedOrigin.x = fPreviousState->fCombinedOrigin.x
356 			+ fOrigin.x * fPreviousState->fCombinedScale;
357 		fCombinedOrigin.y = fPreviousState->fCombinedOrigin.y
358 			+ fOrigin.y * fPreviousState->fCombinedScale;
359 	} else {
360 		fCombinedOrigin = fOrigin;
361 	}
362 }
363 
364 
365 void
366 DrawState::SetScale(float scale)
367 {
368 	if (fScale == scale)
369 		return;
370 
371 	fScale = scale;
372 
373 	// NOTE: the scales of earlier states are never expected to
374 	// change, only the topmost state ever changes
375 	if (fPreviousState != NULL)
376 		fCombinedScale = fPreviousState->fCombinedScale * fScale;
377 	else
378 		fCombinedScale = fScale;
379 
380 	// update font size
381 	// NOTE: This is what makes the call potentially expensive,
382 	// hence the introductory check
383 	fFont.SetSize(fUnscaledFontSize * fCombinedScale);
384 }
385 
386 
387 void
388 DrawState::SetTransform(BAffineTransform transform)
389 {
390 	if (fTransform == transform)
391 		return;
392 
393 	fTransform = transform;
394 
395 	// NOTE: the transforms of earlier states are never expected to
396 	// change, only the topmost state ever changes
397 	if (fPreviousState != NULL)
398 		fCombinedTransform = fPreviousState->fCombinedTransform * fTransform;
399 	else
400 		fCombinedTransform = fTransform;
401 }
402 
403 
404 /* Can be used to temporarily disable all BAffineTransforms in the state
405    stack, and later reenable them.
406 */
407 void
408 DrawState::SetTransformEnabled(bool enabled)
409 {
410 	if (enabled) {
411 		BAffineTransform temp = fTransform;
412 		SetTransform(BAffineTransform());
413 		SetTransform(temp);
414 	}
415 	else
416 		fCombinedTransform = BAffineTransform();
417 }
418 
419 
420 DrawState*
421 DrawState::Squash() const
422 {
423 	DrawState* const squashedState = new(nothrow) DrawState(*this);
424 	return squashedState->PushState();
425 }
426 
427 
428 void
429 DrawState::SetClippingRegion(const BRegion* region)
430 {
431 	if (region) {
432 		if (fClippingRegion != NULL)
433 			*fClippingRegion = *region;
434 		else
435 			fClippingRegion = new(nothrow) BRegion(*region);
436 	} else {
437 		delete fClippingRegion;
438 		fClippingRegion = NULL;
439 	}
440 }
441 
442 
443 bool
444 DrawState::HasClipping() const
445 {
446 	if (fClippingRegion != NULL)
447 		return true;
448 	if (fPreviousState != NULL)
449 		return fPreviousState->HasClipping();
450 	return false;
451 }
452 
453 
454 bool
455 DrawState::HasAdditionalClipping() const
456 {
457 	return fClippingRegion != NULL;
458 }
459 
460 
461 bool
462 DrawState::GetCombinedClippingRegion(BRegion* region) const
463 {
464 	if (fClippingRegion != NULL) {
465 		BRegion localTransformedClipping(*fClippingRegion);
466 		SimpleTransform penTransform;
467 		Transform(penTransform);
468 		penTransform.Apply(&localTransformedClipping);
469 		if (fPreviousState != NULL
470 			&& fPreviousState->GetCombinedClippingRegion(region)) {
471 			localTransformedClipping.IntersectWith(region);
472 		}
473 		*region = localTransformedClipping;
474 		return true;
475 	} else {
476 		if (fPreviousState != NULL)
477 			return fPreviousState->GetCombinedClippingRegion(region);
478 	}
479 	return false;
480 }
481 
482 
483 bool
484 DrawState::ClipToRect(BRect rect, bool inverse)
485 {
486 	if (!rect.IsValid())
487 		return false;
488 
489 	if (!fCombinedTransform.IsIdentity()) {
490 		if (fCombinedTransform.IsDilation()) {
491 			BPoint points[2] = { rect.LeftTop(), rect.RightBottom() };
492 			fCombinedTransform.Apply(&points[0], 2);
493 			rect.Set(points[0].x, points[0].y, points[1].x, points[1].y);
494 		} else {
495 			uint32 ops[] = {
496 				OP_MOVETO | OP_LINETO | 3,
497 				OP_CLOSE
498 			};
499 			BPoint points[4] = {
500 				BPoint(rect.left,  rect.top),
501 				BPoint(rect.right, rect.top),
502 				BPoint(rect.right, rect.bottom),
503 				BPoint(rect.left,  rect.bottom)
504 			};
505 			shape_data rectShape;
506 			rectShape.opList = &ops[0];
507 			rectShape.opCount = 2;
508 			rectShape.opSize = sizeof(uint32) * 2;
509 			rectShape.ptList = &points[0];
510 			rectShape.ptCount = 4;
511 			rectShape.ptSize = sizeof(BPoint) * 4;
512 
513 			ClipToShape(&rectShape, inverse);
514 			return true;
515 		}
516 	}
517 
518 	if (inverse) {
519 		if (fClippingRegion == NULL) {
520 			fClippingRegion = new(nothrow) BRegion(BRect(
521 				-(1 << 16), -(1 << 16), (1 << 16), (1 << 16)));
522 				// TODO: we should have a definition for a rect (or region)
523 				// with "infinite" area. For now, this region size should do...
524 		}
525 		fClippingRegion->Exclude(rect);
526 	} else {
527 		if (fClippingRegion == NULL)
528 			fClippingRegion = new(nothrow) BRegion(rect);
529 		else {
530 			BRegion rectRegion(rect);
531 			fClippingRegion->IntersectWith(&rectRegion);
532 		}
533 	}
534 
535 	return false;
536 }
537 
538 
539 void
540 DrawState::ClipToShape(shape_data* shape, bool inverse)
541 {
542 	if (shape->ptCount == 0)
543 		return;
544 
545 	if (!fCombinedTransform.IsIdentity())
546 		fCombinedTransform.Apply(shape->ptList, shape->ptCount);
547 
548 	AlphaMask* const mask = ShapeAlphaMask::Create(GetAlphaMask(), *shape,
549 		BPoint(0, 0), inverse);
550 
551 	SetAlphaMask(mask);
552 	if (mask != NULL)
553 		mask->ReleaseReference();
554 }
555 
556 
557 void
558 DrawState::SetAlphaMask(AlphaMask* mask)
559 {
560 	// NOTE: In BeOS, it wasn't possible to clip to a BPicture and keep
561 	// regular custom clipping to a BRegion at the same time.
562 	fAlphaMask.SetTo(mask);
563 }
564 
565 
566 AlphaMask*
567 DrawState::GetAlphaMask() const
568 {
569 	return fAlphaMask.Get();
570 }
571 
572 
573 // #pragma mark -
574 
575 
576 void
577 DrawState::Transform(SimpleTransform& transform) const
578 {
579 	transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
580 	transform.SetScale(fCombinedScale);
581 }
582 
583 
584 void
585 DrawState::InverseTransform(SimpleTransform& transform) const
586 {
587 	transform.AddOffset(-fCombinedOrigin.x, -fCombinedOrigin.y);
588 	if (fCombinedScale != 0.0)
589 		transform.SetScale(1.0 / fCombinedScale);
590 }
591 
592 
593 // #pragma mark -
594 
595 
596 void
597 DrawState::SetHighColor(rgb_color color)
598 {
599 	fHighColor = color;
600 }
601 
602 
603 void
604 DrawState::SetLowColor(rgb_color color)
605 {
606 	fLowColor = color;
607 }
608 
609 
610 void
611 DrawState::SetHighUIColor(color_which which, float tint)
612 {
613 	fWhichHighColor = which;
614 	fWhichHighColorTint = tint;
615 }
616 
617 
618 color_which
619 DrawState::HighUIColor(float* tint) const
620 {
621 	if (tint != NULL)
622 		*tint = fWhichHighColorTint;
623 
624 	return fWhichHighColor;
625 }
626 
627 
628 void
629 DrawState::SetLowUIColor(color_which which, float tint)
630 {
631 	fWhichLowColor = which;
632 	fWhichLowColorTint = tint;
633 }
634 
635 
636 color_which
637 DrawState::LowUIColor(float* tint) const
638 {
639 	if (tint != NULL)
640 		*tint = fWhichLowColorTint;
641 
642 	return fWhichLowColor;
643 }
644 
645 
646 void
647 DrawState::SetPattern(const Pattern& pattern)
648 {
649 	fPattern = pattern;
650 }
651 
652 
653 bool
654 DrawState::SetDrawingMode(drawing_mode mode)
655 {
656 	if (!fDrawingModeLocked) {
657 		fDrawingMode = mode;
658 		return true;
659 	}
660 	return false;
661 }
662 
663 
664 bool
665 DrawState::SetBlendingMode(source_alpha srcMode, alpha_function fncMode)
666 {
667 	if (!fDrawingModeLocked) {
668 		fAlphaSrcMode = srcMode;
669 		fAlphaFncMode = fncMode;
670 		return true;
671 	}
672 	return false;
673 }
674 
675 
676 void
677 DrawState::SetDrawingModeLocked(bool locked)
678 {
679 	fDrawingModeLocked = locked;
680 }
681 
682 
683 
684 void
685 DrawState::SetPenLocation(BPoint location)
686 {
687 	fPenLocation = location;
688 }
689 
690 
691 BPoint
692 DrawState::PenLocation() const
693 {
694 	return fPenLocation;
695 }
696 
697 
698 void
699 DrawState::SetPenSize(float size)
700 {
701 	fPenSize = size;
702 }
703 
704 
705 //! returns the scaled pen size
706 float
707 DrawState::PenSize() const
708 {
709 	float penSize = fPenSize * fCombinedScale;
710 	// NOTE: As documented in the BeBook,
711 	// pen size is never smaller than 1.0.
712 	// This is supposed to be the smallest
713 	// possible device size.
714 	if (penSize < 1.0)
715 		penSize = 1.0;
716 	return penSize;
717 }
718 
719 
720 //! returns the unscaled pen size
721 float
722 DrawState::UnscaledPenSize() const
723 {
724 	// NOTE: As documented in the BeBook,
725 	// pen size is never smaller than 1.0.
726 	// This is supposed to be the smallest
727 	// possible device size.
728 	return max_c(fPenSize, 1.0);
729 }
730 
731 
732 //! sets the font to be already scaled by fScale
733 void
734 DrawState::SetFont(const ServerFont& font, uint32 flags)
735 {
736 	if (flags == B_FONT_ALL) {
737 		fFont = font;
738 		fUnscaledFontSize = font.Size();
739 		fFont.SetSize(fUnscaledFontSize * fCombinedScale);
740 	} else {
741 		// family & style
742 		if ((flags & B_FONT_FAMILY_AND_STYLE) != 0)
743 			fFont.SetFamilyAndStyle(font.GetFamilyAndStyle());
744 		// size
745 		if ((flags & B_FONT_SIZE) != 0) {
746 			fUnscaledFontSize = font.Size();
747 			fFont.SetSize(fUnscaledFontSize * fCombinedScale);
748 		}
749 		// shear
750 		if ((flags & B_FONT_SHEAR) != 0)
751 			fFont.SetShear(font.Shear());
752 		// rotation
753 		if ((flags & B_FONT_ROTATION) != 0)
754 			fFont.SetRotation(font.Rotation());
755 		// spacing
756 		if ((flags & B_FONT_SPACING) != 0)
757 			fFont.SetSpacing(font.Spacing());
758 		// encoding
759 		if ((flags & B_FONT_ENCODING) != 0)
760 			fFont.SetEncoding(font.Encoding());
761 		// face
762 		if ((flags & B_FONT_FACE) != 0)
763 			fFont.SetFace(font.Face());
764 		// flags
765 		if ((flags & B_FONT_FLAGS) != 0)
766 			fFont.SetFlags(font.Flags());
767 	}
768 }
769 
770 
771 void
772 DrawState::SetForceFontAliasing(bool aliasing)
773 {
774 	fFontAliasing = aliasing;
775 }
776 
777 
778 void
779 DrawState::SetSubPixelPrecise(bool precise)
780 {
781 	fSubPixelPrecise = precise;
782 }
783 
784 
785 void
786 DrawState::SetLineCapMode(cap_mode mode)
787 {
788 	fLineCapMode = mode;
789 }
790 
791 
792 void
793 DrawState::SetLineJoinMode(join_mode mode)
794 {
795 	fLineJoinMode = mode;
796 }
797 
798 
799 void
800 DrawState::SetMiterLimit(float limit)
801 {
802 	fMiterLimit = limit;
803 }
804 
805 
806 void
807 DrawState::SetFillRule(int32 fillRule)
808 {
809 	fFillRule = fillRule;
810 }
811 
812 
813 void
814 DrawState::PrintToStream() const
815 {
816 	printf("\t Origin: (%.1f, %.1f)\n", fOrigin.x, fOrigin.y);
817 	printf("\t Scale: %.2f\n", fScale);
818 	printf("\t Transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
819 		fTransform.sx, fTransform.shy, fTransform.shx,
820 		fTransform.sy, fTransform.tx, fTransform.ty);
821 
822 	printf("\t Pen Location and Size: (%.1f, %.1f) - %.2f (%.2f)\n",
823 		   fPenLocation.x, fPenLocation.y, PenSize(), fPenSize);
824 
825 	printf("\t HighColor: r=%d g=%d b=%d a=%d\n",
826 		fHighColor.red, fHighColor.green, fHighColor.blue, fHighColor.alpha);
827 	printf("\t LowColor: r=%d g=%d b=%d a=%d\n",
828 		fLowColor.red, fLowColor.green, fLowColor.blue, fLowColor.alpha);
829 	printf("\t WhichHighColor: %i\n", fWhichHighColor);
830 	printf("\t WhichLowColor: %i\n", fWhichLowColor);
831 	printf("\t WhichHighColorTint: %.3f\n", fWhichHighColorTint);
832 	printf("\t WhichLowColorTint: %.3f\n", fWhichLowColorTint);
833 	printf("\t Pattern: %" B_PRIu64 "\n", fPattern.GetInt64());
834 
835 	printf("\t DrawMode: %" B_PRIu32 "\n", (uint32)fDrawingMode);
836 	printf("\t AlphaSrcMode: %" B_PRId32 "\t AlphaFncMode: %" B_PRId32 "\n",
837 		   (int32)fAlphaSrcMode, (int32)fAlphaFncMode);
838 
839 	printf("\t LineCap: %d\t LineJoin: %d\t MiterLimit: %.2f\n",
840 		   (int16)fLineCapMode, (int16)fLineJoinMode, fMiterLimit);
841 
842 	if (fClippingRegion != NULL)
843 		fClippingRegion->PrintToStream();
844 
845 	printf("\t ===== Font Data =====\n");
846 	printf("\t Style: CURRENTLY NOT SET\n"); // ???
847 	printf("\t Size: %.1f (%.1f)\n", fFont.Size(), fUnscaledFontSize);
848 	printf("\t Shear: %.2f\n", fFont.Shear());
849 	printf("\t Rotation: %.2f\n", fFont.Rotation());
850 	printf("\t Spacing: %" B_PRId32 "\n", fFont.Spacing());
851 	printf("\t Encoding: %" B_PRId32 "\n", fFont.Encoding());
852 	printf("\t Face: %d\n", fFont.Face());
853 	printf("\t Flags: %" B_PRIu32 "\n", fFont.Flags());
854 }
855 
856