| # Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 
 | # | 
 | # Use of this source code is governed by a BSD-style license | 
 | # that can be found in the LICENSE file in the root of the source | 
 | # tree. An additional intellectual property rights grant can be found | 
 | # in the file PATENTS.  All contributing project authors may | 
 | # be found in the AUTHORS file in the root of the source tree. | 
 |  | 
 | import("//build/config/linux/pkg_config.gni") | 
 | import("//build/config/ui.gni") | 
 | import("//tools/generate_stubs/rules.gni") | 
 | import("../../webrtc.gni") | 
 |  | 
 | use_desktop_capture_differ_sse2 = current_cpu == "x86" || current_cpu == "x64" | 
 |  | 
 | config("x11_config") { | 
 |   if (rtc_use_x11_extensions) { | 
 |     defines = [ "WEBRTC_USE_X11" ] | 
 |   } | 
 | } | 
 |  | 
 | rtc_library("primitives") { | 
 |   visibility = [ "*" ] | 
 |   sources = [ | 
 |     "desktop_capture_types.h", | 
 |     "desktop_frame.cc", | 
 |     "desktop_frame.h", | 
 |     "desktop_geometry.cc", | 
 |     "desktop_geometry.h", | 
 |     "desktop_region.cc", | 
 |     "desktop_region.h", | 
 |     "shared_desktop_frame.cc", | 
 |     "shared_desktop_frame.h", | 
 |     "shared_memory.cc", | 
 |     "shared_memory.h", | 
 |   ] | 
 |  | 
 |   deps = [ | 
 |     "../../api:scoped_refptr", | 
 |     "../../rtc_base:checks", | 
 |     "../../rtc_base/system:rtc_export", | 
 |     "//third_party/libyuv", | 
 |   ] | 
 |  | 
 |   if (!build_with_mozilla) { | 
 |     deps += [ "../../rtc_base" ]  # TODO(kjellander): Cleanup in | 
 |                                   # bugs.webrtc.org/3806. | 
 |   } | 
 | } | 
 |  | 
 | if (rtc_include_tests) { | 
 |   rtc_library("desktop_capture_modules_tests") { | 
 |     testonly = true | 
 |  | 
 |     defines = [] | 
 |     sources = [] | 
 |     deps = [ | 
 |       "../../api:function_view", | 
 |       "../../api:scoped_refptr", | 
 |       "../../rtc_base:checks", | 
 |     ] | 
 |     if (rtc_desktop_capture_supported) { | 
 |       deps += [ | 
 |         ":desktop_capture_mock", | 
 |         ":primitives", | 
 |         ":screen_drawer", | 
 |         "../../rtc_base", | 
 |         "../../rtc_base:rtc_base_approved", | 
 |         "../../rtc_base/third_party/base64", | 
 |         "../../system_wrappers", | 
 |         "../../test:test_support", | 
 |         "../../test:video_test_support", | 
 |       ] | 
 |       sources += [ | 
 |         "screen_capturer_integration_test.cc", | 
 |         "screen_drawer_unittest.cc", | 
 |         "window_finder_unittest.cc", | 
 |       ] | 
 |       public_configs = [ ":x11_config" ] | 
 |     } | 
 |   } | 
 |  | 
 |   rtc_library("desktop_capture_unittests") { | 
 |     testonly = true | 
 |  | 
 |     defines = [] | 
 |     sources = [ | 
 |       "blank_detector_desktop_capturer_wrapper_unittest.cc", | 
 |       "cropped_desktop_frame_unittest.cc", | 
 |       "desktop_and_cursor_composer_unittest.cc", | 
 |       "desktop_capturer_differ_wrapper_unittest.cc", | 
 |       "desktop_frame_rotation_unittest.cc", | 
 |       "desktop_frame_unittest.cc", | 
 |       "desktop_geometry_unittest.cc", | 
 |       "desktop_region_unittest.cc", | 
 |       "differ_block_unittest.cc", | 
 |       "fallback_desktop_capturer_wrapper_unittest.cc", | 
 |       "mouse_cursor_monitor_unittest.cc", | 
 |       "rgba_color_unittest.cc", | 
 |       "test_utils.cc", | 
 |       "test_utils.h", | 
 |       "test_utils_unittest.cc", | 
 |     ] | 
 |     if (is_win) { | 
 |       sources += [ | 
 |         "win/cursor_unittest.cc", | 
 |         "win/cursor_unittest_resources.h", | 
 |         "win/cursor_unittest_resources.rc", | 
 |         "win/screen_capture_utils_unittest.cc", | 
 |         "win/screen_capturer_win_directx_unittest.cc", | 
 |         "win/test_support/test_window.cc", | 
 |         "win/test_support/test_window.h", | 
 |         "win/window_capture_utils_unittest.cc", | 
 |       ] | 
 |     } | 
 |     deps = [ | 
 |       ":desktop_capture", | 
 |       ":desktop_capture_mock", | 
 |       ":primitives", | 
 |       "../../rtc_base:checks", | 
 |  | 
 |       # TODO(bugs.webrtc.org/9987): Remove this dep on rtc_base:rtc_base once | 
 |       # rtc_base:threading is fully defined. | 
 |       "../../rtc_base:rtc_base", | 
 |       "../../rtc_base:rtc_base_approved", | 
 |       "../../rtc_base:threading", | 
 |       "../../system_wrappers", | 
 |       "../../test:test_support", | 
 |     ] | 
 |     if (rtc_desktop_capture_supported) { | 
 |       sources += [ | 
 |         "screen_capturer_helper_unittest.cc", | 
 |         "screen_capturer_unittest.cc", | 
 |         "window_capturer_unittest.cc", | 
 |       ] | 
 |       if (is_mac) { | 
 |         sources += [ "screen_capturer_mac_unittest.cc" ] | 
 |       } | 
 |       if (rtc_enable_win_wgc) { | 
 |         sources += [ | 
 |           "win/wgc_capture_source_unittest.cc", | 
 |           "win/wgc_capturer_win_unittest.cc", | 
 |         ] | 
 |       } | 
 |       deps += [ | 
 |         ":desktop_capture_mock", | 
 |         "../../system_wrappers:metrics", | 
 |       ] | 
 |       public_configs = [ ":x11_config" ] | 
 |     } | 
 |   } | 
 |  | 
 |   rtc_library("screen_drawer") { | 
 |     testonly = true | 
 |  | 
 |     public_deps = [ ":desktop_capture" ]  # no-presubmit-check TODO(webrtc:8603) | 
 |  | 
 |     sources = [ | 
 |       "screen_drawer.cc", | 
 |       "screen_drawer.h", | 
 |     ] | 
 |  | 
 |     if (is_linux || is_chromeos) { | 
 |       sources += [ "screen_drawer_linux.cc" ] | 
 |     } | 
 |  | 
 |     if (is_mac) { | 
 |       sources += [ "screen_drawer_mac.cc" ] | 
 |     } | 
 |  | 
 |     if (is_win) { | 
 |       sources += [ "screen_drawer_win.cc" ] | 
 |     } | 
 |  | 
 |     deps = [ | 
 |       ":primitives", | 
 |       "../../api:scoped_refptr", | 
 |       "../../rtc_base:checks", | 
 |       "../../rtc_base:rtc_base_approved", | 
 |       "../../system_wrappers", | 
 |     ] | 
 |  | 
 |     if (is_posix || is_fuchsia) { | 
 |       sources += [ | 
 |         "screen_drawer_lock_posix.cc", | 
 |         "screen_drawer_lock_posix.h", | 
 |       ] | 
 |     } | 
 |   } | 
 |  | 
 |   rtc_library("desktop_capture_mock") { | 
 |     testonly = true | 
 |  | 
 |     public_deps = [ ":desktop_capture" ]  # no-presubmit-check TODO(webrtc:8603) | 
 |  | 
 |     sources = [ | 
 |       "mock_desktop_capturer_callback.cc", | 
 |       "mock_desktop_capturer_callback.h", | 
 |     ] | 
 |  | 
 |     deps = [ | 
 |       ":primitives", | 
 |       "../../rtc_base:rtc_base_approved", | 
 |       "../../test:test_support", | 
 |     ] | 
 |   } | 
 | } | 
 |  | 
 | if (is_linux || is_chromeos) { | 
 |   if (rtc_use_pipewire) { | 
 |     pkg_config("gio") { | 
 |       packages = [ | 
 |         "gio-2.0", | 
 |         "gio-unix-2.0", | 
 |       ] | 
 |     } | 
 |  | 
 |     pkg_config("pipewire") { | 
 |       packages = [ "libpipewire-0.3" ] | 
 |       if (!rtc_link_pipewire) { | 
 |         ignore_libs = true | 
 |       } | 
 |     } | 
 |  | 
 |     pkg_config("gbm") { | 
 |       packages = [ "gbm" ] | 
 |     } | 
 |     pkg_config("egl") { | 
 |       packages = [ "egl" ] | 
 |     } | 
 |     pkg_config("epoxy") { | 
 |       packages = [ "epoxy" ] | 
 |       ignore_libs = true | 
 |     } | 
 |     pkg_config("libdrm") { | 
 |       packages = [ "libdrm" ] | 
 |       if (!rtc_link_pipewire) { | 
 |         ignore_libs = true | 
 |       } | 
 |     } | 
 |  | 
 |     if (!rtc_link_pipewire) { | 
 |       # When libpipewire is not directly linked, use stubs to allow for dlopening of | 
 |       # the binary. | 
 |       generate_stubs("pipewire_stubs") { | 
 |         configs = [ | 
 |           "../../:common_config", | 
 |           ":pipewire", | 
 |           ":libdrm", | 
 |         ] | 
 |         deps = [ "../../rtc_base" ] | 
 |         extra_header = "linux/pipewire_stub_header.fragment" | 
 |         logging_function = "RTC_LOG(LS_VERBOSE)" | 
 |         logging_include = "rtc_base/logging.h" | 
 |         output_name = "linux/pipewire_stubs" | 
 |         path_from_source = "modules/desktop_capture/linux" | 
 |         sigs = [ | 
 |           "linux/pipewire.sigs", | 
 |           "linux/drm.sigs", | 
 |         ] | 
 |       } | 
 |     } | 
 |  | 
 |     config("pipewire_config") { | 
 |       defines = [ "WEBRTC_USE_PIPEWIRE" ] | 
 |       if (!rtc_link_pipewire) { | 
 |         defines += [ "WEBRTC_DLOPEN_PIPEWIRE" ] | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | rtc_source_set("desktop_capture") { | 
 |   visibility = [ "*" ] | 
 |   public_deps =  # no-presubmit-check TODO(webrtc:8603) | 
 |       [ ":desktop_capture_generic" ] | 
 |   if (is_mac) { | 
 |     public_deps += [ ":desktop_capture_objc" ] | 
 |   } | 
 | } | 
 |  | 
 | if (is_mac) { | 
 |   rtc_library("desktop_capture_objc") { | 
 |     visibility = [ ":desktop_capture" ] | 
 |     sources = [ | 
 |       "mac/desktop_configuration.mm", | 
 |       "mac/desktop_frame_cgimage.h", | 
 |       "mac/desktop_frame_cgimage.mm", | 
 |       "mac/desktop_frame_iosurface.h", | 
 |       "mac/desktop_frame_iosurface.mm", | 
 |       "mac/desktop_frame_provider.h", | 
 |       "mac/desktop_frame_provider.mm", | 
 |       "mac/screen_capturer_mac.h", | 
 |       "mac/screen_capturer_mac.mm", | 
 |       "mouse_cursor_monitor_mac.mm", | 
 |       "screen_capturer_darwin.mm", | 
 |       "window_capturer_mac.mm", | 
 |       "window_finder_mac.h", | 
 |       "window_finder_mac.mm", | 
 |     ] | 
 |     deps = [ | 
 |       ":desktop_capture_generic", | 
 |       ":primitives", | 
 |       "../../api:scoped_refptr", | 
 |       "../../rtc_base", | 
 |       "../../rtc_base:checks", | 
 |       "../../rtc_base:rtc_base_approved", | 
 |       "../../rtc_base/system:rtc_export", | 
 |       "../../sdk:helpers_objc", | 
 |     ] | 
 |     frameworks = [ | 
 |       "AppKit.framework", | 
 |       "IOKit.framework", | 
 |       "IOSurface.framework", | 
 |     ] | 
 |   } | 
 | } | 
 |  | 
 | rtc_library("desktop_capture_generic") { | 
 |   defines = [] | 
 |   public_configs = [ ":x11_config" ] | 
 |   visibility = [ | 
 |     ":desktop_capture", | 
 |     ":desktop_capture_objc", | 
 |   ] | 
 |   sources = [ | 
 |     "blank_detector_desktop_capturer_wrapper.cc", | 
 |     "blank_detector_desktop_capturer_wrapper.h", | 
 |     "cropped_desktop_frame.cc", | 
 |     "cropped_desktop_frame.h", | 
 |     "cropping_window_capturer.cc", | 
 |     "cropping_window_capturer.h", | 
 |     "desktop_and_cursor_composer.cc", | 
 |     "desktop_and_cursor_composer.h", | 
 |     "desktop_capture_metrics_helper.cc", | 
 |     "desktop_capture_metrics_helper.h", | 
 |     "desktop_capture_options.cc", | 
 |     "desktop_capture_options.h", | 
 |     "desktop_capturer.cc", | 
 |     "desktop_capturer.h", | 
 |     "desktop_capturer_differ_wrapper.cc", | 
 |     "desktop_capturer_differ_wrapper.h", | 
 |     "desktop_capturer_wrapper.cc", | 
 |     "desktop_capturer_wrapper.h", | 
 |     "desktop_frame_generator.cc", | 
 |     "desktop_frame_generator.h", | 
 |     "desktop_frame_rotation.cc", | 
 |     "desktop_frame_rotation.h", | 
 |     "differ_block.cc", | 
 |     "differ_block.h", | 
 |     "fake_desktop_capturer.cc", | 
 |     "fake_desktop_capturer.h", | 
 |     "fallback_desktop_capturer_wrapper.cc", | 
 |     "fallback_desktop_capturer_wrapper.h", | 
 |     "full_screen_application_handler.cc", | 
 |     "full_screen_application_handler.h", | 
 |     "full_screen_window_detector.cc", | 
 |     "full_screen_window_detector.h", | 
 |     "mouse_cursor.cc", | 
 |     "mouse_cursor.h", | 
 |     "mouse_cursor_monitor.h", | 
 |     "resolution_tracker.cc", | 
 |     "resolution_tracker.h", | 
 |     "rgba_color.cc", | 
 |     "rgba_color.h", | 
 |     "screen_capture_frame_queue.h", | 
 |     "screen_capturer_helper.cc", | 
 |     "screen_capturer_helper.h", | 
 |     "window_finder.cc", | 
 |     "window_finder.h", | 
 |   ] | 
 |  | 
 |   if (is_mac) { | 
 |     sources += [ | 
 |       "mac/desktop_configuration.h", | 
 |       "mac/desktop_configuration_monitor.cc", | 
 |       "mac/desktop_configuration_monitor.h", | 
 |       "mac/full_screen_mac_application_handler.cc", | 
 |       "mac/full_screen_mac_application_handler.h", | 
 |       "mac/window_list_utils.cc", | 
 |       "mac/window_list_utils.h", | 
 |     ] | 
 |   } | 
 |  | 
 |   if (build_with_mozilla) { | 
 |     sources += [ | 
 |       "desktop_device_info.cc", | 
 |       "desktop_device_info.h", | 
 |     ] | 
 |     if (is_win) { | 
 |       sources += [ | 
 |         "app_capturer_win.cc", | 
 |         "win/desktop_device_info_win.cc", | 
 |         "win/win_shared.cc", | 
 |       ] | 
 |     } | 
 |   } | 
 |  | 
 |   if (rtc_use_x11_extensions || rtc_use_pipewire) { | 
 |     sources += [ | 
 |       "mouse_cursor_monitor_linux.cc", | 
 |       "screen_capturer_linux.cc", | 
 |       "window_capturer_linux.cc", | 
 |     ] | 
 |  | 
 |     if (build_with_mozilla && (is_linux || is_chromeos)) { | 
 |       sources += [ | 
 |         "app_capturer_linux.cc", | 
 |         "linux/app_capturer_x11.cc", | 
 |         "linux/desktop_device_info_linux.cc", | 
 |         "linux/desktop_device_info_linux.h", | 
 |         "linux/shared_x_util.cc", | 
 |         "linux/shared_x_util.h", | 
 |       ] | 
 |     } | 
 |   } | 
 |  | 
 |   if (rtc_use_x11_extensions) { | 
 |     sources += [ | 
 |       "linux/mouse_cursor_monitor_x11.cc", | 
 |       "linux/mouse_cursor_monitor_x11.h", | 
 |       "linux/screen_capturer_x11.cc", | 
 |       "linux/screen_capturer_x11.h", | 
 |       "linux/shared_x_display.cc", | 
 |       "linux/shared_x_display.h", | 
 |       "linux/window_capturer_x11.cc", | 
 |       "linux/window_capturer_x11.h", | 
 |       "linux/window_finder_x11.cc", | 
 |       "linux/window_finder_x11.h", | 
 |       "linux/window_list_utils.cc", | 
 |       "linux/window_list_utils.h", | 
 |       "linux/x_atom_cache.cc", | 
 |       "linux/x_atom_cache.h", | 
 |       "linux/x_error_trap.cc", | 
 |       "linux/x_error_trap.h", | 
 |       "linux/x_server_pixel_buffer.cc", | 
 |       "linux/x_server_pixel_buffer.h", | 
 |       "linux/x_window_property.cc", | 
 |       "linux/x_window_property.h", | 
 |     ] | 
 |     libs = [ | 
 |       "X11", | 
 |       "Xcomposite", | 
 |       "Xdamage", | 
 |       "Xext", | 
 |       "Xfixes", | 
 |       "Xrender", | 
 |       "Xrandr", | 
 |       "Xtst", | 
 |     ] | 
 |   } | 
 |  | 
 |   if (!is_win && !is_mac && !rtc_use_x11_extensions && !rtc_use_pipewire) { | 
 |     sources += [ | 
 |       "mouse_cursor_monitor_null.cc", | 
 |       "screen_capturer_null.cc", | 
 |       "window_capturer_null.cc", | 
 |     ] | 
 |   } | 
 |  | 
 |   deps = [ | 
 |     ":primitives", | 
 |     "../../api:function_view", | 
 |     "../../api:refcountedbase", | 
 |     "../../api:scoped_refptr", | 
 |     "../../api:sequence_checker", | 
 |     "../../rtc_base",  # TODO(kjellander): Cleanup in bugs.webrtc.org/3806. | 
 |     "../../rtc_base:checks", | 
 |     "../../rtc_base/synchronization:mutex", | 
 |     "../../rtc_base/system:arch", | 
 |     "../../rtc_base/system:rtc_export", | 
 |     "../../system_wrappers", | 
 |     "../../system_wrappers:metrics", | 
 |   ] | 
 |  | 
 |   if (is_win) { | 
 |     sources += [ | 
 |       "cropping_window_capturer_win.cc", | 
 |       "desktop_frame_win.cc", | 
 |       "desktop_frame_win.h", | 
 |       "mouse_cursor_monitor_win.cc", | 
 |       "screen_capturer_win.cc", | 
 |       "win/cursor.cc", | 
 |       "win/cursor.h", | 
 |       "win/d3d_device.cc", | 
 |       "win/d3d_device.h", | 
 |       "win/desktop.cc", | 
 |       "win/desktop.h", | 
 |       "win/desktop_capture_utils.cc", | 
 |       "win/desktop_capture_utils.h", | 
 |       "win/display_configuration_monitor.cc", | 
 |       "win/display_configuration_monitor.h", | 
 |       "win/dxgi_adapter_duplicator.cc", | 
 |       "win/dxgi_adapter_duplicator.h", | 
 |       "win/dxgi_context.cc", | 
 |       "win/dxgi_context.h", | 
 |       "win/dxgi_duplicator_controller.cc", | 
 |       "win/dxgi_duplicator_controller.h", | 
 |       "win/dxgi_frame.cc", | 
 |       "win/dxgi_frame.h", | 
 |       "win/dxgi_output_duplicator.cc", | 
 |       "win/dxgi_output_duplicator.h", | 
 |       "win/dxgi_texture.cc", | 
 |       "win/dxgi_texture.h", | 
 |       "win/dxgi_texture_mapping.cc", | 
 |       "win/dxgi_texture_mapping.h", | 
 |       "win/dxgi_texture_staging.cc", | 
 |       "win/dxgi_texture_staging.h", | 
 |       "win/full_screen_win_application_handler.cc", | 
 |       "win/full_screen_win_application_handler.h", | 
 |       "win/scoped_gdi_object.h", | 
 |       "win/scoped_thread_desktop.cc", | 
 |       "win/scoped_thread_desktop.h", | 
 |       "win/screen_capture_utils.cc", | 
 |       "win/screen_capture_utils.h", | 
 |       "win/screen_capturer_win_directx.cc", | 
 |       "win/screen_capturer_win_directx.h", | 
 |       "win/screen_capturer_win_gdi.cc", | 
 |       "win/screen_capturer_win_gdi.h", | 
 |       "win/screen_capturer_win_magnifier.cc", | 
 |       "win/screen_capturer_win_magnifier.h", | 
 |       "win/selected_window_context.cc", | 
 |       "win/selected_window_context.h", | 
 |       "win/window_capture_utils.cc", | 
 |       "win/window_capture_utils.h", | 
 |       "win/window_capturer_win_gdi.cc", | 
 |       "win/window_capturer_win_gdi.h", | 
 |       "window_capturer_win.cc", | 
 |       "window_finder_win.cc", | 
 |       "window_finder_win.h", | 
 |     ] | 
 |     libs = [ | 
 |       "d3d11.lib", | 
 |       "dxgi.lib", | 
 |     ] | 
 |     deps += [ | 
 |       "../../rtc_base:rtc_base_approved", | 
 |       "../../rtc_base:win32", | 
 |     ] | 
 |   } | 
 |  | 
 |   absl_deps = [ | 
 |     "//third_party/abseil-cpp/absl/memory", | 
 |     "//third_party/abseil-cpp/absl/strings", | 
 |     "//third_party/abseil-cpp/absl/types:optional", | 
 |   ] | 
 |  | 
 |   if (rtc_use_x11_extensions) { | 
 |     deps += [ "../../rtc_base:sanitizer" ] | 
 |   } | 
 |  | 
 |   if (build_with_mozilla) { | 
 |     deps += [ "../../rtc_base:rtc_base_approved" ] | 
 |   } else { | 
 |     deps += [ "//third_party/libyuv" ] | 
 |   } | 
 |  | 
 |   if (use_desktop_capture_differ_sse2) { | 
 |     deps += [ ":desktop_capture_differ_sse2" ] | 
 |   } | 
 |  | 
 |   if (rtc_use_pipewire) { | 
 |     sources += [ | 
 |       "linux/base_capturer_pipewire.cc", | 
 |       "linux/base_capturer_pipewire.h", | 
 |       "linux/egl_dmabuf.cc", | 
 |       "linux/egl_dmabuf.h", | 
 |     ] | 
 |  | 
 |     configs += [ | 
 |       ":pipewire_config", | 
 |       ":gio", | 
 |       ":pipewire", | 
 |       ":gbm", | 
 |       ":egl", | 
 |       ":epoxy", | 
 |       ":libdrm", | 
 |     ] | 
 |  | 
 |     if (!rtc_link_pipewire) { | 
 |       deps += [ ":pipewire_stubs" ] | 
 |     } | 
 |  | 
 |     deps += [ "../../rtc_base:sanitizer" ] | 
 |   } | 
 |  | 
 |   if (rtc_enable_win_wgc) { | 
 |     sources += [ | 
 |       "win/wgc_capture_session.cc", | 
 |       "win/wgc_capture_session.h", | 
 |       "win/wgc_capture_source.cc", | 
 |       "win/wgc_capture_source.h", | 
 |       "win/wgc_capturer_win.cc", | 
 |       "win/wgc_capturer_win.h", | 
 |       "win/wgc_desktop_frame.cc", | 
 |       "win/wgc_desktop_frame.h", | 
 |     ] | 
 |   } | 
 | } | 
 |  | 
 | if (use_desktop_capture_differ_sse2) { | 
 |   # Have to be compiled as a separate target because it needs to be compiled | 
 |   # with SSE2 enabled. | 
 |   rtc_library("desktop_capture_differ_sse2") { | 
 |     visibility = [ ":*" ] | 
 |     sources = [ | 
 |       "differ_vector_sse2.cc", | 
 |       "differ_vector_sse2.h", | 
 |     ] | 
 |  | 
 |     if (is_posix || is_fuchsia) { | 
 |       cflags = [ "-msse2" ] | 
 |     } | 
 |   } | 
 | } |