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