2 * Copyright 2002-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Updated by Sikosis (beos@gravity24hr.com)
7 * Copyright 1999, Be Incorporated. All Rights Reserved.
8 * This file may be used under the terms of the Be Sample Code License.
15 #include <BitmapStream.h>
17 #include <Clipboard.h>
19 #include <Directory.h>
21 #include <FindDirectory.h>
24 #include <MenuField.h>
25 #include <MessageFormat.h>
28 #include <PopUpMenu.h>
29 #include <PropertyInfo.h>
31 #include <ScrollView.h>
33 #include <TranslationUtils.h>
34 #include <TranslatorRoster.h>
35 #include <WindowScreen.h>
45 #undef B_TRANSLATION_CONTEXT
46 #define B_TRANSLATION_CONTEXT "Magnify-Main"
49 const int32 msg_update_info
= 'info';
50 const int32 msg_show_info
= 'show';
51 const int32 msg_toggle_grid
= 'grid';
52 const int32 msg_shrink
= 'shnk';
53 const int32 msg_grow
= 'grow';
54 const int32 msg_make_square
= 'sqar';
55 const int32 msg_shrink_pixel
= 'pshk';
56 const int32 msg_grow_pixel
= 'pgrw';
58 const int32 msg_new_color
= 'colr';
59 const int32 msg_toggle_ruler
= 'rulr';
60 const int32 msg_copy_image
= 'copy';
61 const int32 msg_track_color
= 'trak';
62 const int32 msg_freeze
= 'frez';
63 const int32 msg_stick
= 'stic';
64 const int32 msg_dump
= 'dump';
65 const int32 msg_add_cross_hair
= 'acrs';
66 const int32 msg_remove_cross_hair
= 'rcrs';
67 const int32 msg_save
= 'save';
69 const rgb_color kViewGray
= { 216, 216, 216, 255};
70 const rgb_color kGridGray
= {130, 130, 130, 255 };
71 const rgb_color kWhite
= { 255, 255, 255, 255};
72 const rgb_color kBlack
= { 0, 0, 0, 255};
73 const rgb_color kDarkGray
= { 96, 96, 96, 255};
74 const rgb_color kRedColor
= { 255, 10, 50, 255 };
75 const rgb_color kGreenColor
= { 10, 255, 50, 255 };
76 const rgb_color kBlueColor
= { 10, 50, 255, 255 };
78 const char* const kBitmapMimeType
= "image/x-vnd.Be-bitmap";
80 const float kCurrentVersion
= 1.2;
81 const char *kPrefsFileName
= "Magnify_prefs";
87 // show info (rgb, location)
90 const char* const kAppName
= "Magnify";
91 const bool kDefaultShowGrid
= true;
92 const bool kDefaultShowInfo
= true;
93 const int32 kDefaultPixelCount
= 32;
94 const int32 kDefaultPixelSize
= 8;
96 // each info region will be:
97 // top-bottom: 5 fontheight 5 fontheight 5
98 // left-right: 10 minwindowwidth 10
99 const int32 kBorderSize
= 10;
102 static property_info sProperties
[] = {
103 { "Info", { B_GET_PROPERTY
, B_SET_PROPERTY
, 0 },
104 { B_DIRECT_SPECIFIER
, 0 },
105 "Show/hide info.", 0,
108 { "Grid", { B_GET_PROPERTY
, B_SET_PROPERTY
, 0 },
109 { B_DIRECT_SPECIFIER
, 0 },
110 "Show/hide grid.", 0,
113 { "MakeSquare", { B_EXECUTE_PROPERTY
, 0 },
114 { B_DIRECT_SPECIFIER
, 0 },
115 "Make the view square.", 0,
117 { "Zoom", { B_GET_PROPERTY
, B_SET_PROPERTY
, 0 },
118 { B_DIRECT_SPECIFIER
, 0 },
119 "Gets/sets the zoom factor (1-16).", 0,
122 { "Stick", { B_GET_PROPERTY
, B_SET_PROPERTY
, 0 },
123 { B_DIRECT_SPECIFIER
, 0 },
124 "Stick/unstick coordinates.", 0,
127 { "CopyImage", { B_EXECUTE_PROPERTY
, 0 },
128 { B_DIRECT_SPECIFIER
, 0 },
129 "Copy image to clipboard.", 0,
137 FontHeight(BView
* target
, bool full
)
140 target
->GetFontHeight(&finfo
);
141 float h
= ceil(finfo
.ascent
) + ceil(finfo
.descent
);
144 h
+= ceil(finfo
.leading
);
151 BoundsSelection(int32 incX
, int32 incY
, float* x
, float* y
,
152 int32 xCount
, int32 yCount
)
170 BuildInfoMenu(BMenu
*menu
)
173 menuItem
= new BMenuItem(B_TRANSLATE("Save image"),
174 new BMessage(msg_save
), 'S');
175 menu
->AddItem(menuItem
);
176 // menuItem = new BMenuItem(B_TRANSLATE("Save selection"),
177 // new BMessage(msg_save), 'S');
178 // menu->AddItem(menuItem);
179 menuItem
= new BMenuItem(B_TRANSLATE("Copy image"),
180 new BMessage(msg_copy_image
), 'C');
181 menu
->AddItem(menuItem
);
182 menu
->AddSeparatorItem();
184 menuItem
= new BMenuItem(B_TRANSLATE("Show info"),
185 new BMessage(msg_show_info
), 'T');
186 menu
->AddItem(menuItem
);
187 menuItem
= new BMenuItem(B_TRANSLATE("Add a crosshair"),
188 new BMessage(msg_add_cross_hair
), 'H');
189 menu
->AddItem(menuItem
);
190 menuItem
= new BMenuItem(B_TRANSLATE("Remove a crosshair"),
191 new BMessage(msg_remove_cross_hair
), 'H', B_SHIFT_KEY
);
192 menu
->AddItem(menuItem
);
193 menuItem
= new BMenuItem(B_TRANSLATE("Show grid"),
194 new BMessage(msg_toggle_grid
), 'G');
195 menu
->AddItem(menuItem
);
196 menu
->AddSeparatorItem();
198 menuItem
= new BMenuItem(B_TRANSLATE("Freeze image"),
199 new BMessage(msg_freeze
), 'F');
200 menu
->AddItem(menuItem
);
201 menuItem
= new BMenuItem(B_TRANSLATE("Stick coordinates"),
202 new BMessage(msg_stick
), 'I');
203 menu
->AddItem(menuItem
);
204 menu
->AddSeparatorItem();
206 menuItem
= new BMenuItem(B_TRANSLATE("Make square"),
207 new BMessage(msg_make_square
), '/');
208 menu
->AddItem(menuItem
);
209 menuItem
= new BMenuItem(B_TRANSLATE("Decrease window size"),
210 new BMessage(msg_shrink
), '-');
211 menu
->AddItem(menuItem
);
212 menuItem
= new BMenuItem(B_TRANSLATE("Increase window size"),
213 new BMessage(msg_grow
), '+');
214 menu
->AddItem(menuItem
);
215 menuItem
= new BMenuItem(B_TRANSLATE("Decrease pixel size"),
216 new BMessage(msg_shrink_pixel
), ',');
217 menu
->AddItem(menuItem
);
218 menuItem
= new BMenuItem(B_TRANSLATE("Increase pixel size"),
219 new BMessage(msg_grow_pixel
), '.');
220 menu
->AddItem(menuItem
);
224 UpdateInfoMenu(BMenu
*menu
, TWindow
*window
)
227 bool showGrid
= true;
228 bool infoBarIsVisible
= true;
229 bool stickCordinates
= true;
231 state
= window
->IsActive();
232 showGrid
= window
->ShowGrid();
233 infoBarIsVisible
= window
->InfoBarIsVisible();
234 stickCordinates
= window
->IsSticked();
236 BMenuItem
* menuItem
= menu
->FindItem(B_TRANSLATE("Show info"));
238 menuItem
->SetEnabled(state
);
239 menuItem
->SetMarked(infoBarIsVisible
);
241 menuItem
= menu
->FindItem(B_TRANSLATE("Add a crosshair"));
243 menuItem
->SetEnabled(state
);
244 menuItem
= menu
->FindItem(B_TRANSLATE("Remove a crosshair"));
246 menuItem
->SetEnabled(state
);
247 menuItem
= menu
->FindItem(B_TRANSLATE("Show grid"));
249 menuItem
->SetEnabled(state
);
250 menuItem
->SetMarked(showGrid
);
252 menuItem
= menu
->FindItem(B_TRANSLATE("Freeze image"));
254 menuItem
->SetMarked(!state
);
256 menuItem
= menu
->FindItem(B_TRANSLATE("Stick coordinates"));
258 menuItem
->SetMarked(stickCordinates
);
260 menuItem
= menu
->FindItem(B_TRANSLATE("Make square"));
262 menuItem
->SetEnabled(state
);
263 menuItem
= menu
->FindItem(B_TRANSLATE("Decrease window size"));
265 menuItem
->SetEnabled(state
);
266 menuItem
= menu
->FindItem(B_TRANSLATE("Increase window size"));
268 menuItem
->SetEnabled(state
);
269 menuItem
= menu
->FindItem(B_TRANSLATE("Decrease pixel size"));
271 menuItem
->SetEnabled(state
);
272 menuItem
= menu
->FindItem(B_TRANSLATE("Increase pixel size"));
274 menuItem
->SetEnabled(state
);
280 // pass in pixelCount to maintain backward compatibility of setting
281 // the pixelcount from the command line
282 TApp::TApp(int32 pixelCount
)
283 : BApplication("application/x-vnd.Haiku-Magnify")
285 TWindow
* magWindow
= new TWindow(pixelCount
);
293 TWindow::TWindow(int32 pixelCount
)
295 BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Magnify"),
296 B_TITLED_WINDOW
, B_OUTLINE_RESIZE
)
298 GetPrefs(pixelCount
);
301 BRect
infoRect(Bounds());
302 infoRect
.InsetBy(-1, -1);
303 fInfo
= new TInfoView(infoRect
);
306 fFontHeight
= FontHeight(fInfo
, true);
307 fInfoHeight
= (fFontHeight
* 2) + (3 * 5);
309 BRect
fbRect(0, 0, (fHPixelCount
*fPixelSize
), (fHPixelCount
*fPixelSize
));
311 fbRect
.OffsetBy(10, fInfoHeight
);
312 fFatBits
= new TMagnify(fbRect
, this);
313 fInfo
->AddChild(fFatBits
);
315 fFatBits
->SetSelection(fShowInfo
);
316 fInfo
->SetMagView(fFatBits
);
318 ResizeWindow(fHPixelCount
, fVPixelCount
);
319 UpdateInfoBarOnResize();
321 AddShortcut('S', B_COMMAND_KEY
, new BMessage(msg_save
));
322 AddShortcut('C', B_COMMAND_KEY
, new BMessage(msg_copy_image
));
323 AddShortcut('T', B_COMMAND_KEY
, new BMessage(msg_show_info
));
324 AddShortcut('H', B_COMMAND_KEY
, new BMessage(msg_add_cross_hair
));
325 AddShortcut('H', B_SHIFT_KEY
, new BMessage(msg_remove_cross_hair
));
326 AddShortcut('G', B_COMMAND_KEY
, new BMessage(msg_toggle_grid
));
327 AddShortcut('F', B_COMMAND_KEY
, new BMessage(msg_freeze
));
328 AddShortcut('I', B_COMMAND_KEY
, new BMessage(msg_stick
));
329 AddShortcut('-', B_COMMAND_KEY
, new BMessage(msg_shrink
));
330 AddShortcut('=', B_COMMAND_KEY
, new BMessage(msg_grow
));
331 AddShortcut('/', B_COMMAND_KEY
, new BMessage(msg_make_square
));
332 AddShortcut(',', B_COMMAND_KEY
, new BMessage(msg_shrink_pixel
));
333 AddShortcut('.', B_COMMAND_KEY
, new BMessage(msg_grow_pixel
));
343 TWindow::GetSupportedSuites(BMessage
* msg
)
345 msg
->AddString("suites", "suite/x-vnd.Haiku-Magnify");
347 BPropertyInfo
propertyInfo(sProperties
);
348 msg
->AddFlat("messages", &propertyInfo
);
350 return BHandler::GetSupportedSuites(msg
);
355 TWindow::ResolveSpecifier(BMessage
* msg
, int32 index
, BMessage
* specifier
,
356 int32 what
, const char* property
)
358 BPropertyInfo
propertyInfo(sProperties
);
359 if (propertyInfo
.FindMatch(msg
, index
, specifier
, what
, property
) >= 0)
362 return BHandler::ResolveSpecifier(msg
, index
, specifier
, what
, property
);
367 TWindow::MessageReceived(BMessage
* m
)
369 bool active
= fFatBits
->Active();
372 case B_EXECUTE_PROPERTY
:
379 const char* property
;
380 if (m
->GetCurrentSpecifier(&index
, &specifier
, &what
, &property
)
382 return BWindow::MessageReceived(m
);
384 status_t result
= B_OK
;
385 BMessage
reply(B_REPLY
);
387 BPropertyInfo
propertyInfo(sProperties
);
388 switch (propertyInfo
.FindMatch(m
, index
, &specifier
, what
,
391 if (m
->what
== B_GET_PROPERTY
)
392 result
= reply
.AddBool("result", fInfoBarState
);
393 else if (m
->what
== B_SET_PROPERTY
) {
395 result
= m
->FindBool("data", &showInfo
);
396 if (result
== B_OK
) {
397 fInfoBarState
= showInfo
;
398 ShowInfo(fInfoBarState
);
404 if (m
->what
== B_GET_PROPERTY
)
405 result
= reply
.AddBool("result", fShowGrid
);
406 else if (m
->what
== B_SET_PROPERTY
) {
408 result
= m
->FindBool("data", &showGrid
);
415 if (fHPixelCount
!= fVPixelCount
) {
416 int32 big
= fHPixelCount
> fVPixelCount
? fHPixelCount
418 ResizeWindow(big
, big
);
423 if (m
->what
== B_GET_PROPERTY
)
424 result
= reply
.AddInt32("result", fPixelSize
);
425 else if (m
->what
== B_SET_PROPERTY
) {
427 result
= m
->FindInt32("data", &zoom
);
434 if (m
->what
== B_GET_PROPERTY
)
435 result
= reply
.AddBool("result", fFatBits
->Sticked());
436 else if (m
->what
== B_SET_PROPERTY
) {
438 result
= m
->FindBool("data", &stick
);
440 fFatBits
->MakeSticked(stick
);
445 fFatBits
->CopyImage();
449 return BWindow::MessageReceived(m
);
452 if (result
!= B_OK
) {
453 reply
.what
= B_MESSAGE_NOT_UNDERSTOOD
;
454 reply
.AddString("message", strerror(result
));
455 reply
.AddInt32("error", result
);
458 m
->SendReply(&reply
);
464 fInfoBarState
= !fInfoBarState
;
465 ShowInfo(!fShowInfo
);
469 case msg_toggle_grid
:
482 case msg_make_square
:
484 if (fHPixelCount
== fVPixelCount
)
486 int32 big
= (fHPixelCount
> fVPixelCount
) ? fHPixelCount
: fVPixelCount
;
487 ResizeWindow(big
, big
);
491 case msg_shrink_pixel
:
500 case msg_add_cross_hair
:
501 if (active
&& fShowInfo
)
504 case msg_remove_cross_hair
:
505 if (active
&& fShowInfo
)
511 SetFlags(B_OUTLINE_RESIZE
| B_NOT_ZOOMABLE
| B_NOT_RESIZABLE
);
513 SetFlags(B_OUTLINE_RESIZE
| B_NOT_ZOOMABLE
);
515 fFatBits
->MakeActive(!fFatBits
->Active());
519 fFatBits
->MakeSticked(!fFatBits
->Sticked());
523 // freeze the image here, unfreeze after dump or cancel
524 fFatBits
->StartSave();
526 BMessenger
messenger(this);
527 BMessage
message(msg_dump
);
528 fSavePanel
= new BFilePanel(B_SAVE_PANEL
, &messenger
, 0, 0, false,
530 fSavePanel
->SetSaveText("Bitmaps.png");
539 m
->FindRef("directory", &dirRef
);
540 m
->FindString((const char*)"name",(const char**) &name
);
542 fFatBits
->SaveImage(&dirRef
, name
);
546 // image is frozen before the FilePanel is shown
551 fFatBits
->CopyImage();
554 BWindow::MessageReceived(m
);
561 TWindow::QuitRequested()
564 be_app
->PostMessage(B_QUIT_REQUESTED
);
570 TWindow::GetPrefs(int32 overridePixelCount
)
577 bool showGrid
= kDefaultShowGrid
;
578 bool showInfo
= kDefaultShowInfo
;
579 bool ch1Showing
=false;
580 bool ch2Showing
=false;
581 int32 hPixelCount
= kDefaultPixelCount
;
582 int32 vPixelCount
= kDefaultPixelCount
;
583 int32 pixelSize
= kDefaultPixelSize
;
585 if (find_directory (B_USER_SETTINGS_DIRECTORY
, &path
) == B_OK
) {
587 path
.Append(kPrefsFileName
);
588 if ((ref
= open(path
.Path(), 0)) >= 0) {
589 if (read(ref
, name
, 7) != 7)
593 if (strcmp(name
, kAppName
) != 0)
596 read(ref
, &version
, sizeof(float));
598 if (read(ref
, &loc
, sizeof(BPoint
)) != sizeof(BPoint
))
603 if (read(ref
, &showGrid
, sizeof(bool)) != sizeof(bool)) {
604 showGrid
= kDefaultShowGrid
;
608 if (read(ref
, &showInfo
, sizeof(bool)) != sizeof(bool)) {
609 showInfo
= kDefaultShowInfo
;
613 if (read(ref
, &ch1Showing
, sizeof(bool)) != sizeof(bool)) {
618 if (read(ref
, &ch2Showing
, sizeof(bool)) != sizeof(bool)) {
623 if (read(ref
, &hPixelCount
, sizeof(int32
)) != sizeof(int32
)) {
624 hPixelCount
= kDefaultPixelCount
;
627 if (read(ref
, &vPixelCount
, sizeof(int32
)) != sizeof(int32
)) {
628 vPixelCount
= kDefaultPixelCount
;
632 if (read(ref
, &pixelSize
, sizeof(int32
)) != sizeof(int32
)) {
633 pixelSize
= kDefaultPixelSize
;
637 ALMOST_DONE
: // clean up and try to position the window
640 if (haveLoc
&& BScreen(B_MAIN_SCREEN_ID
).Frame().Contains(loc
)) {
647 // if prefs dont yet exist or the window is not onscreen, center the window
650 // set all the settings to defaults if we get here
652 fShowGrid
= showGrid
;
653 fShowInfo
= showInfo
;
654 fInfoBarState
= showInfo
;
655 fHPixelCount
= (overridePixelCount
== -1) ? hPixelCount
: overridePixelCount
;
656 fVPixelCount
= (overridePixelCount
== -1) ? vPixelCount
: overridePixelCount
;
657 fPixelSize
= pixelSize
;
666 if (find_directory (B_USER_SETTINGS_DIRECTORY
, &path
, true) == B_OK
) {
669 path
.Append (kPrefsFileName
);
670 if ((ref
= creat(path
.Path(), S_IRUSR
| S_IWUSR
)) >= 0) {
671 float version
= kCurrentVersion
;
673 lseek (ref
, 0, SEEK_SET
);
674 write(ref
, kAppName
, 7);
675 write(ref
, &version
, sizeof(float));
677 BPoint loc
= Frame().LeftTop();
678 write(ref
, &loc
, sizeof(BPoint
));
680 write(ref
, &fShowGrid
, sizeof(bool));
681 write(ref
, &fShowInfo
, sizeof(bool));
683 CrossHairsShowing(&ch1
, &ch2
);
684 write(ref
, &ch1
, sizeof(bool));
685 write(ref
, &ch2
, sizeof(bool));
687 write(ref
, &fHPixelCount
, sizeof(int32
));
688 write(ref
, &fVPixelCount
, sizeof(int32
));
689 write(ref
, &fPixelSize
, sizeof(int32
));
698 TWindow::FrameResized(float w
, float h
)
700 CalcViewablePixels();
701 fFatBits
->InitBuffers(fHPixelCount
, fVPixelCount
, fPixelSize
, ShowGrid());
702 UpdateInfoBarOnResize();
707 TWindow::ScreenChanged(BRect screenSize
, color_space depth
)
709 BWindow::ScreenChanged(screenSize
, depth
);
711 fFatBits
->ScreenChanged(screenSize
,depth
);
716 TWindow::Minimize(bool m
)
718 BWindow::Minimize(m
);
723 TWindow::Zoom(BPoint
/*position*/, float /*width*/, float /*height*/)
725 if (fFatBits
->Active())
726 ShowInfo(!fShowInfo
);
731 TWindow::CalcViewablePixels()
733 float w
= Bounds().Width();
734 float h
= Bounds().Height();
736 if (InfoIsShowing()) {
737 w
-= 20; // remove the gutter
738 h
= h
-fInfoHeight
-10; // remove info and gutter
742 fFatBits
->CrossHairsShowing(&ch1
, &ch2
);
746 h
-= fFontHeight
+ 5;
748 fHPixelCount
= (int32
)w
/ fPixelSize
; // calc h pixels
749 if (fHPixelCount
< 16)
752 fVPixelCount
= (int32
)h
/ fPixelSize
; // calc v pixels
753 if (fVPixelCount
< 4)
759 TWindow::GetPreferredSize(float* width
, float* height
)
761 *width
= fHPixelCount
* fPixelSize
; // calc window width
762 *height
= fVPixelCount
* fPixelSize
; // calc window height
763 if (InfoIsShowing()) {
765 *height
+= fInfoHeight
+ 10;
769 fFatBits
->CrossHairsShowing(&ch1
, &ch2
);
771 *height
+= fFontHeight
;
773 *height
+= fFontHeight
+ 5;
778 TWindow::ResizeWindow(int32 hPixelCount
, int32 vPixelCount
)
780 fHPixelCount
= hPixelCount
;
781 fVPixelCount
= vPixelCount
;
784 GetPreferredSize(&width
, &height
);
786 ResizeTo(width
, height
);
791 TWindow::ResizeWindow(bool direction
)
793 int32 x
= fHPixelCount
;
794 int32 y
= fVPixelCount
;
815 TWindow::SetGrid(bool s
)
821 fFatBits
->SetUpdate(true);
833 TWindow::ShowInfo(bool i
)
841 fFatBits
->MoveTo(10, fInfoHeight
);
843 fFatBits
->MoveTo(1,1);
844 fFatBits
->SetCrossHairsShowing(false, false);
847 fFatBits
->SetSelection(fShowInfo
);
848 ResizeWindow(fHPixelCount
, fVPixelCount
);
849 fInfo
->SetInfoTextVisible(i
);
854 TWindow::InfoIsShowing()
861 TWindow::InfoBarIsVisible()
863 return fInfoBarState
;
868 TWindow::UpdateInfo()
875 TWindow::UpdateInfoBarOnResize()
877 float infoWidth
, infoHeight
;
878 fInfo
->GetPreferredSize(&infoWidth
, &infoHeight
);
880 if (infoWidth
> Bounds().Width()
881 || infoHeight
> Bounds().Height()) {
884 ShowInfo(fInfoBarState
);
890 TWindow::AddCrossHair()
892 fFatBits
->AddCrossHair();
894 // crosshair info needs to be added
895 // window resizes accordingly
898 GetPreferredSize(&width
, &height
);
899 ResizeTo(width
, height
);
904 TWindow::RemoveCrossHair()
906 fFatBits
->RemoveCrossHair();
908 // crosshair info needs to be removed
909 // window resizes accordingly
912 GetPreferredSize(&width
, &height
);
913 ResizeTo(width
, height
);
918 TWindow::CrossHairsShowing(bool* ch1
, bool* ch2
)
920 fFatBits
->CrossHairsShowing(ch1
, ch2
);
925 TWindow::PixelCount(int32
* h
, int32
*v
)
933 TWindow::SetPixelSize(int32 s
)
945 // tell info that size has changed
946 // tell mag that size has changed
948 float w
= Bounds().Width();
949 float h
= Bounds().Height();
950 CalcViewablePixels();
951 ResizeWindow(fHPixelCount
, fVPixelCount
);
953 // the window might not actually change in size
954 // in that case force the buffers to the new dimension
955 if (w
== Bounds().Width() && h
== Bounds().Height())
956 fFatBits
->InitBuffers(fHPixelCount
, fVPixelCount
, fPixelSize
, ShowGrid());
961 TWindow::SetPixelSize(bool plus
)
966 if (fPixelSize
>= 16)
969 pixelSize
= fPixelSize
+ 1;
971 pixelSize
= fPixelSize
/ 2;
973 if (pixelSize
< 16) {
975 pixelSize
= (fPixelSize
+ 16) / 2;
977 pixelSize
= fPixelSize
- 1;
981 SetPixelSize(pixelSize
);
992 #undef B_TRANSLATION_CONTEXT
993 #define B_TRANSLATION_CONTEXT "Magnify-Main"
999 return fFatBits
->Active();
1004 TWindow::IsSticked()
1006 return fFatBits
->Sticked();
1013 TInfoView::TInfoView(BRect frame
)
1014 : BBox(frame
, "rgb", B_FOLLOW_ALL
,
1015 B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
| B_FRAME_EVENTS
,
1018 SetFont(be_plain_font
);
1019 fFontHeight
= FontHeight(this, true);
1022 fSelectionColor
= kBlack
;
1023 fCH1Loc
.x
= fCH1Loc
.y
= fCH2Loc
.x
= fCH2Loc
.y
= 0;
1030 fInfoTextVisible
= true;
1034 TInfoView::~TInfoView()
1040 TInfoView::AttachedToWindow()
1042 BBox::AttachedToWindow();
1043 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
1044 dynamic_cast<TWindow
*>(Window())->PixelCount(&fHPixelCount
, &fVPixelCount
);
1045 fPixelSize
= dynamic_cast<TWindow
*>(Window())->PixelSize();
1052 TInfoView::Draw(BRect updateRect
)
1055 SetLowColor(ViewColor());
1059 int32 hPixelCount
, vPixelCount
;
1060 dynamic_cast<TWindow
*>(Window())->PixelCount(&hPixelCount
, &vPixelCount
);
1061 int32 pixelSize
= dynamic_cast<TWindow
*>(Window())->PixelSize();
1063 MovePenTo(15 + fPopUp
->Bounds().Width(), fFontHeight
+ 5);
1065 static BMessageFormat
format(B_TRANSLATE("%width x %height @ {0, plural, "
1066 "one{# pixel/pixel} other{# pixels/pixel}}"));
1068 BString dimensionsInfo
;
1069 format
.Format(dimensionsInfo
, pixelSize
);
1073 dimensionsInfo
.ReplaceAll("%width", rep
);
1076 dimensionsInfo
.ReplaceAll("%height", rep
);
1078 invalRect
.Set(10, 5, 10 + StringWidth(fInfoStr
), fFontHeight
+7);
1079 SetHighColor(ViewColor());
1080 FillRect(invalRect
);
1081 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
1082 strcpy(fInfoStr
, dimensionsInfo
);
1083 if (fInfoTextVisible
)
1084 DrawString(fInfoStr
);
1086 rgb_color color
= { 0, 0, 0, 255 };
1088 color
= fMagView
->SelectionColor();
1090 snprintf(str
, sizeof(str
), "R: %i G: %i B: %i (#%02x%02x%02x)",
1091 color
.red
, color
.green
, color
.blue
, color
.red
, color
.green
, color
.blue
);
1093 MovePenTo(15 + fPopUp
->Bounds().Width(), fFontHeight
*2+5);
1094 invalRect
.Set(10, fFontHeight
+7, 10 + StringWidth(fRGBStr
), fFontHeight
*2+7);
1095 SetHighColor(ViewColor());
1096 FillRect(invalRect
);
1097 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
1098 strcpy(fRGBStr
,str
);
1099 if (fInfoTextVisible
)
1100 DrawString(fRGBStr
);
1102 bool ch1Showing
, ch2Showing
;
1103 dynamic_cast<TWindow
*>(Window())->CrossHairsShowing(&ch1Showing
, &ch2Showing
);
1106 BPoint
pt1(fMagView
->CrossHair1Loc());
1107 BPoint
pt2(fMagView
->CrossHair2Loc());
1109 float h
= Bounds().Height();
1111 MovePenTo(10, h
-12);
1112 sprintf(str
, "2) x: %" B_PRIi32
" y: %" B_PRIi32
" y: %d",
1113 (int32
)pt2
.x
, (int32
)pt2
.y
, abs((int)(pt1
.y
- pt2
.y
)));
1114 invalRect
.Set(10, h
-12-fFontHeight
, 10 + StringWidth(fCH2Str
), h
-10);
1115 SetHighColor(ViewColor());
1116 FillRect(invalRect
);
1117 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
1118 strcpy(fCH2Str
,str
);
1119 if (fInfoTextVisible
)
1120 DrawString(fCH2Str
);
1123 if (ch1Showing
&& ch2Showing
) {
1124 MovePenTo(10, h
-10-fFontHeight
-2);
1125 sprintf(str
, "1) x: %" B_PRIi32
" y: %" B_PRIi32
" x: %d",
1126 (int32
)pt1
.x
, (int32
)pt1
.y
, abs((int)(pt1
.x
- pt2
.x
)));
1127 invalRect
.Set(10, h
-10-2*fFontHeight
-2, 10 + StringWidth(fCH1Str
), h
-10-fFontHeight
);
1128 SetHighColor(ViewColor());
1129 FillRect(invalRect
);
1130 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
1131 strcpy(fCH1Str
,str
);
1132 if (fInfoTextVisible
)
1133 DrawString(fCH1Str
);
1134 } else if (ch1Showing
) {
1135 MovePenTo(10, h
-10);
1136 sprintf(str
, "x: %" B_PRIi32
" y: %" B_PRIi32
, (int32
)pt1
.x
, (int32
)pt1
.y
);
1137 invalRect
.Set(10, h
-10-fFontHeight
, 10 + StringWidth(fCH1Str
), h
-8);
1138 SetHighColor(ViewColor());
1139 FillRect(invalRect
);
1140 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
1141 strcpy(fCH1Str
,str
);
1142 if (fInfoTextVisible
)
1143 DrawString(fCH1Str
);
1152 TInfoView::FrameResized(float width
, float height
)
1154 BBox::FrameResized(width
, height
);
1159 TInfoView::AddMenu()
1161 fMenu
= new TMenu(dynamic_cast<TWindow
*>(Window()), "");
1162 BuildInfoMenu(fMenu
);
1164 BRect
r(9, 11, 22, 27);
1165 fPopUp
= new BMenuField( r
, "region menu", NULL
, fMenu
, true,
1166 B_FOLLOW_LEFT
| B_FOLLOW_TOP
);
1172 TInfoView::SetMagView(TMagnify
* magView
)
1181 TMenu::TMenu(TWindow
*mainWindow
, const char *title
, menu_layout layout
)
1182 : BMenu(title
, layout
),
1183 fMainWindow(mainWindow
)
1194 TMenu::AttachedToWindow()
1196 UpdateInfoMenu(this, fMainWindow
);
1198 BMenu::AttachedToWindow();
1203 TInfoView::GetPreferredSize(float* _width
, float* _height
)
1206 float str1Width
= StringWidth(fCH1Str
)
1207 + StringWidth(fCH2Str
)
1208 + StringWidth(fRGBStr
)
1210 float str2Width
= StringWidth(fInfoStr
) + 30;
1211 *_width
= str1Width
> str2Width
? str1Width
: str2Width
;
1215 *_height
= fFontHeight
* 2 + 10;
1220 TInfoView::IsInfoTextVisible()
1222 return fInfoTextVisible
;
1227 TInfoView::SetInfoTextVisible(bool visible
)
1229 fInfoTextVisible
= visible
;
1237 TMagnify::TMagnify(BRect r
, TWindow
* parent
)
1238 : BView(r
, "MagView", B_FOLLOW_NONE
, B_WILL_DRAW
| B_FRAME_EVENTS
),
1239 fNeedToUpdate(true),
1246 fShowSelection(false),
1247 fSelectionLoc(0, 0),
1248 fShowCrossHair1(false),
1249 fCrossHair1(-1, -1),
1250 fShowCrossHair2(false),
1251 fCrossHair2(-1, -1),
1253 fStickCoordinates(false)
1258 TMagnify::~TMagnify()
1260 kill_thread(fThread
);
1266 TMagnify::AttachedToWindow()
1268 int32 width
, height
;
1269 fParent
->PixelCount(&width
, &height
);
1270 InitBuffers(width
, height
, fParent
->PixelSize(), fParent
->ShowGrid());
1272 fThread
= spawn_thread(TMagnify::MagnifyTask
, "MagnifyTask",
1273 B_NORMAL_PRIORITY
, this);
1275 resume_thread(fThread
);
1277 SetViewColor(B_TRANSPARENT_32_BIT
);
1283 TMagnify::InitBuffers(int32 hPixelCount
, int32 vPixelCount
,
1284 int32 pixelSize
, bool showGrid
)
1286 color_space colorSpace
= BScreen(Window()).ColorSpace();
1288 BRect
r(0, 0, (pixelSize
* hPixelCount
)-1, (pixelSize
* vPixelCount
)-1);
1289 if (Bounds().Width() != r
.Width() || Bounds().Height() != r
.Height())
1290 ResizeTo(r
.Width(), r
.Height());
1294 fImageView
->RemoveSelf();
1295 fImageBuf
->Unlock();
1297 fImageView
->Resize((int32
)r
.Width(), (int32
)r
.Height());
1298 fImageView
->SetSpace(colorSpace
);
1300 fImageView
= new TOSMagnify(r
, this, colorSpace
);
1303 fImageBuf
= new BBitmap(r
, colorSpace
, true);
1305 fImageBuf
->AddChild(fImageView
);
1306 fImageBuf
->Unlock();
1311 TMagnify::Draw(BRect
)
1313 BRect
bounds(Bounds());
1314 DrawBitmap(fImageBuf
, bounds
, bounds
);
1315 static_cast<TWindow
*>(Window())->UpdateInfo();
1320 TMagnify::KeyDown(const char *key
, int32 numBytes
)
1322 if (!fShowSelection
)
1323 BView::KeyDown(key
, numBytes
);
1325 uint32 mods
= modifiers();
1329 if (fShowCrossHair1
) {
1332 if (fShowCrossHair2
) {
1335 } else if (fShowCrossHair1
) {
1339 fNeedToUpdate
= true;
1345 if (mods
& B_OPTION_KEY
)
1348 MoveSelection(-1,0);
1351 if (mods
& B_OPTION_KEY
)
1357 if (mods
& B_OPTION_KEY
)
1360 MoveSelection(0,-1);
1363 if (mods
& B_OPTION_KEY
)
1370 BView::KeyDown(key
,numBytes
);
1377 TMagnify::FrameResized(float newW
, float newH
)
1382 if (fSelectionLoc
.x
>= w
)
1383 fSelectionLoc
.x
= 0;
1384 if (fSelectionLoc
.y
>= h
)
1385 fSelectionLoc
.y
= 0;
1387 if (fShowCrossHair1
) {
1388 if (fCrossHair1
.x
>= w
) {
1389 fCrossHair1
.x
= fSelectionLoc
.x
+ 2;
1390 if (fCrossHair1
.x
>= w
)
1393 if (fCrossHair1
.y
>= h
) {
1394 fCrossHair1
.y
= fSelectionLoc
.y
+ 2;
1395 if (fCrossHair1
.y
>= h
)
1399 if (fShowCrossHair2
) {
1400 if (fCrossHair2
.x
>= w
) {
1401 fCrossHair2
.x
= fCrossHair1
.x
+ 2;
1402 if (fCrossHair2
.x
>= w
)
1405 if (fCrossHair2
.y
>= h
) {
1406 fCrossHair2
.y
= fCrossHair1
.y
+ 2;
1407 if (fCrossHair2
.y
>= h
)
1416 TMagnify::MouseDown(BPoint where
)
1418 BMessage
*currentMsg
= Window()->CurrentMessage();
1419 if (currentMsg
->what
== B_MOUSE_DOWN
) {
1421 currentMsg
->FindInt32("buttons", (int32
*)&buttons
);
1423 uint32 modifiers
= 0;
1424 currentMsg
->FindInt32("modifiers", (int32
*)&modifiers
);
1426 if ((buttons
& B_SECONDARY_MOUSE_BUTTON
) || (modifiers
& B_CONTROL_KEY
)) {
1427 // secondary button was clicked or control key was down, show menu and return
1429 BPopUpMenu
*menu
= new BPopUpMenu(B_TRANSLATE("Info"), false, false);
1430 menu
->SetFont(be_plain_font
);
1431 BuildInfoMenu(menu
);
1432 UpdateInfoMenu(menu
, dynamic_cast<TWindow
*>(Window()));
1433 BMenuItem
*selected
= menu
->Go(ConvertToScreen(where
));
1435 Window()->PostMessage(selected
->Message()->what
);
1440 // add a mousedown looper here
1442 int32 pixelSize
= PixelSize();
1443 float x
= where
.x
/ pixelSize
;
1444 float y
= where
.y
/ pixelSize
;
1446 MoveSelectionTo(x
, y
);
1448 // draw the frozen image
1449 // update the info region
1451 fNeedToUpdate
= true;
1458 TMagnify::ScreenChanged(BRect
, color_space
)
1460 int32 width
, height
;
1461 fParent
->PixelCount(&width
, &height
);
1462 InitBuffers(width
, height
, fParent
->PixelSize(), fParent
->ShowGrid());
1467 TMagnify::SetSelection(bool state
)
1469 if (fShowSelection
== state
)
1472 fShowSelection
= state
;
1479 TMagnify::MoveSelection(int32 x
, int32 y
)
1481 if (!fShowSelection
)
1484 int32 xCount
, yCount
;
1485 PixelCount(&xCount
, &yCount
);
1488 if (fSelection
== 0) {
1489 xloc
= fSelectionLoc
.x
;
1490 yloc
= fSelectionLoc
.y
;
1491 BoundsSelection(x
, y
, &xloc
, &yloc
, xCount
, yCount
);
1492 fSelectionLoc
.x
= xloc
;
1493 fSelectionLoc
.y
= yloc
;
1494 } else if (fSelection
== 1) {
1495 xloc
= fCrossHair1
.x
;
1496 yloc
= fCrossHair1
.y
;
1497 BoundsSelection(x
, y
, &xloc
, &yloc
, xCount
, yCount
);
1498 fCrossHair1
.x
= xloc
;
1499 fCrossHair1
.y
= yloc
;
1500 } else if (fSelection
== 2) {
1501 xloc
= fCrossHair2
.x
;
1502 yloc
= fCrossHair2
.y
;
1503 BoundsSelection(x
, y
, &xloc
, &yloc
, xCount
, yCount
);
1504 fCrossHair2
.x
= xloc
;
1505 fCrossHair2
.y
= yloc
;
1508 fNeedToUpdate
= true;
1514 TMagnify::MoveSelectionTo(int32 x
, int32 y
)
1516 if (!fShowSelection
)
1519 int32 xCount
, yCount
;
1520 PixelCount(&xCount
, &yCount
);
1526 if (fSelection
== 0) {
1527 fSelectionLoc
.x
= x
;
1528 fSelectionLoc
.y
= y
;
1529 } else if (fSelection
== 1) {
1532 } else if (fSelection
== 2) {
1537 fNeedToUpdate
= true;
1538 Invalidate(); //Draw(Bounds());
1543 TMagnify::ShowSelection()
1549 TMagnify::Selection()
1556 TMagnify::SelectionIsShowing()
1558 return fShowSelection
;
1563 TMagnify::SelectionLoc(float* x
, float* y
)
1565 *x
= fSelectionLoc
.x
;
1566 *y
= fSelectionLoc
.y
;
1571 TMagnify::SetSelectionLoc(float x
, float y
)
1573 fSelectionLoc
.x
= x
;
1574 fSelectionLoc
.y
= y
;
1579 TMagnify::SelectionColor()
1581 return fImageView
->ColorAtSelection();
1586 TMagnify::CrossHair1Loc(float* x
, float* y
)
1594 TMagnify::CrossHair2Loc(float* x
, float* y
)
1602 TMagnify::CrossHair1Loc()
1609 TMagnify::CrossHair2Loc()
1616 TMagnify::NudgeMouse(float x
, float y
)
1621 GetMouse(&loc
, &button
);
1622 ConvertToScreen(&loc
);
1626 set_mouse_position((int32
)loc
.x
, (int32
)loc
.y
);
1631 TMagnify::WindowActivated(bool active
)
1639 TMagnify::MagnifyTask(void *arg
)
1641 TMagnify
* view
= (TMagnify
*)arg
;
1643 // static data members can't access members, methods without
1644 // a pointer to an instance of the class
1645 TWindow
* window
= (TWindow
*)view
->Window();
1648 if (window
->Lock()) {
1649 if (view
->NeedToUpdate() || view
->Active())
1650 view
->Update(view
->NeedToUpdate());
1662 TMagnify::Update(bool force
)
1666 static long counter
= 0;
1668 if (!fStickCoordinates
) {
1669 GetMouse(&loc
, &button
);
1670 ConvertToScreen(&loc
);
1674 if (force
|| fLastLoc
!= loc
|| counter
++ % 35 == 0) {
1675 if (fImageView
->CreateImage(loc
, force
))
1687 TMagnify::NeedToUpdate()
1689 return fNeedToUpdate
;
1694 TMagnify::SetUpdate(bool s
)
1701 TMagnify::CopyImage()
1704 be_clipboard
->Lock();
1705 be_clipboard
->Clear();
1707 BMessage
*message
= be_clipboard
->Data();
1709 printf(B_TRANSLATE_CONTEXT("no clip msg\n",
1710 "In console, when clipboard is empty after clicking Copy image"));
1714 BMessage
*embeddedBitmap
= new BMessage();
1715 (fImageView
->Bitmap())->Archive(embeddedBitmap
,false);
1716 status_t err
= message
->AddMessage(kBitmapMimeType
, embeddedBitmap
);
1718 err
= message
->AddRect("rect", fImageView
->Bitmap()->Bounds());
1720 be_clipboard
->Commit();
1722 be_clipboard
->Unlock();
1728 TMagnify::AddCrossHair()
1730 if (fShowCrossHair1
&& fShowCrossHair2
)
1736 if (fShowCrossHair1
) {
1738 fShowCrossHair2
= true;
1739 fCrossHair2
.x
= fCrossHair1
.x
+ 2;
1740 if (fCrossHair2
.x
>= w
)
1742 fCrossHair2
.y
= fCrossHair1
.y
+ 2;
1743 if (fCrossHair2
.y
>= h
)
1747 fShowCrossHair1
= true;
1748 fCrossHair1
.x
= fSelectionLoc
.x
+ 2;
1749 if (fCrossHair1
.x
>= w
)
1751 fCrossHair1
.y
= fSelectionLoc
.y
+ 2;
1752 if (fCrossHair1
.y
>= h
)
1760 TMagnify::RemoveCrossHair()
1762 if (!fShowCrossHair1
&& !fShowCrossHair2
)
1765 if (fShowCrossHair2
) {
1767 fShowCrossHair2
= false;
1768 } else if (fShowCrossHair1
) {
1770 fShowCrossHair1
= false;
1777 TMagnify::SetCrossHairsShowing(bool ch1
, bool ch2
)
1779 fShowCrossHair1
= ch1
;
1780 fShowCrossHair2
= ch2
;
1785 TMagnify::CrossHairsShowing(bool* ch1
, bool* ch2
)
1787 *ch1
= fShowCrossHair1
;
1788 *ch2
= fShowCrossHair2
;
1793 TMagnify::MakeActive(bool s
)
1800 TMagnify::MakeSticked(bool s
)
1802 fStickCoordinates
= s
;
1807 TMagnify::PixelCount(int32
* width
, int32
* height
)
1809 fParent
->PixelCount(width
, height
);
1814 TMagnify::PixelSize()
1816 return fParent
->PixelSize();
1821 TMagnify::ShowGrid()
1823 return fParent
->ShowGrid();
1828 TMagnify::StartSave()
1830 fImageFrozenOnSave
= Active();
1831 if (fImageFrozenOnSave
)
1839 if (fImageFrozenOnSave
)
1845 TMagnify::SaveImage(entry_ref
* ref
, char* name
)
1847 // create a new file
1849 BDirectory
parentDir(ref
);
1850 parentDir
.CreateFile(name
, &file
);
1852 // Write the screenshot bitmap to the file
1853 BBitmapStream
stream(fImageView
->Bitmap());
1854 BTranslatorRoster
* roster
= BTranslatorRoster::Default();
1855 roster
->Translate(&stream
, NULL
, NULL
, &file
, B_PNG_FORMAT
,
1856 B_TRANSLATOR_BITMAP
);
1859 stream
.DetachBitmap(&bitmap
);
1860 // The stream takes over ownership of the bitmap
1862 // unfreeze the image, image was frozen before invoke of FilePanel
1869 TOSMagnify::TOSMagnify(BRect r
, TMagnify
* parent
, color_space space
)
1870 : BView(r
, "ImageView", B_FOLLOW_NONE
, B_WILL_DRAW
| B_FRAME_EVENTS
),
1871 fColorSpace(space
), fParent(parent
)
1895 // uh, oh -- a color space we don't support
1896 fprintf(stderr
, "Tried to run in an unsupported color space; exiting\n");
1908 TOSMagnify::~TOSMagnify()
1917 TOSMagnify::SetSpace(color_space space
)
1919 fColorSpace
= space
;
1925 TOSMagnify::InitObject()
1928 fParent
->PixelCount(&w
, &h
);
1931 BRect
bitsRect(0, 0, w
-1, h
-1);
1932 fBitmap
= new BBitmap(bitsRect
, fColorSpace
);
1935 fOldBits
= (char*)malloc(fBitmap
->BitsLength());
1938 #if B_HOST_IS_BENDIAN
1939 fPixel
= new BBitmap(BRect(0,0,0,0), B_RGBA32_BIG
, true);
1941 fPixel
= new BBitmap(BRect(0,0,0,0), B_RGBA32
, true);
1943 fPixelView
= new BView(BRect(0,0,0,0), NULL
, 0, 0);
1945 fPixel
->AddChild(fPixelView
);
1952 TOSMagnify::FrameResized(float width
, float height
)
1954 BView::FrameResized(width
, height
);
1960 TOSMagnify::Resize(int32 width
, int32 height
)
1962 ResizeTo(width
, height
);
1968 TOSMagnify::CreateImage(BPoint mouseLoc
, bool force
)
1970 bool created
= false;
1971 if (Window() && Window()->Lock()) {
1972 int32 width
, height
;
1973 fParent
->PixelCount(&width
, &height
);
1974 int32 pixelSize
= fParent
->PixelSize();
1976 BRect
srcRect(0, 0, width
- 1, height
- 1);
1977 srcRect
.OffsetBy(mouseLoc
.x
- (width
/ 2),
1978 mouseLoc
.y
- (height
/ 2));
1980 if (force
|| CopyScreenRect(srcRect
)) {
1981 srcRect
.OffsetTo(BPoint(0, 0));
1982 BRect
destRect(Bounds());
1984 DrawBitmap(fBitmap
, srcRect
, destRect
);
1986 DrawGrid(width
, height
, destRect
, pixelSize
);
1994 printf("window problem\n");
2001 TOSMagnify::CopyScreenRect(BRect srcRect
)
2003 // constrain src rect to legal screen rect
2004 BScreen
screen(Window());
2005 BRect scrnframe
= screen
.Frame();
2007 if (srcRect
.right
> scrnframe
.right
)
2008 srcRect
.OffsetTo(scrnframe
.right
- srcRect
.Width(), srcRect
.top
);
2009 if (srcRect
.top
< 0)
2010 srcRect
.OffsetTo(srcRect
.left
, 0);
2012 if (srcRect
.bottom
> scrnframe
.bottom
)
2013 srcRect
.OffsetTo(srcRect
.left
, scrnframe
.bottom
- srcRect
.Height());
2014 if (srcRect
.left
< 0)
2015 srcRect
.OffsetTo(0, srcRect
.top
);
2017 // save a copy of the bits for comparison later
2018 memcpy(fOldBits
, fBitmap
->Bits(), fBitmap
->BitsLength());
2020 screen
.ReadBitmap(fBitmap
, false, &srcRect
);
2022 // let caller know whether bits have actually changed
2023 return memcmp(fBitmap
->Bits(), fOldBits
, fBitmap
->BitsLength()) != 0;
2028 TOSMagnify::DrawGrid(int32 width
, int32 height
, BRect destRect
, int32 pixelSize
)
2031 if (fParent
->ShowGrid() && fParent
->PixelSize() > 2) {
2032 BeginLineArray(width
* height
);
2035 for (int32 i
= pixelSize
; i
< (height
* pixelSize
); i
+= pixelSize
)
2036 AddLine(BPoint(0, i
), BPoint(destRect
.right
, i
), kGridGray
);
2039 for (int32 i
= pixelSize
; i
< (width
* pixelSize
); i
+= pixelSize
)
2040 AddLine(BPoint(i
, 0), BPoint(i
, destRect
.bottom
), kGridGray
);
2045 SetHighColor(kGridGray
);
2046 StrokeRect(destRect
);
2051 TOSMagnify::DrawSelection()
2053 if (!fParent
->SelectionIsShowing())
2057 int32 pixelSize
= fParent
->PixelSize();
2058 int32 squareSize
= pixelSize
- 2;
2060 fParent
->SelectionLoc(&x
, &y
);
2061 x
*= pixelSize
; x
++;
2062 y
*= pixelSize
; y
++;
2063 BRect
selRect(x
, y
, x
+squareSize
, y
+squareSize
);
2065 short selection
= fParent
->Selection();
2068 SetLowColor(ViewColor());
2069 SetHighColor(kRedColor
);
2070 StrokeRect(selRect
);
2071 if (selection
== 0) {
2072 StrokeLine(BPoint(x
,y
), BPoint(x
+squareSize
,y
+squareSize
));
2073 StrokeLine(BPoint(x
,y
+squareSize
), BPoint(x
+squareSize
,y
));
2076 bool ch1Showing
, ch2Showing
;
2077 fParent
->CrossHairsShowing(&ch1Showing
, &ch2Showing
);
2079 SetHighColor(kBlueColor
);
2080 fParent
->CrossHair1Loc(&x
, &y
);
2081 x
*= pixelSize
; x
++;
2082 y
*= pixelSize
; y
++;
2083 selRect
.Set(x
, y
,x
+squareSize
, y
+squareSize
);
2084 StrokeRect(selRect
);
2086 AddLine(BPoint(0, y
+(squareSize
/2)),
2087 BPoint(x
, y
+(squareSize
/2)), kBlueColor
); // left
2088 AddLine(BPoint(x
+squareSize
,y
+(squareSize
/2)),
2089 BPoint(Bounds().Width(), y
+(squareSize
/2)), kBlueColor
); // right
2090 AddLine(BPoint(x
+(squareSize
/2), 0),
2091 BPoint(x
+(squareSize
/2), y
), kBlueColor
); // top
2092 AddLine(BPoint(x
+(squareSize
/2), y
+squareSize
),
2093 BPoint(x
+(squareSize
/2), Bounds().Height()), kBlueColor
); // bottom
2095 if (selection
== 1) {
2096 StrokeLine(BPoint(x
,y
), BPoint(x
+squareSize
,y
+squareSize
));
2097 StrokeLine(BPoint(x
,y
+squareSize
), BPoint(x
+squareSize
,y
));
2101 SetHighColor(kBlueColor
);
2102 fParent
->CrossHair2Loc(&x
, &y
);
2103 x
*= pixelSize
; x
++;
2104 y
*= pixelSize
; y
++;
2105 selRect
.Set(x
, y
,x
+squareSize
, y
+squareSize
);
2106 StrokeRect(selRect
);
2108 AddLine(BPoint(0, y
+(squareSize
/2)),
2109 BPoint(x
, y
+(squareSize
/2)), kBlueColor
); // left
2110 AddLine(BPoint(x
+squareSize
,y
+(squareSize
/2)),
2111 BPoint(Bounds().Width(), y
+(squareSize
/2)), kBlueColor
); // right
2112 AddLine(BPoint(x
+(squareSize
/2), 0),
2113 BPoint(x
+(squareSize
/2), y
), kBlueColor
); // top
2114 AddLine(BPoint(x
+(squareSize
/2), y
+squareSize
),
2115 BPoint(x
+(squareSize
/2), Bounds().Height()), kBlueColor
); // bottom
2117 if (selection
== 2) {
2118 StrokeLine(BPoint(x
,y
), BPoint(x
+squareSize
,y
+squareSize
));
2119 StrokeLine(BPoint(x
,y
+squareSize
), BPoint(x
+squareSize
,y
));
2128 TOSMagnify::ColorAtSelection()
2131 fParent
->SelectionLoc(&x
, &y
);
2132 BRect
srcRect(x
, y
, x
, y
);
2133 BRect
dstRect(0, 0, 0, 0);
2135 fPixelView
->DrawBitmap(fBitmap
, srcRect
, dstRect
);
2139 uint32 pixel
= *((uint32
*)fPixel
->Bits());
2141 c
.alpha
= pixel
>> 24;
2142 c
.red
= (pixel
>> 16) & 0xFF;
2143 c
.green
= (pixel
>> 8) & 0xFF;
2144 c
.blue
= pixel
& 0xFF;
2154 main(int argc
, char* argv
[])
2156 int32 pixelCount
= -1;
2159 printf(B_TRANSLATE_CONTEXT(
2160 "usage: magnify [size] (magnify size * size pixels)\n",
2165 pixelCount
= abs(atoi(argv
[1]));
2167 if ((pixelCount
> 100) || (pixelCount
< 4)) {
2168 printf(B_TRANSLATE_CONTEXT(
2169 "usage: magnify [size] (magnify size * size pixels)\n",
2171 printf(B_TRANSLATE_CONTEXT(
2172 " size must be > 4 and a multiple of 4\n",
2177 if (pixelCount
% 4) {
2178 printf(B_TRANSLATE_CONTEXT(
2179 "magnify: size must be a multiple of 4\n",
2186 TApp
app(pixelCount
);