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
31using std::nothrow;
32
33
34DrawState::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
71DrawState::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
117DrawState::~DrawState()
118{
119}
120
121
122DrawState*
123DrawState::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
140DrawState*
141DrawState::PopState()
142{
143	return fPreviousState.Detach();
144}
145
146
147uint16
148DrawState::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
213void
214DrawState::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
280void
281DrawState::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
339void
340DrawState::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
357void
358DrawState::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
379void
380DrawState::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*/
399void
400DrawState::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
412DrawState*
413DrawState::Squash() const
414{
415	DrawState* const squashedState = new(nothrow) DrawState(*this);
416	return squashedState->PushState();
417}
418
419
420void
421DrawState::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
434bool
435DrawState::HasClipping() const
436{
437	if (fClippingRegion.IsSet())
438		return true;
439	if (fPreviousState.IsSet())
440		return fPreviousState->HasClipping();
441	return false;
442}
443
444
445bool
446DrawState::HasAdditionalClipping() const
447{
448	return fClippingRegion.IsSet();
449}
450
451
452bool
453DrawState::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
474bool
475DrawState::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
537void
538DrawState::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
553void
554DrawState::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
562AlphaMask*
563DrawState::GetAlphaMask() const
564{
565	return fAlphaMask.Get();
566}
567
568
569// #pragma mark -
570
571
572void
573DrawState::Transform(SimpleTransform& transform) const
574{
575	transform.AddOffset(fCombinedOrigin.x, fCombinedOrigin.y);
576	transform.SetScale(fCombinedScale);
577}
578
579
580void
581DrawState::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
592void
593DrawState::SetHighColor(rgb_color color)
594{
595	fHighColor = color;
596}
597
598
599void
600DrawState::SetLowColor(rgb_color color)
601{
602	fLowColor = color;
603}
604
605
606void
607DrawState::SetHighUIColor(color_which which, float tint)
608{
609	fWhichHighColor = which;
610	fWhichHighColorTint = tint;
611}
612
613
614color_which
615DrawState::HighUIColor(float* tint) const
616{
617	if (tint != NULL)
618		*tint = fWhichHighColorTint;
619
620	return fWhichHighColor;
621}
622
623
624void
625DrawState::SetLowUIColor(color_which which, float tint)
626{
627	fWhichLowColor = which;
628	fWhichLowColorTint = tint;
629}
630
631
632color_which
633DrawState::LowUIColor(float* tint) const
634{
635	if (tint != NULL)
636		*tint = fWhichLowColorTint;
637
638	return fWhichLowColor;
639}
640
641
642void
643DrawState::SetPattern(const Pattern& pattern)
644{
645	fPattern = pattern;
646}
647
648
649bool
650DrawState::SetDrawingMode(drawing_mode mode)
651{
652	if (!fDrawingModeLocked) {
653		fDrawingMode = mode;
654		return true;
655	}
656	return false;
657}
658
659
660bool
661DrawState::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
672void
673DrawState::SetDrawingModeLocked(bool locked)
674{
675	fDrawingModeLocked = locked;
676}
677
678
679
680void
681DrawState::SetPenLocation(BPoint location)
682{
683	fPenLocation = location;
684}
685
686
687BPoint
688DrawState::PenLocation() const
689{
690	return fPenLocation;
691}
692
693
694void
695DrawState::SetPenSize(float size)
696{
697	fPenSize = size;
698}
699
700
701//! returns the scaled pen size
702float
703DrawState::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
717float
718DrawState::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
729void
730DrawState::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
767void
768DrawState::SetForceFontAliasing(bool aliasing)
769{
770	fFontAliasing = aliasing;
771}
772
773
774void
775DrawState::SetSubPixelPrecise(bool precise)
776{
777	fSubPixelPrecise = precise;
778}
779
780
781void
782DrawState::SetLineCapMode(cap_mode mode)
783{
784	fLineCapMode = mode;
785}
786
787
788void
789DrawState::SetLineJoinMode(join_mode mode)
790{
791	fLineJoinMode = mode;
792}
793
794
795void
796DrawState::SetMiterLimit(float limit)
797{
798	fMiterLimit = limit;
799}
800
801
802void
803DrawState::SetFillRule(int32 fillRule)
804{
805	fFillRule = fillRule;
806}
807
808
809void
810DrawState::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