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