Mercurial > hg > orthanc-stone
comparison Applications/Samples/SingleFrameEditorApplication.h @ 357:ec4ad6c5eb99 am-2
avoid breaking class hierarchy
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 29 Oct 2018 17:59:04 +0100 |
parents | 885f0a5eaa49 |
children | b8eeb49f3e65 |
comparison
equal
deleted
inserted
replaced
356:885f0a5eaa49 | 357:ec4ad6c5eb99 |
---|---|
1273 } | 1273 } |
1274 | 1274 |
1275 return false; | 1275 return false; |
1276 } | 1276 } |
1277 | 1277 |
1278 void DrawControls(CairoSurface& surface, | 1278 void DrawControls(CairoContext& context, |
1279 const ViewportGeometry& view) | 1279 double zoom) |
1280 { | 1280 { |
1281 if (hasSelection_) | 1281 if (hasSelection_) |
1282 { | 1282 { |
1283 Bitmaps::const_iterator bitmap = bitmaps_.find(selectedBitmap_); | 1283 Bitmaps::const_iterator bitmap = bitmaps_.find(selectedBitmap_); |
1284 | 1284 |
1285 if (bitmap != bitmaps_.end()) | 1285 if (bitmap != bitmaps_.end()) |
1286 { | 1286 { |
1287 CairoContext context(surface); | |
1288 | |
1289 context.SetSourceColor(255, 0, 0); | 1287 context.SetSourceColor(255, 0, 0); |
1290 view.ApplyTransform(context); | 1288 //view.ApplyTransform(context); |
1291 bitmap->second->DrawBorders(context, view.GetZoom()); | 1289 bitmap->second->DrawBorders(context, zoom); |
1292 } | 1290 } |
1293 } | 1291 } |
1294 } | 1292 } |
1295 | 1293 |
1296 | 1294 |
1972 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 1970 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
1973 } | 1971 } |
1974 | 1972 |
1975 virtual void MouseUp() | 1973 virtual void MouseUp() |
1976 { | 1974 { |
1977 if (accessor_.IsValid()) | 1975 if (accessor_.IsValid() && |
1976 accessor_.GetBitmap().IsResizeable()) | |
1978 { | 1977 { |
1979 undoRedoStack_.Add(new UndoRedoCommand(*this)); | 1978 undoRedoStack_.Add(new UndoRedoCommand(*this)); |
1980 } | 1979 } |
1981 } | 1980 } |
1982 | 1981 |
2440 public WorldSceneWidget, | 2439 public WorldSceneWidget, |
2441 public IObservable, | 2440 public IObservable, |
2442 public IObserver | 2441 public IObserver |
2443 { | 2442 { |
2444 private: | 2443 private: |
2445 BitmapStack& stack_; | 2444 BitmapStack& stack_; |
2446 BitmapStackInteractor myInteractor_; | 2445 BitmapStackInteractor myInteractor_; |
2447 | 2446 std::auto_ptr<Orthanc::Image> floatBuffer_; |
2448 protected: | 2447 std::auto_ptr<CairoSurface> cairoBuffer_; |
2449 virtual Extent2D GetSceneExtent() | 2448 |
2450 { | 2449 virtual bool RenderInternal(unsigned int width, |
2451 return stack_.GetSceneExtent(); | 2450 unsigned int height, |
2452 } | 2451 ImageInterpolation interpolation) |
2453 | 2452 { |
2454 virtual bool RenderScene(CairoContext& context, | |
2455 const ViewportGeometry& view) | |
2456 { | |
2457 // "Render()" has been replaced | |
2458 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
2459 } | |
2460 | |
2461 public: | |
2462 BitmapStackWidget(MessageBroker& broker, | |
2463 BitmapStack& stack, | |
2464 const std::string& name) : | |
2465 WorldSceneWidget(name), | |
2466 IObservable(broker), | |
2467 IObserver(broker), | |
2468 stack_(stack), | |
2469 myInteractor_(stack_) | |
2470 { | |
2471 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged)); | |
2472 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged)); | |
2473 | |
2474 SetInteractor(myInteractor_); | |
2475 } | |
2476 | |
2477 void OnGeometryChanged(const BitmapStack::GeometryChangedMessage& message) | |
2478 { | |
2479 printf("Geometry has changed\n"); | |
2480 FitContent(); | |
2481 } | |
2482 | |
2483 void OnContentChanged(const BitmapStack::ContentChangedMessage& message) | |
2484 { | |
2485 printf("Content has changed\n"); | |
2486 NotifyContentChanged(); | |
2487 } | |
2488 | |
2489 virtual bool Render(Orthanc::ImageAccessor& target) | |
2490 { | |
2491 Orthanc::Image buffer(Orthanc::PixelFormat_Float32, target.GetWidth(), | |
2492 target.GetHeight(), false); | |
2493 | |
2494 // TODO => rendering quality | |
2495 stack_.Render(buffer, GetView(), ImageInterpolation_Nearest); | |
2496 //stack_.Render(buffer, GetView(), ImageInterpolation_Bilinear); | |
2497 | |
2498 // As in GrayscaleFrameRenderer => TODO MERGE? | |
2499 | |
2500 float windowCenter, windowWidth; | 2453 float windowCenter, windowWidth; |
2501 stack_.GetWindowingWithDefault(windowCenter, windowWidth); | 2454 stack_.GetWindowingWithDefault(windowCenter, windowWidth); |
2502 | 2455 |
2503 float x0 = windowCenter - windowWidth / 2.0f; | 2456 float x0 = windowCenter - windowWidth / 2.0f; |
2504 float x1 = windowCenter + windowWidth / 2.0f; | 2457 float x1 = windowCenter + windowWidth / 2.0f; |
2505 | 2458 |
2506 if (windowWidth >= 0.001f) // Avoid division by zero at (*) | 2459 if (windowWidth <= 0.001f) // Avoid division by zero at (*) |
2507 { | 2460 { |
2508 const unsigned int width = target.GetWidth(); | 2461 return false; |
2509 const unsigned int height = target.GetHeight(); | 2462 } |
2510 | 2463 else |
2464 { | |
2465 if (floatBuffer_.get() == NULL || | |
2466 floatBuffer_->GetWidth() != width || | |
2467 floatBuffer_->GetHeight() != height) | |
2468 { | |
2469 floatBuffer_.reset(new Orthanc::Image(Orthanc::PixelFormat_Float32, width, height, false)); | |
2470 } | |
2471 | |
2472 if (cairoBuffer_.get() == NULL || | |
2473 cairoBuffer_->GetWidth() != width || | |
2474 cairoBuffer_->GetHeight() != height) | |
2475 { | |
2476 cairoBuffer_.reset(new CairoSurface(width, height)); | |
2477 } | |
2478 | |
2479 stack_.Render(*floatBuffer_, GetView(), interpolation); | |
2480 | |
2481 // TODO => rendering quality | |
2482 | |
2483 // As in GrayscaleFrameRenderer => TODO MERGE? | |
2484 | |
2485 Orthanc::ImageAccessor target; | |
2486 cairoBuffer_->GetAccessor(target); | |
2487 | |
2511 for (unsigned int y = 0; y < height; y++) | 2488 for (unsigned int y = 0; y < height; y++) |
2512 { | 2489 { |
2513 const float* p = reinterpret_cast<const float*>(buffer.GetConstRow(y)); | 2490 const float* p = reinterpret_cast<const float*>(floatBuffer_->GetConstRow(y)); |
2514 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | 2491 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
2515 | 2492 |
2516 for (unsigned int x = 0; x < width; x++, p++, q += 4) | 2493 for (unsigned int x = 0; x < width; x++, p++, q += 4) |
2517 { | 2494 { |
2518 uint8_t v = 0; | 2495 uint8_t v = 0; |
2540 q[1] = v; | 2517 q[1] = v; |
2541 q[2] = v; | 2518 q[2] = v; |
2542 q[3] = 255; | 2519 q[3] = 255; |
2543 } | 2520 } |
2544 } | 2521 } |
2522 | |
2523 return true; | |
2524 } | |
2525 } | |
2526 | |
2527 | |
2528 protected: | |
2529 virtual Extent2D GetSceneExtent() | |
2530 { | |
2531 return stack_.GetSceneExtent(); | |
2532 } | |
2533 | |
2534 virtual bool RenderScene(CairoContext& context, | |
2535 const ViewportGeometry& view) | |
2536 { | |
2537 ImageInterpolation interpolation = ImageInterpolation_Nearest; // TODO PARAMETER? | |
2538 | |
2539 cairo_t* cr = context.GetObject(); | |
2540 | |
2541 if (RenderInternal(context.GetWidth(), context.GetHeight(), interpolation)) | |
2542 { | |
2543 // https://www.cairographics.org/FAQ/#paint_from_a_surface | |
2544 cairo_save(cr); | |
2545 cairo_identity_matrix(cr); | |
2546 cairo_set_source_surface(cr, cairoBuffer_->GetObject(), 0, 0); | |
2547 cairo_paint(cr); | |
2548 cairo_restore(cr); | |
2549 } | |
2550 else | |
2551 { | |
2552 // https://www.cairographics.org/FAQ/#clear_a_surface | |
2553 context.SetSourceColor(0, 0, 0); | |
2554 cairo_paint(cr); | |
2555 } | |
2556 | |
2557 stack_.DrawControls(context, view.GetZoom()); | |
2558 | |
2559 return true; | |
2560 } | |
2561 | |
2562 public: | |
2563 BitmapStackWidget(MessageBroker& broker, | |
2564 BitmapStack& stack, | |
2565 const std::string& name) : | |
2566 WorldSceneWidget(name), | |
2567 IObservable(broker), | |
2568 IObserver(broker), | |
2569 stack_(stack), | |
2570 myInteractor_(stack_) | |
2571 { | |
2572 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged)); | |
2573 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged)); | |
2574 | |
2575 SetInteractor(myInteractor_); | |
2576 } | |
2577 | |
2578 void OnGeometryChanged(const BitmapStack::GeometryChangedMessage& message) | |
2579 { | |
2580 printf("Geometry has changed\n"); | |
2581 FitContent(); | |
2582 } | |
2583 | |
2584 void OnContentChanged(const BitmapStack::ContentChangedMessage& message) | |
2585 { | |
2586 printf("Content has changed\n"); | |
2587 NotifyContentChanged(); | |
2588 } | |
2589 | |
2590 #if 0 | |
2591 virtual bool Render(Orthanc::ImageAccessor& target) | |
2592 { | |
2593 if (RenderInternal(target.GetWidth(), target.GetHeight(), ImageInterpolation_Nearest)) | |
2594 { | |
2595 assert(cairoBuffer_.get() != NULL); | |
2596 | |
2597 Orthanc::ImageAccessor source; | |
2598 cairoBuffer_->GetAccessor(source); | |
2599 Orthanc::ImageProcessing::Copy(target, source); | |
2545 } | 2600 } |
2546 else | 2601 else |
2547 { | 2602 { |
2548 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255); | 2603 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255); |
2549 } | 2604 } |
2550 | 2605 |
2551 { | 2606 { |
2552 // TODO => REFACTOR | 2607 // TODO => REFACTOR |
2553 CairoSurface surface(target); | 2608 CairoSurface surface(target); |
2554 stack_.DrawControls(surface, GetView()); | 2609 CairoContext context(surface); |
2610 GetView().ApplyTransform(context); | |
2611 stack_.DrawControls(context, GetView().GetZoom()); | |
2555 } | 2612 } |
2556 | 2613 |
2557 return true; | 2614 return true; |
2558 } | 2615 } |
2559 | 2616 #endif |
2560 }; | 2617 }; |
2561 | 2618 |
2562 | 2619 |
2563 namespace Samples | 2620 namespace Samples |
2564 { | 2621 { |
2732 | 2789 |
2733 Orthanc::FontRegistry fonts; | 2790 Orthanc::FontRegistry fonts; |
2734 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); | 2791 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); |
2735 | 2792 |
2736 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); | 2793 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); |
2737 //stack_->LoadFrame(instance, frame, false); | 2794 stack_->LoadFrame(instance, frame, false); |
2738 //stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); | 2795 stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); |
2739 | 2796 |
2740 { | 2797 { |
2741 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain"); | 2798 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain"); |
2742 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); | 2799 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); |
2743 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); | 2800 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); |
2744 } | 2801 } |
2745 | 2802 |
2746 { | 2803 { |
2747 BitmapStack::Bitmap& bitmap = stack_->LoadTestBlock(100, 50); | 2804 BitmapStack::Bitmap& bitmap = stack_->LoadTestBlock(100, 50); |
2748 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); | 2805 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); |
2749 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); | 2806 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); |
2750 } | 2807 } |
2751 | 2808 |
2752 | 2809 |
2753 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); | 2810 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); |