1 /*
2 * GraphicsDriver.cpp
3 * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4 */
5
6 #include <algorithm>
7 #include <cstdio>
8 #include <cstdarg>
9
10 #include <Alert.h>
11 #include <Bitmap.h>
12 #include <Debug.h>
13 #include <Message.h>
14 #include <PrintJob.h>
15 #include <Region.h>
16 #include <TextControl.h>
17 #include <TextControl.h>
18 #include <StopWatch.h>
19 #include <View.h>
20 #include <Directory.h>
21 #include <File.h>
22
23 #include "GraphicsDriver.h"
24 #include "PrintProcess.h"
25 #include "JobData.h"
26 #include "PrinterData.h"
27 #include "PrinterCap.h"
28 #include "Preview.h"
29 #include "Transport.h"
30 #include "ValidRect.h"
31 #include "DbgMsg.h"
32
33
34 using namespace std;
35
36
37 // Measure printJob() time. Either true or false.
38 #define MEASURE_PRINT_JOB_TIME false
39
40
GraphicsDriver(BMessage * message,PrinterData * printerData,const PrinterCap * printerCap)41 GraphicsDriver::GraphicsDriver(BMessage* message, PrinterData* printerData,
42 const PrinterCap* printerCap)
43 :
44 fMessage(message),
45 fView(NULL),
46 fBitmap(NULL),
47 fRotatedBitmap(NULL),
48 fTransport(NULL),
49 fOrgJobData(NULL),
50 fRealJobData(NULL),
51 fPrinterData(printerData),
52 fPrinterCap(printerCap),
53 fSpoolMetaData(NULL),
54 fPageWidth(0),
55 fPageHeight(0),
56 fBandWidth(0),
57 fBandHeight(0),
58 fPixelDepth(0),
59 fBandCount(0),
60 fInternalCopies(0),
61 fPageCount(0),
62 fStatusWindow(NULL)
63 {
64 }
65
66
~GraphicsDriver()67 GraphicsDriver::~GraphicsDriver()
68 {
69 }
70
71
72 static BRect
RotateRect(BRect rect)73 RotateRect(BRect rect)
74 {
75 BRect rotated(rect.top, rect.left, rect.bottom, rect.right);
76 return rotated;
77 }
78
79
80 bool
_SetupData(BFile * spoolFile)81 GraphicsDriver::_SetupData(BFile* spoolFile)
82 {
83 if (fOrgJobData != NULL) {
84 // already initialized
85 return true;
86 }
87
88 print_file_header pfh;
89 spoolFile->Seek(0, SEEK_SET);
90 spoolFile->Read(&pfh, sizeof(pfh));
91
92 DBGMSG(("print_file_header::version = 0x%x\n", pfh.version));
93 DBGMSG(("print_file_header::page_count = %d\n", pfh.page_count));
94 DBGMSG(("print_file_header::first_page = 0x%x\n", (int)pfh.first_page));
95
96 if (pfh.page_count <= 0) {
97 // nothing to print
98 return false;
99 }
100
101 fPageCount = (uint32) pfh.page_count;
102 BMessage *msg = new BMessage();
103 msg->Unflatten(spoolFile);
104 fOrgJobData = new JobData(msg, fPrinterCap, JobData::kJobSettings);
105 DUMP_BMESSAGE(msg);
106 delete msg;
107
108 fRealJobData = new JobData(*fOrgJobData);
109
110 switch (fOrgJobData->GetNup()) {
111 case 2:
112 case 8:
113 case 32:
114 case 128:
115 fRealJobData->SetPrintableRect(
116 RotateRect(fOrgJobData->GetPrintableRect()));
117 fRealJobData->SetScaledPrintableRect(
118 RotateRect(fOrgJobData->GetScaledPrintableRect()));
119 fRealJobData->SetPhysicalRect(
120 RotateRect(fOrgJobData->GetPhysicalRect()));
121 fRealJobData->SetScaledPhysicalRect(
122 RotateRect(fOrgJobData->GetScaledPhysicalRect()));
123
124 if (JobData::kPortrait == fOrgJobData->GetOrientation())
125 fRealJobData->SetOrientation(JobData::kLandscape);
126 else
127 fRealJobData->SetOrientation(JobData::kPortrait);
128 break;
129 }
130
131 if (fOrgJobData->GetCollate() && fPageCount > 1) {
132 fRealJobData->SetCopies(1);
133 fInternalCopies = fOrgJobData->GetCopies();
134 } else {
135 fInternalCopies = 1;
136 }
137
138 fSpoolMetaData = new SpoolMetaData(spoolFile);
139 return true;
140 }
141
142
143 void
_CleanupData()144 GraphicsDriver::_CleanupData()
145 {
146 delete fRealJobData;
147 delete fOrgJobData;
148 delete fSpoolMetaData;
149 fRealJobData = NULL;
150 fOrgJobData = NULL;
151 fSpoolMetaData = NULL;
152 }
153
154
155 void
_SetupBitmap()156 GraphicsDriver::_SetupBitmap()
157 {
158 fPixelDepth = color_space2pixel_depth(fOrgJobData->GetSurfaceType());
159
160 fPageWidth = (fRealJobData->GetPhysicalRect().IntegerWidth()
161 * fOrgJobData->GetXres() + 71) / 72;
162 fPageHeight = (fRealJobData->GetPhysicalRect().IntegerHeight()
163 * fOrgJobData->GetYres() + 71) / 72;
164
165 fBitmap = NULL;
166 fRotatedBitmap = NULL;
167 BRect rect;
168
169 for (fBandCount = 1; fBandCount < 256; fBandCount++) {
170 if (_NeedRotateBitmapBand()) {
171 fBandWidth = (fPageWidth + fBandCount - 1) / fBandCount;
172 fBandHeight = fPageHeight;
173 } else {
174 fBandWidth = fPageWidth;
175 fBandHeight = (fPageHeight + fBandCount - 1) / fBandCount;
176 }
177
178 rect.Set(0, 0, fBandWidth - 1, fBandHeight - 1);
179 fBitmap = new(std::nothrow) BBitmap(rect, fOrgJobData->GetSurfaceType(),
180 true);
181 if (fBitmap == NULL || fBitmap->InitCheck() != B_OK) {
182 delete fBitmap;
183 fBitmap = NULL;
184 // Try with smaller bands
185 continue;
186 }
187
188 if (_NeedRotateBitmapBand()) {
189 BRect rotatedRect(0, 0, rect.bottom, rect.right);
190 delete fRotatedBitmap;
191 fRotatedBitmap = new(std::nothrow) BBitmap(rotatedRect,
192 fOrgJobData->GetSurfaceType(), false);
193 if (fRotatedBitmap == NULL || fRotatedBitmap->InitCheck() != B_OK) {
194 delete fBitmap;
195 fBitmap = NULL;
196 delete fRotatedBitmap;
197 fRotatedBitmap = NULL;
198
199 // Try with smaller bands
200 continue;
201 }
202 }
203
204 // If we get here, all needed allocations have succeeded, we can safely
205 // go ahead.
206 break;
207 };
208
209 if (fBitmap == NULL) {
210 debugger("Failed to allocate bitmaps for print rasterization");
211 return;
212 }
213
214 fView = new BView(rect, "", B_FOLLOW_ALL, B_WILL_DRAW);
215 fBitmap->AddChild(fView);
216
217 DBGMSG(("****************\n"));
218 DBGMSG(("page_width = %d\n", fPageWidth));
219 DBGMSG(("page_height = %d\n", fPageHeight));
220 DBGMSG(("band_count = %d\n", fBandCount));
221 DBGMSG(("band_height = %d\n", fBandHeight));
222 DBGMSG(("****************\n"));
223 }
224
225
226 void
_CleanupBitmap()227 GraphicsDriver::_CleanupBitmap()
228 {
229 delete fBitmap;
230 fBitmap = NULL;
231 fView = NULL;
232
233 delete fRotatedBitmap;
234 fRotatedBitmap = NULL;
235 }
236
237
238 BPoint
GetScale(int32 nup,BRect physicalRect,float scaling)239 GraphicsDriver::GetScale(int32 nup, BRect physicalRect, float scaling)
240 {
241 float width;
242 float height;
243 BPoint scale;
244
245 scale.x = scale.y = 1.0f;
246
247 switch (nup) {
248 case 1:
249 scale.x = scale.y = 1.0f;
250 break;
251 case 2: /* 1x2 or 2x1 */
252 width = physicalRect.Width();
253 height = physicalRect.Height();
254 if (width < height) { // portrait
255 scale.x = height / 2.0f / width;
256 scale.y = width / height;
257 } else { // landscape
258 scale.x = height / width;
259 scale.y = width / 2.0f / height;
260 }
261 break;
262 case 8: /* 2x4 or 4x2 */
263 width = physicalRect.Width();
264 height = physicalRect.Height();
265 if (width < height) {
266 scale.x = height / 4.0f / width;
267 scale.y = width / height / 2.0f;
268 } else {
269 scale.x = height / width / 2.0f;
270 scale.y = width / 4.0f / height;
271 }
272 break;
273 case 32: /* 4x8 or 8x4 */
274 width = physicalRect.Width();
275 height = physicalRect.Height();
276 if (width < height) {
277 scale.x = height / 8.0f / width;
278 scale.y = width / height / 4.0f;
279 } else {
280 scale.x = height / width / 4.0f;
281 scale.y = width / 8.0f / height;
282 }
283 break;
284 case 4: /* 2x2 */
285 scale.x = scale.y = 1.0f / 2.0f;
286 break;
287 case 9: /* 3x3 */
288 scale.x = scale.y = 1.0f / 3.0f;
289 break;
290 case 16: /* 4x4 */
291 scale.x = scale.y = 1.0f / 4.0f;
292 break;
293 case 25: /* 5x5 */
294 scale.x = scale.y = 1.0f / 5.0f;
295 break;
296 case 36: /* 6x6 */
297 scale.x = scale.y = 1.0f / 6.0f;
298 break;
299 case 49: /* 7x7 */
300 scale.x = scale.y = 1.0f / 7.0f;
301 break;
302 case 64: /* 8x8 */
303 scale.x = scale.y = 1.0f / 8.0f;
304 break;
305 case 81: /* 9x9 */
306 scale.x = scale.y = 1.0f / 9.0f;
307 break;
308 case 100: /* 10x10 */
309 scale.x = scale.y = 1.0f / 10.0f;
310 break;
311 case 121: /* 11x11 */
312 scale.x = scale.y = 1.0f / 11.0f;
313 break;
314 }
315
316 scale.x = scale.x * scaling / 100.0;
317 scale.y = scale.y * scaling / 100.0;
318
319 return scale;
320 }
321
322
323 BPoint
GetOffset(int32 nup,int index,JobData::Orientation orientation,const BPoint * scale,BRect scaledPhysicalRect,BRect scaledPrintableRect,BRect physicalRect)324 GraphicsDriver::GetOffset(int32 nup, int index,
325 JobData::Orientation orientation, const BPoint* scale,
326 BRect scaledPhysicalRect, BRect scaledPrintableRect,
327 BRect physicalRect)
328 {
329 BPoint offset;
330 offset.x = 0;
331 offset.y = 0;
332
333 float width = scaledPhysicalRect.Width();
334 float height = scaledPhysicalRect.Height();
335
336 switch (nup) {
337 case 1:
338 break;
339 case 2:
340 if (index == 1) {
341 if (JobData::kPortrait == orientation) {
342 offset.x = width;
343 } else {
344 offset.y = height;
345 }
346 }
347 break;
348 case 8:
349 if (JobData::kPortrait == orientation) {
350 offset.x = width * (index / 2);
351 offset.y = height * (index % 2);
352 } else {
353 offset.x = width * (index % 2);
354 offset.y = height * (index / 2);
355 }
356 break;
357 case 32:
358 if (JobData::kPortrait == orientation) {
359 offset.x = width * (index / 4);
360 offset.y = height * (index % 4);
361 } else {
362 offset.x = width * (index % 4);
363 offset.y = height * (index / 4);
364 }
365 break;
366 case 4:
367 offset.x = width * (index / 2);
368 offset.y = height * (index % 2);
369 break;
370 case 9:
371 offset.x = width * (index / 3);
372 offset.y = height * (index % 3);
373 break;
374 case 16:
375 offset.x = width * (index / 4);
376 offset.y = height * (index % 4);
377 break;
378 case 25:
379 offset.x = width * (index / 5);
380 offset.y = height * (index % 5);
381 break;
382 case 36:
383 offset.x = width * (index / 6);
384 offset.y = height * (index % 6);
385 break;
386 case 49:
387 offset.x = width * (index / 7);
388 offset.y = height * (index % 7);
389 break;
390 case 64:
391 offset.x = width * (index / 8);
392 offset.y = height * (index % 8);
393 break;
394 case 81:
395 offset.x = width * (index / 9);
396 offset.y = height * (index % 9);
397 break;
398 case 100:
399 offset.x = width * (index / 10);
400 offset.y = height * (index % 10);
401 break;
402 case 121:
403 offset.x = width * (index / 11);
404 offset.y = height * (index % 11);
405 break;
406 }
407
408 // adjust margin
409 offset.x += scaledPrintableRect.left - physicalRect.left;
410 offset.y += scaledPrintableRect.top - physicalRect.top;
411
412 float real_scale = min(scale->x, scale->y);
413 if (real_scale != scale->x)
414 offset.x *= scale->x / real_scale;
415 else
416 offset.y *= scale->y / real_scale;
417
418 return offset;
419 }
420
421
422 // print the specified pages on a physical page
423 bool
_PrintPage(PageDataList * pages)424 GraphicsDriver::_PrintPage(PageDataList* pages)
425 {
426 BPoint offset;
427 offset.x = 0.0f;
428 offset.y = 0.0f;
429
430 if (pages == NULL) {
431 return true;
432 }
433
434 do {
435 // clear the physical page
436 fView->SetScale(1.0);
437 fView->SetHighColor(255, 255, 255);
438 fView->ConstrainClippingRegion(NULL);
439 fView->FillRect(fView->Bounds());
440
441 BPoint scale = GetScale(fOrgJobData->GetNup(),
442 fOrgJobData->GetPhysicalRect(), fOrgJobData->GetScaling());
443 float real_scale = min(scale.x, scale.y) * fOrgJobData->GetXres()
444 / 72.0f;
445 fView->SetScale(real_scale);
446 float x = offset.x / real_scale;
447 float y = offset.y / real_scale;
448 int page_index = 0;
449
450 for (PageDataList::iterator it = pages->begin(); it != pages->end();
451 it++) {
452 BPoint left_top(GetOffset(fOrgJobData->GetNup(), page_index++,
453 fOrgJobData->GetOrientation(), &scale,
454 fOrgJobData->GetScaledPhysicalRect(),
455 fOrgJobData->GetScaledPrintableRect(),
456 fOrgJobData->GetPhysicalRect()));
457
458 left_top.x -= x;
459 left_top.y -= y;
460
461 BRect clip(fOrgJobData->GetScaledPrintableRect());
462 clip.OffsetTo(left_top);
463
464 BRegion *region = new BRegion();
465 region->Set(clip);
466 fView->ConstrainClippingRegion(region);
467 delete region;
468
469 if ((*it)->startEnum()) {
470 bool more;
471 do {
472 PictureData *picture_data;
473 more = (*it)->enumObject(&picture_data);
474 BPoint real_offset = left_top + picture_data->point;
475 fView->DrawPicture(picture_data->picture, real_offset);
476 fView->Sync();
477 delete picture_data;
478 } while (more);
479 }
480 }
481
482 if (!_PrintBand(fBitmap, &offset))
483 return false;
484
485 } while (offset.x >= 0.0f && offset.y >= 0.0f);
486
487 return true;
488 }
489
490
491 bool
_PrintBand(BBitmap * band,BPoint * offset)492 GraphicsDriver::_PrintBand(BBitmap* band, BPoint* offset)
493 {
494 if (!_NeedRotateBitmapBand())
495 return NextBand(band, offset);
496
497 _RotateInto(fRotatedBitmap, band);
498
499 BPoint rotatedOffset(offset->y, offset->x);
500 bool success = NextBand(fRotatedBitmap, &rotatedOffset);
501 offset->x = rotatedOffset.y;
502 offset->y = rotatedOffset.x;
503
504 return success;
505 }
506
507
508 void
_RotateInto(BBitmap * target,const BBitmap * source)509 GraphicsDriver::_RotateInto(BBitmap* target, const BBitmap* source)
510 {
511 ASSERT(target->ColorSpace() == B_RGB32);
512 ASSERT(source->ColorSpace() == B_RGB32);
513 ASSERT(target->Bounds().IntegerWidth() == source->Bounds().IntegerHeight());
514 ASSERT(target->Bounds().IntegerHeight() == source->Bounds().IntegerWidth());
515
516 const int32 width = source->Bounds().IntegerWidth() + 1;
517 const int32 height = source->Bounds().IntegerHeight() + 1;
518
519 const int32 sourceBPR = source->BytesPerRow();
520 const int32 targetBPR = target->BytesPerRow();
521
522 const uint8_t* sourceBits =
523 reinterpret_cast<const uint8_t*>(source->Bits());
524 uint8_t* targetBits = static_cast<uint8_t*>(target->Bits());
525
526 for (int32 y = 0; y < height; y ++) {
527 for (int32 x = 0; x < width; x ++) {
528 const uint32_t* sourcePixel =
529 reinterpret_cast<const uint32_t*>(sourceBits + sourceBPR * y
530 + sizeof(uint32_t) * x);
531
532 int32 targetX = (height - y - 1);
533 int32 targetY = x;
534 uint32_t* targetPixel =
535 reinterpret_cast<uint32_t*>(targetBits + targetBPR * targetY
536 + sizeof(uint32_t) * targetX);
537 *targetPixel = *sourcePixel;
538 }
539 }
540 }
541
542 bool
_CollectPages(SpoolData * spoolData,PageDataList * pages)543 GraphicsDriver::_CollectPages(SpoolData* spoolData, PageDataList* pages)
544 {
545 // collect the pages to be printed on the physical page
546 PageData *page_data;
547 int nup = fOrgJobData->GetNup();
548 bool more;
549 do {
550 more = spoolData->enumObject(&page_data);
551 if (pages != NULL)
552 pages->push_back(page_data);
553 } while (more && --nup);
554
555 return more;
556 }
557
558
559 bool
_SkipPages(SpoolData * spoolData)560 GraphicsDriver::_SkipPages(SpoolData* spoolData)
561 {
562 return _CollectPages(spoolData, NULL);
563 }
564
565
566 bool
_PrintDocument(SpoolData * spoolData)567 GraphicsDriver::_PrintDocument(SpoolData* spoolData)
568 {
569 bool more;
570 bool success;
571 int page_index;
572 int copy;
573 int copies;
574
575 more = true;
576 success = true;
577 page_index = 0;
578
579 if (fPrinterCap->Supports(PrinterCap::kCopyCommand))
580 // let the printer perform the copy operation
581 copies = 1;
582 else
583 // send the page multiple times to the printer
584 copies = fRealJobData->GetCopies();
585
586 fStatusWindow -> SetPageCopies(copies);
587 // inform fStatusWindow about number of copies
588
589 // printing of even/odd numbered pages only is valid in simplex mode
590 bool simplex = fRealJobData->GetPrintStyle() == JobData::kSimplex;
591
592 if (spoolData->startEnum()) {
593 do {
594 DBGMSG(("page index = %d\n", page_index));
595
596 if (simplex
597 && fRealJobData->GetPageSelection()
598 == JobData::kEvenNumberedPages)
599 // skip odd numbered page
600 more = _SkipPages(spoolData);
601
602 if (!more)
603 // end reached
604 break;
605
606 PageDataList pages;
607 more = _CollectPages(spoolData, &pages);
608
609 if (more && simplex
610 && fRealJobData->GetPageSelection()
611 == JobData::kOddNumberedPages)
612 // skip even numbered page
613 more = _SkipPages(spoolData);
614
615 // print each physical page "copies" of times
616 for (copy = 0; success && copy < copies; copy ++) {
617
618 // Update the status / cancel job
619 if (fStatusWindow->UpdateStatusBar(page_index, copy))
620 return false;
621
622 success = StartPage(page_index);
623 if (!success)
624 break;
625
626 // print the pages on the physical page
627 fView->Window()->Lock();
628 success = _PrintPage(&pages);
629 fView->Window()->Unlock();
630
631 if (success) {
632 success = EndPage(page_index);
633 }
634 }
635
636 page_index++;
637 } while (success && more);
638 }
639
640 #ifndef USE_PREVIEW_FOR_DEBUG
641 if (success
642 && fPrinterCap->Supports(PrinterCap::kPrintStyle)
643 && (fOrgJobData->GetPrintStyle() != JobData::kSimplex)
644 && (((page_index + fOrgJobData->GetNup() - 1) / fOrgJobData->GetNup())
645 % 2)) {
646 // append an empty page on the back side of the page in duplex or
647 // booklet mode
648 success =
649 StartPage(page_index) &&
650 _PrintPage(NULL) &&
651 EndPage(page_index);
652 }
653 #endif
654
655 return success;
656 }
657
658
659 const JobData*
GetJobData(BFile * spoolFile)660 GraphicsDriver::GetJobData(BFile* spoolFile)
661 {
662 _SetupData(spoolFile);
663 return fOrgJobData;
664 }
665
666
667 bool
_PrintJob(BFile * spoolFile)668 GraphicsDriver::_PrintJob(BFile* spoolFile)
669 {
670 bool success = true;
671 if (!_SetupData(spoolFile)) {
672 // silently exit if there is nothing to print
673 return true;
674 }
675
676 fTransport = new Transport(fPrinterData);
677
678 if (fTransport->CheckAbort()) {
679 success = false;
680 } else if (!fTransport->IsPrintToFileCanceled()) {
681 BStopWatch stopWatch("printJob", !MEASURE_PRINT_JOB_TIME);
682 _SetupBitmap();
683 SpoolData spoolData(spoolFile, fPageCount, fOrgJobData->GetNup(),
684 fOrgJobData->GetReverse());
685 success = StartDocument();
686 if (success) {
687 fStatusWindow = new StatusWindow(
688 fRealJobData->GetPageSelection() == JobData::kOddNumberedPages,
689 fRealJobData->GetPageSelection() == JobData::kEvenNumberedPages,
690 fRealJobData->GetFirstPage(),
691 fPageCount,
692 fInternalCopies,fRealJobData->GetNup());
693
694 while (fInternalCopies--) {
695 success = _PrintDocument(&spoolData);
696 if (success == false) {
697 break;
698 }
699 }
700 EndDocument(success);
701
702 fStatusWindow->Lock();
703 fStatusWindow->Quit();
704 }
705 _CleanupBitmap();
706 _CleanupData();
707 }
708
709 if (success == false) {
710 BAlert *alert;
711 if (fTransport->CheckAbort())
712 alert = new BAlert("", fTransport->LastError().c_str(), "OK");
713 else
714 alert = new BAlert("", "Printer not responding.", "OK");
715 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
716 alert->Go();
717 }
718
719 delete fTransport;
720 fTransport = NULL;
721
722 return success;
723 }
724
725
726 BMessage*
TakeJob(BFile * spoolFile)727 GraphicsDriver::TakeJob(BFile* spoolFile)
728 {
729 BMessage *msg;
730 if (_PrintJob(spoolFile))
731 msg = new BMessage('okok');
732 else
733 msg = new BMessage('baad');
734 return msg;
735 }
736
737
738 bool
StartDocument()739 GraphicsDriver::StartDocument()
740 {
741 return true;
742 }
743
744
745 bool
StartPage(int)746 GraphicsDriver::StartPage(int)
747 {
748 return true;
749 }
750
751
752 bool
NextBand(BBitmap *,BPoint *)753 GraphicsDriver::NextBand(BBitmap*, BPoint*)
754 {
755 return true;
756 }
757
758
759 bool
EndPage(int)760 GraphicsDriver::EndPage(int)
761 {
762 return true;
763 }
764
765
766 bool
EndDocument(bool)767 GraphicsDriver::EndDocument(bool)
768 {
769 return true;
770 }
771
772
773 void
WriteSpoolData(const void * buffer,size_t size)774 GraphicsDriver::WriteSpoolData(const void* buffer, size_t size)
775 {
776 if (fTransport == NULL)
777 return;
778 fTransport->Write(buffer, size);
779 }
780
781
782 void
WriteSpoolString(const char * format,...)783 GraphicsDriver::WriteSpoolString(const char* format, ...)
784 {
785 if (fTransport == NULL)
786 return;
787
788 char buffer[256];
789 va_list ap;
790 va_start(ap, format);
791 vsprintf(buffer, format, ap);
792 fTransport->Write(buffer, strlen(buffer));
793 va_end(ap);
794 }
795
796
797 void
WriteSpoolChar(char c)798 GraphicsDriver::WriteSpoolChar(char c)
799 {
800 if (fTransport == NULL)
801 return;
802
803 fTransport->Write(&c, 1);
804 }
805
806
807 void
ReadSpoolData(void * buffer,size_t size)808 GraphicsDriver::ReadSpoolData(void* buffer, size_t size)
809 {
810 if (fTransport == NULL)
811 return;
812 fTransport->Read(buffer, size);
813 }
814
815
816 int
ReadSpoolChar()817 GraphicsDriver::ReadSpoolChar()
818 {
819 if (fTransport == NULL)
820 return -1;
821
822 char c;
823 fTransport->Read(&c, 1);
824 return c;
825 }
826
827
828 bool
_NeedRotateBitmapBand() const829 GraphicsDriver::_NeedRotateBitmapBand() const
830 {
831 return JobData::kLandscape == fRealJobData->GetOrientation()
832 && !fPrinterCap->Supports(PrinterCap::kCanRotatePageInLandscape);
833 }
834
835
836 void
_ConvertRGB32ToRGB24(const void * src,void * dst,int width)837 GraphicsDriver::_ConvertRGB32ToRGB24(const void* src, void* dst, int width) {
838 uint8* d = (uint8*)dst;
839 const rgb_color* s = static_cast<const rgb_color*>(src);
840 for (int i = width; i > 0; i --) {
841 *d ++ = s->red;
842 *d ++ = s->green;
843 *d ++ = s->blue;
844 s++;
845 }
846 }
847
848
849 void
_ConvertCMAP8ToRGB24(const void * src,void * dst,int width)850 GraphicsDriver::_ConvertCMAP8ToRGB24(const void* src, void* dst, int width) {
851 uint8* d = (uint8*)dst;
852 const uint8* s = static_cast<const uint8*>(src);
853 const color_map* cmap = system_colors();
854 for (int i = width; i > 0; i --) {
855 const rgb_color* rgb = &cmap->color_list[*s];
856 *d ++ = rgb->red;
857 *d ++ = rgb->green;
858 *d ++ = rgb->blue;
859 s ++;
860 }
861 }
862
863
864 void
ConvertToRGB24(const void * src,void * dst,int width,color_space cs)865 GraphicsDriver::ConvertToRGB24(const void* src, void* dst, int width,
866 color_space cs) {
867 if (cs == B_RGB32)
868 _ConvertRGB32ToRGB24(src, dst, width);
869 else if (cs == B_CMAP8)
870 _ConvertCMAP8ToRGB24(src, dst, width);
871 else {
872 DBGMSG(("color_space %d not supported", cs));
873 }
874 }
875
876
877 uint8
_ConvertToGray(uint8 r,uint8 g,uint8 b)878 GraphicsDriver::_ConvertToGray(uint8 r, uint8 g, uint8 b) {
879 if (r == g && g == b)
880 return r;
881 else
882 return (r * 3 + g * 6 + b) / 10;
883 }
884
885
886 void
_ConvertRGB32ToGray(const void * src,void * dst,int width)887 GraphicsDriver::_ConvertRGB32ToGray(const void* src, void* dst, int width) {
888 uint8* d = (uint8*)dst;
889 const rgb_color* s = static_cast<const rgb_color*>(src);
890 for (int i = width; i > 0; i--, s++, d++)
891 *d = _ConvertToGray(s->red, s->green, s->blue);
892 }
893
894
895 void
_ConvertCMAP8ToGray(const void * src,void * dst,int width)896 GraphicsDriver::_ConvertCMAP8ToGray(const void* src, void* dst, int width) {
897 uint8* d = (uint8*)dst;
898 const uint8* s = static_cast<const uint8*>(src);
899 const color_map* cmap = system_colors();
900 for (int i = width; i > 0; i--, s++, d++) {
901 const rgb_color* rgb = &cmap->color_list[*s];
902 *d = _ConvertToGray(rgb->red, rgb->green, rgb->blue);
903 }
904 }
905
906
907 void
ConvertToGray(const void * src,void * dst,int width,color_space cs)908 GraphicsDriver::ConvertToGray(const void* src, void* dst, int width,
909 color_space cs) {
910 if (cs == B_RGB32)
911 _ConvertRGB32ToGray(src, dst, width);
912 else if (cs == B_CMAP8)
913 _ConvertCMAP8ToGray(src, dst, width);
914 else {
915 DBGMSG(("color_space %d not supported", cs));
916 }
917 }
918
919