diff --git a/CMakeLists.txt b/CMakeLists.txt index b8e5f3516..ed2cc7c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,9 +152,9 @@ int main() { find_program (XXD_CMD "xxd") find_program (PARASOL_CMD "parasol" NO_DEFAULT_PATH PATHS "${PARASOL_CMD_PATH}") -find_file (IDL_C_SCRIPT "idl-c.fluid" PATHS "${PROJECT_SOURCE_DIR}/scripts/dev/idl") -find_file (IDL_COMPILE_SCRIPT "idl-compile.fluid" PATHS "${PROJECT_SOURCE_DIR}/scripts/dev/idl") -find_file (FLUTE_SCRIPT "flute.fluid" PATHS "${PROJECT_SOURCE_DIR}/scripts/dev") +find_file (IDL_C_SCRIPT "idl-c.fluid" PATHS "${PROJECT_SOURCE_DIR}/tools/idl") +find_file (IDL_COMPILE_SCRIPT "idl-compile.fluid" PATHS "${PROJECT_SOURCE_DIR}/tools/idl") +find_file (FLUTE_SCRIPT "flute.fluid" PATHS "${PROJECT_SOURCE_DIR}/tools") if (PARASOL_CMD STREQUAL "PARASOL_CMD-NOTFOUND") message (STATUS "Definitions will not be built and tests are disabled.") @@ -171,15 +171,15 @@ if (BUILD_TESTS) endif () if (IDL_C_SCRIPT STREQUAL "IDL_C_SCRIPT-NOTFOUND") - message (FATAL_ERROR "The idl-c.fluid script was not found in ${PROJECT_SOURCE_DIR}/scripts/dev/idl") + message (FATAL_ERROR "The idl-c.fluid script was not found in ${PROJECT_SOURCE_DIR}/tools/idl") endif () if (IDL_COMPILE_SCRIPT STREQUAL "IDL_COMPILE_SCRIPT-NOTFOUND") - message (FATAL_ERROR "The idl-compile.fluid script was not found in ${PROJECT_SOURCE_DIR}/scripts/dev/idl") + message (FATAL_ERROR "The idl-compile.fluid script was not found in ${PROJECT_SOURCE_DIR}/tools/idl") endif () if (FLUTE_SCRIPT STREQUAL "FLUTE_SCRIPT-NOTFOUND") - message (FATAL_ERROR "The flute.fluid script was not found in ${PROJECT_SOURCE_DIR}/scripts/dev") + message (FATAL_ERROR "The flute.fluid script was not found in ${PROJECT_SOURCE_DIR}/tools") endif () if (NOT MSVC) diff --git a/docs/xml/modules/classes/controller.xml b/docs/xml/modules/classes/controller.xml new file mode 100644 index 000000000..4a80fe82b --- /dev/null +++ b/docs/xml/modules/classes/controller.xml @@ -0,0 +1,108 @@ + + + + + + Controller + class + Display + Provides support for reading state-based game controllers. + 1 + bf67c809 + ID_CONTROLLER + IO + modules/controller.h + Paul Manias 2003-2024 + +

Use the Controller class to read the state of game controllers that are recognised by the operating system.

+

Unlike analog devices that stream input commands (e.g. mice), gamepad controllers maintain a state that can be read at any time. The controller state is normally read at least once per frame, which can be achieved in the main inner loop, or in a separate timer.

+

Controller input management is governed by the Display class. The GRAB_CONTROLLERS flag must be defined in the active Display's Flags field in order to ensure that controller input can be received. Failure to do so may mean that the Controller object appears to work but does not receive input.

+ + class_controller.cpp + +
+ + + + Query + Get the current controller state. + ERR acQuery(*Object) + + + + + + + Buttons + JET button values expressed as bit-fields. + Read + CON + + + + + + + LeftStickX + Left analog stick value for X axis, between -1.0 and 1.0. + Read + DOUBLE + + + + LeftStickY + Left analog stick value for Y axis, between -1.0 and 1.0. + Read + DOUBLE + + + + LeftTrigger + Left trigger value between 0.0 and 1.0. + Read + DOUBLE + + + + Port + The port number assigned to the controller. + Read/Init + INT + +

Set the port number to choose the controller that will be queried for state changes. The default of zero is assigned to the primary controller.

+

The port number can be changed at any time, so multiple controllers can be queried through one interface at the cost of overwriting the previous state. Check TotalPorts if your program supports more than one controller.

+
+
+ + + RightStickX + Right analog stick value for X axis, between -1.0 and 1.0. + Read + DOUBLE + + + + RightStickY + Right analog stick value for Y axis, between -1.0 and 1.0. + Read + DOUBLE + + + + RightTrigger + Right trigger value between 0.0 and 1.0. + Read + DOUBLE + + + + TotalPorts + Reports the total number of controllers connected to the system. + Get + INT + + +
+ + +
diff --git a/docs/xml/modules/classes/display.xml b/docs/xml/modules/classes/display.xml index 4a0196988..7cd4f5bef 100644 --- a/docs/xml/modules/classes/display.xml +++ b/docs/xml/modules/classes/display.xml @@ -396,23 +396,13 @@ - - CertificationDate - String describing the date of the graphics driver's certification. - Get - STRING - -

The string in this field describes the date on which the graphics card driver was certified. If this information is not available from the driver, a NULL pointer is returned.

-
-
- Chipset String describing the graphics chipset. Get STRING -

The string in this field describes the graphic card's chipset. If this information is not retrievable, a NULL pointer is returned.

+

This string describes the graphic card's chipset, if known.

@@ -422,7 +412,7 @@ Get STRING -

The string in this field describes the display device that is connected to the user's graphics card. If this information is not detectable, a NULL pointer is returned.

+

This string describes the display device that is connected to the user's graphics card.

@@ -432,7 +422,7 @@ Get STRING -

The string in this field returns the name of the manufacturer that created the user's display device. If this information is not detectable, a NULL pointer is returned.

+

This string names the manufacturer of the user's display device.

@@ -447,36 +437,6 @@ - - DriverCopyright - String containing copyright information on the graphics driver software. - Get - STRING - -

The string in this field returns copyright information related to the graphics driver. If this information is not available, a NULL pointer is returned.

-
-
- - - DriverVendor - String describing the vendor of the graphics driver. - Get - STRING - -

The string in this field returns the name of the vendor that supplied the graphics card driver. If this information is not available, a NULL pointer is returned.

-
-
- - - DriverVersion - String describing the version of the graphics hardware driver. - Get - STRING - -

The string in this field describes the graphic driver's version number. If this information is not detectable, a NULL pointer is returned.

-
-
- Flags Optional flag settings. @@ -783,6 +743,7 @@ The display has been created with a custom window reference. Power saving through DPMS is supported. If SCR::BUFFER is used, this flag may be set by the display manager if it is possible to flip the buffer. + Grab controllers for receiving input when the display has the focus. GTF frequency timings are supported. The display is a desktop hosted window. Special win32 flag. diff --git a/docs/xml/modules/classes/surface.xml b/docs/xml/modules/classes/surface.xml index eda63c53e..75fc56bc5 100644 --- a/docs/xml/modules/classes/surface.xml +++ b/docs/xml/modules/classes/surface.xml @@ -984,36 +984,23 @@ the surface area first). The X, Y values are defined as absolute coordinates, relative to the top-left of the display. - As for ANALOG_XY, this type covers a second analog stick if present. - As for ANALOG_Z, this type covers a second analog stick if present. - Position for the default analog control (on gamepads this is the left analog control). Analog values range between -1.0 and 1.0. A value of zero indicates that the control is at rest. - 3D or yoke position for the default analog control. A negative value indicates that the control has been pulled out and a positive value indicates that it has been pushed in. - Left mouse button, XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). + Left mouse button; XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). Non-specific button assignment. - Right mouse button, XBox X button, PS cross button. - Middle mouse button, XBox Y button, PS triangle. - XBox B button, PS circle. - Left analog stick depressed. - Right analog stick depressed. + Right mouse button; XBox X button, PS cross button. + Middle mouse button; XBox Y button, PS triangle. + Alt. mouse button 1; XBox B button, PS circle. + Alt. mouse button 2. + Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. - Gamepad select button - value is 0 or 1. - Gamepad start button - value is 0 or 1. This message is sent by the input system when the mouse pointer enters an area for the first time. The message value refers to the object ID of the container being monitored for movement. This message is sent by the input system when the mouse pointer leaves an area. The message value refers to the object ID of the container being monitored for movement. Controller tilted on the X/Y axis. Value indicates angle, -ve = left, +ve = right Controller is rising or falling. Value expressed as 'speed', - Digital movement from a relative location. Value is +/- n, where n is the number of units moved horizontally. Mouse movement will normally exceed a value of 1, whereas gamepad movement is limited to a value of +/- 1 except in the case of successive presses. Recently supplied input occurred at the edge of the display. - Gamepad left-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. For pen-based input, this type indicates the vertical tilt of the pen device. A value of 0 indicates that the pen is laid flat with nib at the bottom, 0.5 is 90 degrees, 1.0 is laid flat with nib at the top. Amount of pressure applied, ranges from 0 (none) to 1.0 (normal) and possibly higher if user presses hard enough - Gamepad right-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad right-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand trigger - value is between 0 - 1.0 (0 is released, 1.0 is fully depressed). - Gamepad right-hand trigger. Mouse wheel rotation - the value generally reflects the number of 'clicks' rotated on the wheel. Some mouse wheels can be tilted to the left or right. Ranges from -1.0 to +1.0 diff --git a/docs/xml/modules/classes/vectorgradient.xml b/docs/xml/modules/classes/vectorgradient.xml index 6073e902a..938dfbe5b 100644 --- a/docs/xml/modules/classes/vectorgradient.xml +++ b/docs/xml/modules/classes/vectorgradient.xml @@ -58,18 +58,30 @@ - FX - The horizontal focal point for radial gradients. + Flags + Dimension flags are stored here. + Read/Write + VGF + +

Dimension flags that indicate whether field values are fixed or scaled are defined here.

+ +
+
+ + + FocalRadius + The size of the focal radius for radial gradients. Get/Set DOUBLE -

The (FX, FY) coordinates define the focal point for radial gradients. If left undefined, the focal point will match the center of the gradient.

+

If a radial gradient has a defined focal point (by setting FocalX and FocalY) then the FocalRadius can be used to adjust the size of the focal area. The default of zero ensures that the focal area matches that defined by Radius, which is the standard maintained by SVG.

+

The FocalRadius value has no effect if the gradient is linear.

- FY - The vertical focal point for radial gradients. + FocalX + The horizontal focal point for radial gradients. Get/Set DOUBLE @@ -78,13 +90,12 @@ - Flags - Dimension flags are stored here. - Read/Write - VGF + FocalY + The vertical focal point for radial gradients. + Get/Set + DOUBLE -

Dimension flags that indicate whether field values are fixed or scaled are defined here.

- +

The (FX, FY) coordinates define the focal point for radial gradients. If left undefined, the focal point will match the center of the gradient.

@@ -94,7 +105,7 @@ Get/Set STRING -

The ID field is provided for the purpose of SVG support. Where possible we would recommend that you use the existing object name and automatically assigned ID's for identifiers.

+

The ID field is provided for the purpose of SVG support. Where possible, we recommend that you use the existing object name and automatically assigned ID's for identifiers.

@@ -136,7 +147,7 @@ Get/Set DOUBLE -

The radius of the gradient can be defined in fixed units or scaled terms to its container. A default radius of 50% (0.5) applies if this field is not set.

+

The radius of the gradient can be defined as a fixed unit or scaled relative to its container. A default radius of 50% (0.5) applies if this field is not set.

The Radius value has no effect if the gradient is linear.

@@ -147,7 +158,7 @@ Read/Write VSPREAD -

Indicates what happens if the gradient starts or ends inside the bounds of the target vector. The default is VSPREAD::PAD.

+

Indicates what happens if the gradient starts or ends inside the bounds of the target vector. The default is VSPREAD::PAD. Other valid options for gradients are REFLECT and REPEAT.

@@ -259,15 +270,17 @@ CX is fixed CY is fixed + Focal radius is fixed FX is fixed FY is fixed - is fixed + Radius is fixed X1 is fixed X2 is fixed Y1 is fixed Y2 is fixed CX is scaled CY is scaled + Focal radius is scaled FX is scaled FY is scaled Radius is scaled diff --git a/docs/xml/modules/classes/vectorimage.xml b/docs/xml/modules/classes/vectorimage.xml index 6554a9316..bc9037bd4 100644 --- a/docs/xml/modules/classes/vectorimage.xml +++ b/docs/xml/modules/classes/vectorimage.xml @@ -41,7 +41,7 @@ Read/Set *Bitmap -

This field must be set prior to initialisation. It will refer to a source bitmap that will be used by the rendering algorithm.

+

This field must be set prior to initialisation. It will refer to a source bitmap that will be used by the rendering algorithm. The source bitmap must be in a 32-bit graphics format.

@@ -63,6 +63,7 @@ *Picture

If an image bitmap is sourced from a Picture then this field may be used to refer to the Picture object. The picture will not be used directly by the VectorImage, as only the bitmap is of interest.

+

The picture bitmap must be in a 32-bit graphics format.

diff --git a/docs/xml/modules/classes/vectorscene.xml b/docs/xml/modules/classes/vectorscene.xml index f3b889401..a96fd7ec8 100644 --- a/docs/xml/modules/classes/vectorscene.xml +++ b/docs/xml/modules/classes/vectorscene.xml @@ -15,7 +15,7 @@ Paul Manias © 2010-2024

The VectorScene class acts as a container and control point for the management of vector definitions. Its main purpose is to draw the scene to a target Bitmap or Surface provided by the client.

-

Vector scenes are created by initialising multiple Vector objects such as VectorPath and VectorViewport and positioning them within a vector tree. The VectorScene must lie at the root.

+

Vector scenes are created by initialising multiple Vector objects such as VectorPath and VectorViewport and positioning them within a vector tree. The VectorScene must lie at the root of the tree.

The default mode of operation is for scenes to be manually drawn, for which the client must set the target Bitmap and call the Draw action as required. Automated drawing can be enabled by setting the target Surface prior to initialisation. In automated mode the PageWidth and PageHeight will reflect the dimensions of the target surface at all times.

Vector definitions can be saved and loaded from permanent storage by using the SVG class.

diff --git a/docs/xml/modules/classes/xml.xml b/docs/xml/modules/classes/xml.xml index 95c382e78..3192d5a58 100644 --- a/docs/xml/modules/classes/xml.xml +++ b/docs/xml/modules/classes/xml.xml @@ -8,7 +8,7 @@ XML Provides XML data management services. *.xml - XML File + Extendable Markup Language (XML) 1 0b88bfd6 ID_XML diff --git a/docs/xml/modules/core.xml b/docs/xml/modules/core.xml index 666e47f73..4ccd1199c 100644 --- a/docs/xml/modules/core.xml +++ b/docs/xml/modules/core.xml @@ -2105,6 +2105,25 @@ SetField(Object, FID_Statement|TSTR, "string"); Removes quotes from key values that are quote-encapsulated.
+ + Directional pad down. + Directional pad left. + Directional pad right. + Directional pad up. + East button (B) + North button (Y) + South button (A) + West button (X) + Gamepad left-hand bumper 1 (top, primary). + Gamepad left-hand bumper 2 (lower). + Left thumb stick depressed. + Gamepad right-hand bumper 1 (top, primary). + Gamepad right-hand bumper 2 (lower). + Right thumb stick depressed. + Gamepad select or back button. + Gamepad start button. + + Audio file data, recognised by the Sound class Document content (between XML tags) - sent by document objects only @@ -2333,36 +2352,23 @@ SetField(Object, FID_Statement|TSTR, "string"); The X, Y values are defined as absolute coordinates, relative to the top-left of the display. - As for ANALOG_XY, this type covers a second analog stick if present. - As for ANALOG_Z, this type covers a second analog stick if present. - Position for the default analog control (on gamepads this is the left analog control). Analog values range between -1.0 and 1.0. A value of zero indicates that the control is at rest. - 3D or yoke position for the default analog control. A negative value indicates that the control has been pulled out and a positive value indicates that it has been pushed in. - Left mouse button, XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). + Left mouse button; XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). Non-specific button assignment. - Right mouse button, XBox X button, PS cross button. - Middle mouse button, XBox Y button, PS triangle. - XBox B button, PS circle. - Left analog stick depressed. - Right analog stick depressed. + Right mouse button; XBox X button, PS cross button. + Middle mouse button; XBox Y button, PS triangle. + Alt. mouse button 1; XBox B button, PS circle. + Alt. mouse button 2. + Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. - Gamepad select button - value is 0 or 1. - Gamepad start button - value is 0 or 1. This message is sent by the input system when the mouse pointer enters an area for the first time. The message value refers to the object ID of the container being monitored for movement. This message is sent by the input system when the mouse pointer leaves an area. The message value refers to the object ID of the container being monitored for movement. Controller tilted on the X/Y axis. Value indicates angle, -ve = left, +ve = right Controller is rising or falling. Value expressed as 'speed', - Digital movement from a relative location. Value is +/- n, where n is the number of units moved horizontally. Mouse movement will normally exceed a value of 1, whereas gamepad movement is limited to a value of +/- 1 except in the case of successive presses. Recently supplied input occurred at the edge of the display. - Gamepad left-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. For pen-based input, this type indicates the vertical tilt of the pen device. A value of 0 indicates that the pen is laid flat with nib at the bottom, 0.5 is 90 degrees, 1.0 is laid flat with nib at the top. Amount of pressure applied, ranges from 0 (none) to 1.0 (normal) and possibly higher if user presses hard enough - Gamepad right-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad right-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand trigger - value is between 0 - 1.0 (0 is released, 1.0 is fully depressed). - Gamepad right-hand trigger. Mouse wheel rotation - the value generally reflects the number of 'clicks' rotated on the wheel. Some mouse wheels can be tilted to the left or right. Ranges from -1.0 to +1.0 diff --git a/docs/xml/modules/display.xml b/docs/xml/modules/display.xml index 28c4b6457..8b7c2503c 100644 --- a/docs/xml/modules/display.xml +++ b/docs/xml/modules/display.xml @@ -12,6 +12,7 @@ Bitmap Clipboard + Controller Display Pointer Surface @@ -1091,36 +1092,23 @@ Alpha = CFUnpackAlpha(Format,Colour) The X, Y values are defined as absolute coordinates, relative to the top-left of the display. - As for ANALOG_XY, this type covers a second analog stick if present. - As for ANALOG_Z, this type covers a second analog stick if present. - Position for the default analog control (on gamepads this is the left analog control). Analog values range between -1.0 and 1.0. A value of zero indicates that the control is at rest. - 3D or yoke position for the default analog control. A negative value indicates that the control has been pulled out and a positive value indicates that it has been pushed in. - Left mouse button, XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). + Left mouse button; XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed). Non-specific button assignment. - Right mouse button, XBox X button, PS cross button. - Middle mouse button, XBox Y button, PS triangle. - XBox B button, PS circle. - Left analog stick depressed. - Right analog stick depressed. + Right mouse button; XBox X button, PS cross button. + Middle mouse button; XBox Y button, PS triangle. + Alt. mouse button 1; XBox B button, PS circle. + Alt. mouse button 2. + Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. Non-specific button assignment. - Gamepad select button - value is 0 or 1. - Gamepad start button - value is 0 or 1. This message is sent by the input system when the mouse pointer enters an area for the first time. The message value refers to the object ID of the container being monitored for movement. This message is sent by the input system when the mouse pointer leaves an area. The message value refers to the object ID of the container being monitored for movement. Controller tilted on the X/Y axis. Value indicates angle, -ve = left, +ve = right Controller is rising or falling. Value expressed as 'speed', - Digital movement from a relative location. Value is +/- n, where n is the number of units moved horizontally. Mouse movement will normally exceed a value of 1, whereas gamepad movement is limited to a value of +/- 1 except in the case of successive presses. Recently supplied input occurred at the edge of the display. - Gamepad left-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. For pen-based input, this type indicates the vertical tilt of the pen device. A value of 0 indicates that the pen is laid flat with nib at the bottom, 0.5 is 90 degrees, 1.0 is laid flat with nib at the top. Amount of pressure applied, ranges from 0 (none) to 1.0 (normal) and possibly higher if user presses hard enough - Gamepad right-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0. - Gamepad right-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0. - Gamepad left-hand trigger - value is between 0 - 1.0 (0 is released, 1.0 is fully depressed). - Gamepad right-hand trigger. Mouse wheel rotation - the value generally reflects the number of 'clicks' rotated on the wheel. Some mouse wheels can be tilted to the left or right. Ranges from -1.0 to +1.0 @@ -1231,6 +1219,7 @@ Alpha = CFUnpackAlpha(Format,Colour) The display has been created with a custom window reference. Power saving through DPMS is supported. If SCR::BUFFER is used, this flag may be set by the display manager if it is possible to flip the buffer. + Grab controllers for receiving input when the display has the focus. GTF frequency timings are supported. The display is a desktop hosted window. Special win32 flag. diff --git a/docs/xml/modules/vector.xml b/docs/xml/modules/vector.xml index 2a2c3b938..72a29536f 100644 --- a/docs/xml/modules/vector.xml +++ b/docs/xml/modules/vector.xml @@ -810,15 +810,17 @@ Z: Close Path CX is fixed CY is fixed + Focal radius is fixed FX is fixed FY is fixed - is fixed + Radius is fixed X1 is fixed X2 is fixed Y1 is fixed Y2 is fixed CX is scaled CY is scaled + Focal radius is scaled FX is scaled FY is scaled Radius is scaled diff --git a/examples/data/football.svg b/examples/data/football.svg new file mode 100644 index 000000000..790e92869 --- /dev/null +++ b/examples/data/football.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/gamepad.fluid b/examples/gamepad.fluid new file mode 100644 index 000000000..6112dc393 --- /dev/null +++ b/examples/gamepad.fluid @@ -0,0 +1,59 @@ +--[[ +Gamepad demonstration +--]] + + require 'gui/window' + + glSelf = obj.find('self') + glPath = glSelf.workingPath + + local win = gui.window({ title='Gamepad Demo', insideWidth=600, insideHeight=400, center=true, enableControllers=true }) + local viewport = win:clientViewport({ aspectRatio = ARF_MEET }) + + local text = viewport.new('vectortext', { + x=win.margins.left, y=20, string='Use a gamepad to control the football.', face='Noto Sans', fontSize=20, fill='rgb(0,0,0)' + }) + + local txtLeftStick = viewport.new('vectortext', { + x=win.margins.left, y=50, string='Left Stick:', face='Noto Sans', fontSize=20, fill='rgb(0,0,0)' + }) + + local txtRightStick = viewport.new('vectortext', { + x=win.margins.left, y=80, string='Right Stick:', face='Noto Sans', fontSize=20, fill='rgb(0,0,0)' + }) + + local txtButtons = viewport.new('vectortext', { + x=win.margins.left, y=110, string='Buttons:', face='Noto Sans', fontSize=20, fill='rgb(0,0,0)' + }) + + local ballVP = viewport.new('VectorViewport', { + x = 260, y = 260, width = 60, height = 60 + }) + + local svg = obj.new('svg', { target=ballVP, path=glPath .. 'data/football.svg' }) + + local MAX_SPEED = 3 + local ctrl = obj.new('controller', { port=0 }) + local err, controllerTimer = mSys.SubscribeTimer(1/60, function(Subscriber, Elapsed, CurrentTime) + ctrl.acQuery() + + txtLeftStick.string = 'Left Stick: ' .. string.format('%.2f %.2f', ctrl.leftStickX, ctrl.leftStickY) + txtRightStick.string = 'Right Stick: ' .. string.format('%.2f %.2f', ctrl.rightStickX, ctrl.rightStickY) + txtButtons.string = 'Buttons: ' .. string.format('%.8x', ctrl.buttons) + + local speed = MAX_SPEED + if bit.band(ctrl.buttons, CON_GAMEPAD_S) != 0 then + speed = speed * 2 + end + + ballVP.x = ballVP.x + (ctrl.leftStickX * speed) + ballVP.y = ballVP.y - (ctrl.leftStickY * speed) + + ballVP.width = ballVP.width + ctrl.rightStickY + ballVP.height = ballVP.height + ctrl.rightStickY + + viewport.scene.surface.mtScheduleRedraw() + end) + + win:show() + processing.sleep() diff --git a/examples/gradients.fluid b/examples/gradients.fluid new file mode 100644 index 000000000..07343760e --- /dev/null +++ b/examples/gradients.fluid @@ -0,0 +1,146 @@ +--[[ +Gradient Demonstration + +This is a replica of an AGG demo that was originally built to test focal gradient capabilities. +--]] + + require 'gui/window' + require 'gui/combobox' + + local win, viewport, gradient, gradientVP + local adjust_focal = true, focal_ellipse + +---------------------------------------------------------------------------------------------------------------------- + +function buildScene() + local colours = { { offset=0, r=0, g=255, b=0 }, { offset=0.2, r=120, g=0, b=0 }, { offset=0.7, r=120, g=120, b=0 }, { offset=1, r=0, g=0, b=255 } } + local stops = { } + for _, col in pairs(colours) do + local vc = struct.new('GradientStop') + vc.offset = col.offset + vc.rgb.red = col.r / 255 + vc.rgb.green = col.g / 255 + vc.rgb.blue = col.b / 255 + vc.rgb.alpha = 1.0 + table.insert(stops, vc) + end + + gradient = viewport.scene.new('VectorGradient', { + name = 'focal', type = 'radial', stops = stops, + cX = '50%', cY = '50%', + fX = '50%', fY = '50%', focalRadius = 100, + units = 'boundingbox', radius = 100, + spreadMethod = 'reflect' + }) + + viewport.scene.mtAddDef('focal', gradient) + + gradientVP = viewport.new('VectorViewport', { x = 0, y = 20, width = '100%', height='100%' }) + local rect = gradientVP.new('VectorRectangle', { x = 0, y = 0, width='100%', height='100%', fill='url(#focal)' }) + focal_ellipse = gradientVP.new('VectorEllipse', { + cx ='50%', cy='50%', radius=100, stroke='rgb(255,255,255)', strokeWidth=1 + }) + + local cmbGradient = gui.combobox({ + target = viewport, + label = 'Gradient:', + text = 'Radial', + x = win.margins.left, + y = 10, + items = { + { item='Radial' }, + { item='Conic' }, + { item='Diamond' }, + { item='Contour' } + }, + events = { + activate = function(Widget, Text) + if Text == 'Radial' then + gradient.type = 'radial' + focal_ellipse.visibility = 'visible' + adjust_focal = true + gradient.cX = '50%' + gradient.cY = '50%' + elseif Text == 'Conic' then + focal_ellipse.visibility = 'hidden' + gradient.type = 'conic' + adjust_focal = false + elseif Text == 'Diamond' then + focal_ellipse.visibility = 'hidden' + gradient.type = 'diamond' + adjust_focal = false + elseif Text == 'Contour' then + focal_ellipse.visibility = 'hidden' + gradient.type = 'contour' + adjust_focal = false + end + gradientVP.scene.surface.mtScheduleRedraw() + end + } + }) + + local cmbSpread = gui.combobox({ + target = viewport, + label = 'Spread Method:', + text = 'Reflect', + x = cmbGradient.viewport.x + cmbGradient.viewport.width + 10, + y = 10, + items = { { item='Pad' }, { item='Repeat' }, { item='Reflect' } }, + events = { + activate = function(Widget, Text) + if Text == 'Pad' then + gradient.spreadMethod = VSPREAD_PAD + elseif Text == 'Reflect' then + gradient.spreadMethod = VSPREAD_REFLECT + elseif Text == 'Repeat' then + gradient.spreadMethod = VSPREAD_REPEAT + end + gradientVP.scene.surface.mtScheduleRedraw() + end + } + }) + + gradientVP.y = cmbGradient.viewport.y + cmbGradient.viewport.height + 12 +end + +---------------------------------------------------------------------------------------------------------------------- + + win = gui.window({ title='Focal Gradient Demo', insideWidth=1024, insideHeight=800, center=true }) + viewport = win:clientViewport({ + aspectRatio = ARF_MEET + }) + + buildScene() + + local button_held = false + check(gradientVP.mtSubscribeInput(bit.bor(JTYPE_MOVEMENT, JTYPE_BUTTON, JTYPE_REPEATED), function(Viewport, Events) + local ev = Events + while ev do + if (ev.type == JET_ABS_XY) then + if button_held == 1 then + if adjust_focal then + gradient.fX = (ev.x / gradientVP.width * 100) .. '%' + gradient.fY = (ev.y / gradientVP.height * 100) .. '%' + else + gradient.cX = (ev.x / gradientVP.width * 100) .. '%' + gradient.cY = (ev.y / gradientVP.height * 100) .. '%' + end + gradientVP.scene.surface.mtScheduleRedraw() + end + elseif (ev.type == JET_BUTTON_1) then -- LMB + button_held = ev.value + if adjust_focal then + gradient.fX = (ev.x / gradientVP.width * 100) .. '%' + gradient.fY = (ev.y / gradientVP.height * 100) .. '%' + else + gradient.cX = (ev.x / gradientVP.width * 100) .. '%' + gradient.cY = (ev.y / gradientVP.height * 100) .. '%' + end + gradientVP.scene.surface.mtScheduleRedraw() + end + ev = ev.next + end + end)) + + win:show() + processing.sleep() diff --git a/include/parasol/modules/core.h b/include/parasol/modules/core.h index 62c45addf..585ff6dc1 100644 --- a/include/parasol/modules/core.h +++ b/include/parasol/modules/core.h @@ -347,47 +347,58 @@ enum class JTYPE : ULONG { DEFINE_ENUM_FLAG_OPERATORS(JTYPE) +// Gamepad controller buttons. + +enum class CON : ULONG { + NIL = 0, + GAMEPAD_S = 0x00000001, + GAMEPAD_E = 0x00000002, + GAMEPAD_W = 0x00000004, + GAMEPAD_N = 0x00000008, + DPAD_UP = 0x00000010, + DPAD_DOWN = 0x00000020, + DPAD_LEFT = 0x00000040, + DPAD_RIGHT = 0x00000080, + START = 0x00000100, + SELECT = 0x00000200, + LEFT_BUMPER_1 = 0x00000400, + LEFT_BUMPER_2 = 0x00000800, + RIGHT_BUMPER_1 = 0x00001000, + RIGHT_BUMPER_2 = 0x00002000, + LEFT_THUMB = 0x00004000, + RIGHT_THUMB = 0x00008000, +}; + +DEFINE_ENUM_FLAG_OPERATORS(CON) + // JET constants are documented in GetInputEvent() enum class JET : LONG { NIL = 0, - DIGITAL_XY = 1, - BUTTON_1 = 2, - LMB = 2, - BUTTON_2 = 3, - RMB = 3, - BUTTON_3 = 4, - MMB = 4, - BUTTON_4 = 5, - BUTTON_5 = 6, - BUTTON_6 = 7, - BUTTON_7 = 8, - BUTTON_8 = 9, - BUTTON_9 = 10, - BUTTON_10 = 11, - TRIGGER_LEFT = 12, - TRIGGER_RIGHT = 13, - BUTTON_START = 14, - BUTTON_SELECT = 15, - LEFT_BUMPER_1 = 16, - LEFT_BUMPER_2 = 17, - RIGHT_BUMPER_1 = 18, - RIGHT_BUMPER_2 = 19, - ANALOG_XY = 20, - ANALOG_Z = 21, - ANALOG2_XY = 22, - ANALOG2_Z = 23, - WHEEL = 24, - WHEEL_TILT = 25, - PEN_TILT_XY = 26, - ABS_XY = 27, - CROSSED_IN = 28, - CROSSED_OUT = 29, - PRESSURE = 30, - DEVICE_TILT_XY = 31, - DEVICE_TILT_Z = 32, - DISPLAY_EDGE = 33, - END = 34, + BUTTON_1 = 1, + LMB = 1, + BUTTON_2 = 2, + RMB = 2, + BUTTON_3 = 3, + MMB = 3, + BUTTON_4 = 4, + BUTTON_5 = 5, + BUTTON_6 = 6, + BUTTON_7 = 7, + BUTTON_8 = 8, + BUTTON_9 = 9, + BUTTON_10 = 10, + WHEEL = 11, + WHEEL_TILT = 12, + PEN_TILT_XY = 13, + ABS_XY = 14, + CROSSED_IN = 15, + CROSSED_OUT = 16, + PRESSURE = 17, + DEVICE_TILT_XY = 18, + DEVICE_TILT_Z = 19, + DISPLAY_EDGE = 20, + END = 21, }; // Field descriptors. diff --git a/include/parasol/modules/display.h b/include/parasol/modules/display.h index 5b20276e3..5a4df4bce 100644 --- a/include/parasol/modules/display.h +++ b/include/parasol/modules/display.h @@ -18,6 +18,7 @@ class objBitmap; class objDisplay; class objClipboard; +class objController; class objPointer; class objSurface; @@ -282,6 +283,7 @@ enum class SCR : ULONG { BORDERLESS = 0x00000020, COMPOSITE = 0x00000040, ALPHA_BLEND = 0x00000040, + GRAB_CONTROLLERS = 0x00000080, MAXSIZE = 0x00100000, REFRESH = 0x00200000, HOSTED = 0x02000000, @@ -1009,7 +1011,7 @@ class objDisplay : public Object { inline ERR setRefreshRate(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[43]; + auto field = &this->Class->Dictionary[39]; return field->WriteValue(target, field, FD_DOUBLE, &Value, 1); } @@ -1060,7 +1062,7 @@ class objDisplay : public Object { inline ERR setPopOver(OBJECTID Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[27]; + auto field = &this->Class->Dictionary[25]; return field->WriteValue(target, field, FD_LONG, &Value, 1); } @@ -1072,25 +1074,25 @@ class objDisplay : public Object { inline ERR setHDensity(const LONG Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[17]; + auto field = &this->Class->Dictionary[16]; return field->WriteValue(target, field, FD_LONG, &Value, 1); } inline ERR setVDensity(const LONG Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[15]; + auto field = &this->Class->Dictionary[14]; return field->WriteValue(target, field, FD_LONG, &Value, 1); } inline ERR setOpacity(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[16]; + auto field = &this->Class->Dictionary[15]; return field->WriteValue(target, field, FD_DOUBLE, &Value, 1); } inline ERR setResizeFeedback(const FUNCTION Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[32]; + auto field = &this->Class->Dictionary[29]; return field->WriteValue(target, field, FD_FUNCTION, &Value, 1); } @@ -1185,6 +1187,41 @@ class objClipboard : public Object { }; +// Controller class definition + +#define VER_CONTROLLER (1.000000) + +class objController : public Object { + public: + static constexpr CLASSID CLASS_ID = CLASSID::CONTROLLER; + static constexpr CSTRING CLASS_NAME = "Controller"; + + using create = pf::Create; + + DOUBLE LeftTrigger; // Left trigger value between 0.0 and 1.0. + DOUBLE RightTrigger; // Right trigger value between 0.0 and 1.0. + DOUBLE LeftStickX; // Left analog stick value for X axis, between -1.0 and 1.0. + DOUBLE LeftStickY; // Left analog stick value for Y axis, between -1.0 and 1.0. + DOUBLE RightStickX; // Right analog stick value for X axis, between -1.0 and 1.0. + DOUBLE RightStickY; // Right analog stick value for Y axis, between -1.0 and 1.0. + CON Buttons; // JET button values expressed as bit-fields. + LONG Port; // The port number assigned to the controller. + + // Action stubs + + inline ERR query() noexcept { return Action(AC::Query, this, NULL); } + inline ERR init() noexcept { return InitObject(this); } + + // Customised field setting + + inline ERR setPort(const LONG Value) noexcept { + if (this->initialised()) return ERR::NoFieldAccess; + this->Port = Value; + return ERR::Okay; + } + +}; + // Pointer class definition #define VER_POINTER (1.000000) diff --git a/include/parasol/modules/vector.h b/include/parasol/modules/vector.h index 6618f44dd..1db159ad3 100644 --- a/include/parasol/modules/vector.h +++ b/include/parasol/modules/vector.h @@ -401,15 +401,17 @@ enum class VGF : ULONG { SCALED_FX = 0x00000040, SCALED_FY = 0x00000080, SCALED_RADIUS = 0x00000100, - FIXED_X1 = 0x00000200, - FIXED_Y1 = 0x00000400, - FIXED_X2 = 0x00000800, - FIXED_Y2 = 0x00001000, - FIXED_CX = 0x00002000, - FIXED_CY = 0x00004000, - FIXED_FX = 0x00008000, - FIXED_FY = 0x00010000, - FIXED_RADIUS = 0x00020000, + SCALED_FOCAL_RADIUS = 0x00000200, + FIXED_X1 = 0x00000400, + FIXED_Y1 = 0x00000800, + FIXED_X2 = 0x00001000, + FIXED_Y2 = 0x00002000, + FIXED_CX = 0x00004000, + FIXED_CY = 0x00008000, + FIXED_FX = 0x00010000, + FIXED_FY = 0x00020000, + FIXED_RADIUS = 0x00040000, + FIXED_FOCAL_RADIUS = 0x00080000, }; DEFINE_ENUM_FLAG_OPERATORS(VGF) @@ -941,9 +943,10 @@ class objVectorGradient : public Object { DOUBLE Y2; // Final Y coordinate for the gradient. DOUBLE CenterX; // The horizontal center point of the gradient. DOUBLE CenterY; // The vertical center point of the gradient. - DOUBLE FX; // The horizontal focal point for radial gradients. - DOUBLE FY; // The vertical focal point for radial gradients. + DOUBLE FocalX; // The horizontal focal point for radial gradients. + DOUBLE FocalY; // The vertical focal point for radial gradients. DOUBLE Radius; // The radius of the gradient. + DOUBLE FocalRadius; // The size of the focal radius for radial gradients. objVectorGradient * Inherit; // Inherit attributes from the VectorGradient referenced here. VSPREAD SpreadMethod; // The behaviour to use when the gradient bounds do not match the vector path. VUNIT Units; // Defines the coordinate system for X1, Y1, X2 and Y2. @@ -960,70 +963,77 @@ class objVectorGradient : public Object { inline ERR setX1(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[3]; + auto field = &this->Class->Dictionary[5]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setY1(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[5]; + auto field = &this->Class->Dictionary[7]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setX2(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[4]; + auto field = &this->Class->Dictionary[6]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setY2(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[6]; + auto field = &this->Class->Dictionary[8]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setCenterX(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[21]; + auto field = &this->Class->Dictionary[23]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setCenterY(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[22]; + auto field = &this->Class->Dictionary[24]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } - inline ERR setFX(const DOUBLE Value) noexcept { + inline ERR setFocalX(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[0]; + auto field = &this->Class->Dictionary[28]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } - inline ERR setFY(const DOUBLE Value) noexcept { + inline ERR setFocalY(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[1]; + auto field = &this->Class->Dictionary[29]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setRadius(const DOUBLE Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[14]; + auto field = &this->Class->Dictionary[16]; + Unit var(Value); + return field->WriteValue(target, field, FD_UNIT, &var, 1); + } + + inline ERR setFocalRadius(const DOUBLE Value) noexcept { + auto target = this; + auto field = &this->Class->Dictionary[27]; Unit var(Value); return field->WriteValue(target, field, FD_UNIT, &var, 1); } inline ERR setInherit(objVectorGradient * Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[19]; + auto field = &this->Class->Dictionary[21]; return field->WriteValue(target, field, 0x08000301, Value, 1); } @@ -1057,31 +1067,31 @@ class objVectorGradient : public Object { inline ERR setMatrices(APTR Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[16]; + auto field = &this->Class->Dictionary[18]; return field->WriteValue(target, field, 0x08000318, Value, 1); } inline ERR setNumeric(const LONG Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[20]; + auto field = &this->Class->Dictionary[22]; return field->WriteValue(target, field, FD_LONG, &Value, 1); } template inline ERR setID(T && Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[2]; + auto field = &this->Class->Dictionary[4]; return field->WriteValue(target, field, 0x08800308, to_cstring(Value), 1); } inline ERR setStops(const APTR Value, LONG Elements) noexcept { auto target = this; - auto field = &this->Class->Dictionary[11]; + auto field = &this->Class->Dictionary[13]; return field->WriteValue(target, field, 0x00001318, Value, Elements); } template inline ERR setTransform(T && Value) noexcept { auto target = this; - auto field = &this->Class->Dictionary[15]; + auto field = &this->Class->Dictionary[17]; return field->WriteValue(target, field, 0x08800208, to_cstring(Value), 1); } diff --git a/include/parasol/system/registry.h b/include/parasol/system/registry.h index 4a6b68dfd..33694fdf3 100644 --- a/include/parasol/system/registry.h +++ b/include/parasol/system/registry.h @@ -108,5 +108,6 @@ enum class CLASSID : ULONG { SPOTLIGHTFX = 0x9e7a51c1UL, SOURCEFX = 0x16f8c294UL, FILTEREFFECT = 0x79e93e58UL, + CONTROLLER = 0xbf67c809UL, }; diff --git a/scripts/gui/combobox.fluid b/scripts/gui/combobox.fluid index f549013e8..449da7bed 100644 --- a/scripts/gui/combobox.fluid +++ b/scripts/gui/combobox.fluid @@ -162,7 +162,7 @@ gui.combobox = function(Options) }) local defaultText = Options.text - if not Options.allowCustom then + if not Options.allowCustom and not defaultText then defaultText = Options.items[1].item end diff --git a/scripts/gui/window.fluid b/scripts/gui/window.fluid index 828b5d6f8..5b78586ad 100644 --- a/scripts/gui/window.fluid +++ b/scripts/gui/window.fluid @@ -199,7 +199,7 @@ gui.window = function(Options) self.maximise = function(self, Toggle) if not self.maximiseEnabled then - msg("Maximisation for this window is turned off.") + msg('Maximisation for this window is turned off.') return end @@ -301,10 +301,10 @@ gui.window = function(Options) -- Main entry point -- - self._desktop = obj.find("desktop") + self._desktop = obj.find('desktop') self.surface = obj.new('surface', { - name = "winsurface", + name = 'winsurface', parent = self._desktop, width = nz(Options.width, DEFAULT_WIDTH), height = nz(Options.height, DEFAULT_HEIGHT), @@ -334,6 +334,10 @@ gui.window = function(Options) end)() }) + if Options.enableControllers then + self.surface.display.flags = bit.bor(self.surface.display.flags, SCR_GRAB_CONTROLLERS) + end + if Options.x then self.surface.x = Options.x else diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aa527aa19..1d28f92ef 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -58,7 +58,7 @@ if (BUILD_DEFS) "${CMAKE_CURRENT_SOURCE_DIR}/defs/errors.fdl" "${CMAKE_CURRENT_SOURCE_DIR}/defs/registry.fdl" "${CMAKE_CURRENT_SOURCE_DIR}/defs/fields.fdl" - "${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/dev/idl/common.fdl" + "${CMAKE_CURRENT_SOURCE_DIR}/../../tools/idl/common.fdl" ${FUNCTIONS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Producing definition files for the Core library" @@ -74,7 +74,7 @@ if (BUILD_DEFS) "${CMAKE_CURRENT_SOURCE_DIR}/defs/errors.fdl" "${CMAKE_CURRENT_SOURCE_DIR}/defs/registry.fdl" "${CMAKE_CURRENT_SOURCE_DIR}/defs/fields.fdl" - "${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/dev/idl/common.fdl") + "${CMAKE_CURRENT_SOURCE_DIR}/../../tools/idl/common.fdl") add_dependencies (build_headers core_defs) endif () diff --git a/src/core/defs/registry.fdl b/src/core/defs/registry.fdl index 727d251ec..dc1048509 100644 --- a/src/core/defs/registry.fdl +++ b/src/core/defs/registry.fdl @@ -104,5 +104,6 @@ header({ path="system/registry", copyright="Paul Manias 1996-2024" }, function() "REMAPFX", "SPOTLIGHTFX", "SOURCEFX", - "FILTEREFFECT") + "FILTEREFFECT", + "CONTROLLER") end) diff --git a/src/core/idl.h b/src/core/idl.h index 4648f3012..75e136836 100644 --- a/src/core/idl.h +++ b/src/core/idl.h @@ -1 +1 @@ -char glIDL[] = { 115,46,73,110,112,117,116,69,118,101,110,116,58,112,78,101,120,116,58,73,110,112,117,116,69,118,101,110,116,44,100,86,97,108,117,101,44,120,84,105,109,101,115,116,97,109,112,44,108,82,101,99,105,112,105,101,110,116,73,68,44,108,79,118,101,114,73,68,44,100,65,98,115,88,44,100,65,98,115,89,44,100,88,44,100,89,44,108,68,101,118,105,99,101,73,68,44,108,84,121,112,101,44,108,70,108,97,103,115,44,108,77,97,115,107,10,115,46,100,99,82,101,113,117,101,115,116,58,108,73,116,101,109,44,99,80,114,101,102,101,114,101,110,99,101,91,52,93,10,115,46,100,99,65,117,100,105,111,58,108,83,105,122,101,44,108,70,111,114,109,97,116,10,115,46,100,99,75,101,121,69,110,116,114,121,58,108,70,108,97,103,115,44,108,86,97,108,117,101,44,120,84,105,109,101,115,116,97,109,112,44,108,85,110,105,99,111,100,101,10,115,46,100,99,68,101,118,105,99,101,73,110,112,117,116,58,100,86,97,108,117,101,115,91,50,93,44,120,84,105,109,101,115,116,97,109,112,44,108,68,101,118,105,99,101,73,68,44,108,70,108,97,103,115,44,108,84,121,112,101,10,115,46,68,97,116,101,84,105,109,101,58,119,89,101,97,114,44,99,77,111,110,116,104,44,99,68,97,121,44,99,72,111,117,114,44,99,77,105,110,117,116,101,44,99,83,101,99,111,110,100,44,99,84,105,109,101,90,111,110,101,10,115,46,72,83,86,58,100,72,117,101,44,100,83,97,116,117,114,97,116,105,111,110,44,100,86,97,108,117,101,44,100,65,108,112,104,97,10,115,46,70,82,71,66,58,102,82,101,100,44,102,71,114,101,101,110,44,102,66,108,117,101,44,102,65,108,112,104,97,10,115,46,82,71,66,56,58,117,99,82,101,100,44,117,99,71,114,101,101,110,44,117,99,66,108,117,101,44,117,99,65,108,112,104,97,10,115,46,82,71,66,49,54,58,117,119,82,101,100,44,117,119,71,114,101,101,110,44,117,119,66,108,117,101,44,117,119,65,108,112,104,97,10,115,46,82,71,66,51,50,58,117,108,82,101,100,44,117,108,71,114,101,101,110,44,117,108,66,108,117,101,44,117,108,65,108,112,104,97,10,115,46,82,71,66,80,97,108,101,116,116,101,58,108,65,109,116,67,111,108,111,117,114,115,44,101,67,111,108,58,82,71,66,56,91,50,53,54,93,10,115,46,67,111,108,111,117,114,70,111,114,109,97,116,58,117,99,82,101,100,83,104,105,102,116,44,117,99,71,114,101,101,110,83,104,105,102,116,44,117,99,66,108,117,101,83,104,105,102,116,44,117,99,65,108,112,104,97,83,104,105,102,116,44,117,99,82,101,100,77,97,115,107,44,117,99,71,114,101,101,110,77,97,115,107,44,117,99,66,108,117,101,77,97,115,107,44,117,99,65,108,112,104,97,77,97,115,107,44,117,99,82,101,100,80,111,115,44,117,99,71,114,101,101,110,80,111,115,44,117,99,66,108,117,101,80,111,115,44,117,99,65,108,112,104,97,80,111,115,44,117,99,66,105,116,115,80,101,114,80,105,120,101,108,10,115,46,67,108,105,112,82,101,99,116,97,110,103,108,101,58,108,76,101,102,116,44,108,84,111,112,44,108,82,105,103,104,116,44,108,66,111,116,116,111,109,10,115,46,69,100,103,101,115,58,108,76,101,102,116,44,108,84,111,112,44,108,82,105,103,104,116,44,108,66,111,116,116,111,109,10,115,46,79,98,106,101,99,116,83,105,103,110,97,108,58,111,79,98,106,101,99,116,10,115,46,70,117,110,99,116,105,111,110,70,105,101,108,100,58,115,78,97,109,101,44,117,108,84,121,112,101,10,115,46,70,117,110,99,116,105,111,110,58,112,65,100,100,114,101,115,115,44,115,78,97,109,101,44,112,65,114,103,115,58,70,117,110,99,116,105,111,110,70,105,101,108,100,10,115,46,70,105,101,108,100,65,114,114,97,121,58,115,78,97,109,101,44,112,71,101,116,70,105,101,108,100,44,112,83,101,116,70,105,101,108,100,44,109,65,114,103,44,117,108,70,108,97,103,115,10,115,46,70,105,101,108,100,68,101,102,58,115,78,97,109,101,44,108,86,97,108,117,101,10,115,46,83,121,115,116,101,109,83,116,97,116,101,58,115,80,108,97,116,102,111,114,109,44,108,67,111,110,115,111,108,101,70,68,44,108,83,116,97,103,101,10,115,46,85,110,105,116,58,100,86,97,108,117,101,44,117,108,84,121,112,101,10,115,46,65,99,116,105,111,110,65,114,114,97,121,58,112,82,111,117,116,105,110,101,44,108,65,99,116,105,111,110,67,111,100,101,10,115,46,65,99,116,105,111,110,84,97,98,108,101,58,117,108,72,97,115,104,44,108,83,105,122,101,44,115,78,97,109,101,44,112,65,114,103,115,58,70,117,110,99,116,105,111,110,70,105,101,108,100,10,115,46,67,104,105,108,100,69,110,116,114,121,58,108,79,98,106,101,99,116,73,68,44,117,108,67,108,97,115,115,73,68,10,115,46,77,101,115,115,97,103,101,58,120,84,105,109,101,44,108,85,73,68,44,108,84,121,112,101,44,108,83,105,122,101,10,115,46,77,101,109,73,110,102,111,58,112,83,116,97,114,116,44,108,79,98,106,101,99,116,73,68,44,117,108,83,105,122,101,44,108,70,108,97,103,115,44,108,77,101,109,111,114,121,73,68,44,119,65,99,99,101,115,115,67,111,117,110,116,10,115,46,67,111,109,112,114,101,115,115,105,111,110,70,101,101,100,98,97,99,107,58,108,70,101,101,100,98,97,99,107,73,68,44,108,73,110,100,101,120,44,115,80,97,116,104,44,115,68,101,115,116,44,120,80,114,111,103,114,101,115,115,44,120,79,114,105,103,105,110,97,108,83,105,122,101,44,120,67,111,109,112,114,101,115,115,101,100,83,105,122,101,44,119,89,101,97,114,44,119,77,111,110,116,104,44,119,68,97,121,44,119,72,111,117,114,44,119,77,105,110,117,116,101,44,119,83,101,99,111,110,100,10,115,46,67,111,109,112,114,101,115,115,101,100,73,116,101,109,58,120,79,114,105,103,105,110,97,108,83,105,122,101,44,120,67,111,109,112,114,101,115,115,101,100,83,105,122,101,44,112,78,101,120,116,58,67,111,109,112,114,101,115,115,101,100,73,116,101,109,44,115,80,97,116,104,44,108,80,101,114,109,105,115,115,105,111,110,115,44,108,85,115,101,114,73,68,44,108,71,114,111,117,112,73,68,44,108,79,116,104,101,114,115,73,68,44,108,70,108,97,103,115,44,101,67,114,101,97,116,101,100,58,68,97,116,101,84,105,109,101,44,101,77,111,100,105,102,105,101,100,58,68,97,116,101,84,105,109,101,10,115,46,70,105,108,101,73,110,102,111,58,120,83,105,122,101,44,120,84,105,109,101,83,116,97,109,112,44,112,78,101,120,116,58,70,105,108,101,73,110,102,111,44,115,78,97,109,101,44,108,70,108,97,103,115,44,108,80,101,114,109,105,115,115,105,111,110,115,44,108,85,115,101,114,73,68,44,108,71,114,111,117,112,73,68,44,101,67,114,101,97,116,101,100,58,68,97,116,101,84,105,109,101,44,101,77,111,100,105,102,105,101,100,58,68,97,116,101,84,105,109,101,10,115,46,68,105,114,73,110,102,111,58,112,73,110,102,111,58,70,105,108,101,73,110,102,111,10,115,46,70,105,108,101,70,101,101,100,98,97,99,107,58,120,83,105,122,101,44,120,80,111,115,105,116,105,111,110,44,115,80,97,116,104,44,115,68,101,115,116,44,108,70,101,101,100,98,97,99,107,73,68,44,99,82,101,115,101,114,118,101,100,91,51,50,93,10,115,46,70,105,101,108,100,58,109,65,114,103,44,112,71,101,116,86,97,108,117,101,44,112,83,101,116,86,97,108,117,101,44,112,87,114,105,116,101,86,97,108,117,101,44,115,78,97,109,101,44,117,108,70,105,101,108,100,73,68,44,117,119,79,102,102,115,101,116,44,117,119,73,110,100,101,120,44,117,108,70,108,97,103,115,10,99,46,65,67,58,65,99,116,105,118,97,116,101,61,48,120,50,44,67,108,101,97,114,61,48,120,52,44,67,108,105,112,98,111,97,114,100,61,48,120,50,100,44,67,111,112,121,68,97,116,97,61,48,120,55,44,68,97,116,97,70,101,101,100,61,48,120,56,44,68,101,97,99,116,105,118,97,116,101,61,48,120,57,44,68,105,115,97,98,108,101,61,48,120,50,102,44,68,114,97,103,68,114,111,112,61,48,120,49,48,44,68,114,97,119,61,48,120,97,44,69,78,68,61,48,120,51,49,44,69,110,97,98,108,101,61,48,120,54,44,70,108,117,115,104,61,48,120,98,44,70,111,99,117,115,61,48,120,99,44,70,114,101,101,61,48,120,100,44,70,114,101,101,87,97,114,110,105,110,103,61,48,120,53,44,71,101,116,75,101,121,61,48,120,102,44,72,105,100,101,61,48,120,49,49,44,73,110,105,116,61,48,120,49,50,44,76,111,99,107,61,48,120,49,51,44,76,111,115,116,70,111,99,117,115,61,48,120,49,52,44,77,111,118,101,61,48,120,49,53,44,77,111,118,101,84,111,66,97,99,107,61,48,120,49,54,44,77,111,118,101,84,111,70,114,111,110,116,61,48,120,49,55,44,77,111,118,101,84,111,80,111,105,110,116,61,48,120,50,51,44,78,101,119,67,104,105,108,100,61,48,120,49,56,44,78,101,119,79,98,106,101,99,116,61,48,120,49,97,44,78,101,119,79,119,110,101,114,61,48,120,49,57,44,78,101,119,80,108,97,99,101,109,101,110,116,61,48,120,51,48,44,78,101,120,116,61,48,120,50,57,44,80,114,101,118,61,48,120,50,97,44,81,117,101,114,121,61,48,120,49,99,44,82,101,97,100,61,48,120,49,100,44,82,101,100,105,109,101,110,115,105,111,110,61,48,120,51,44,82,101,100,111,61,48,120,49,98,44,82,101,102,114,101,115,104,61,48,120,50,101,44,82,101,110,97,109,101,61,48,120,49,101,44,82,101,115,101,116,61,48,120,49,102,44,82,101,115,105,122,101,61,48,120,50,48,44,83,97,118,101,73,109,97,103,101,61,48,120,50,49,44,83,97,118,101,83,101,116,116,105,110,103,115,61,48,120,101,44,83,97,118,101,84,111,79,98,106,101,99,116,61,48,120,50,50,44,83,101,101,107,61,48,120,50,52,44,83,101,116,70,105,101,108,100,61,48,120,50,99,44,83,101,116,75,101,121,61,48,120,50,53,44,83,104,111,119,61,48,120,50,54,44,83,105,103,110,97,108,61,48,120,49,44,85,110,100,111,61,48,120,50,55,44,85,110,108,111,99,107,61,48,120,50,56,44,87,114,105,116,101,61,48,120,50,98,10,99,46,65,76,73,71,78,58,66,79,84,84,79,77,61,48,120,50,48,44,67,69,78,84,69,82,61,48,120,99,44,72,79,82,73,90,79,78,84,65,76,61,48,120,52,44,76,69,70,84,61,48,120,49,44,77,73,68,68,76,69,61,48,120,99,44,82,73,71,72,84,61,48,120,50,44,84,79,80,61,48,120,49,48,44,86,69,82,84,73,67,65,76,61,48,120,56,10,99,46,67,67,70,58,65,85,68,73,79,61,48,120,56,48,44,67,79,77,77,65,78,68,61,48,120,49,44,68,65,84,65,61,48,120,49,48,48,44,70,73,76,69,83,89,83,84,69,77,61,48,120,50,44,71,82,65,80,72,73,67,83,61,48,120,52,44,71,85,73,61,48,120,56,44,73,79,61,48,120,49,48,44,77,73,83,67,61,48,120,50,48,48,44,77,85,76,84,73,77,69,68,73,65,61,48,120,56,48,48,44,78,69,84,87,79,82,75,61,48,120,52,48,48,44,83,89,83,84,69,77,61,48,120,50,48,44,84,79,79,76,61,48,120,52,48,10,99,46,67,70,58,68,69,70,76,65,84,69,61,48,120,51,44,71,90,73,80,61,48,120,49,44,90,76,73,66,61,48,120,50,10,99,46,67,76,70,58,73,78,72,69,82,73,84,95,76,79,67,65,76,61,48,120,49,44,78,79,95,79,87,78,69,82,83,72,73,80,61,48,120,50,10,99,46,67,76,73,80,77,79,68,69,58,67,79,80,89,61,48,120,50,44,67,85,84,61,48,120,49,44,80,65,83,84,69,61,48,120,52,10,99,46,67,77,70,58,65,80,80,76,89,95,83,69,67,85,82,73,84,89,61,48,120,50,48,44,67,82,69,65,84,69,95,70,73,76,69,61,48,120,52,44,78,69,87,61,48,120,50,44,78,79,95,76,73,78,75,83,61,48,120,49,48,44,80,65,83,83,87,79,82,68,61,48,120,49,44,82,69,65,68,95,79,78,76,89,61,48,120,56,10,99,46,67,78,70,58,65,85,84,79,95,83,65,86,69,61,48,120,50,44,78,69,87,61,48,120,56,44,79,80,84,73,79,78,65,76,95,70,73,76,69,83,61,48,120,52,44,83,84,82,73,80,95,81,85,79,84,69,83,61,48,120,49,10,99,46,68,65,84,65,58,65,85,68,73,79,61,48,120,53,44,67,79,78,84,69,78,84,61,48,120,98,44,68,69,86,73,67,69,95,73,78,80,85,84,61,48,120,51,44,70,73,76,69,61,48,120,97,44,73,77,65,71,69,61,48,120,55,44,73,78,80,85,84,95,82,69,65,68,89,61,48,120,99,44,82,65,87,61,48,120,50,44,82,69,67,69,73,80,84,61,48,120,57,44,82,69,67,79,82,68,61,48,120,54,44,82,69,81,85,69,83,84,61,48,120,56,44,84,69,88,84,61,48,120,49,44,88,77,76,61,48,120,52,10,99,46,68,69,86,73,67,69,58,66,79,79,75,77,65,82,75,61,48,120,52,48,48,48,48,44,67,79,77,80,65,67,84,95,68,73,83,67,61,48,120,49,44,70,73,88,69,68,61,48,120,56,48,48,48,44,70,76,79,80,80,89,95,68,73,83,75,61,48,120,52,44,72,65,82,68,95,68,73,83,75,61,48,120,50,44,77,69,77,79,82,89,61,48,120,49,48,48,48,44,77,79,68,69,77,61,48,120,50,48,48,48,44,78,69,84,87,79,82,75,61,48,120,56,48,44,80,82,73,78,84,69,82,61,48,120,50,48,48,44,80,82,73,78,84,69,82,95,51,68,61,48,120,49,48,48,48,48,44,82,69,65,68,61,48,120,56,44,82,69,77,79,86,65,66,76,69,61,48,120,50,48,44,82,69,77,79,86,69,65,66,76,69,61,48,120,50,48,44,83,67,65,78,78,69,82,61,48,120,52,48,48,44,83,67,65,78,78,69,82,95,51,68,61,48,120,50,48,48,48,48,44,83,79,70,84,87,65,82,69,61,48,120,52,48,44,84,65,80,69,61,48,120,49,48,48,44,84,69,77,80,79,82,65,82,89,61,48,120,56,48,48,44,85,83,66,61,48,120,52,48,48,48,44,87,82,73,84,69,61,48,120,49,48,10,99,46,68,77,70,58,70,73,88,69,68,95,67,69,78,84,69,82,95,88,61,48,120,49,48,48,48,48,48,44,70,73,88,69,68,95,67,69,78,84,69,82,95,89,61,48,120,50,48,48,48,48,48,44,70,73,88,69,68,95,68,69,80,84,72,61,48,120,49,48,48,48,44,70,73,88,69,68,95,72,69,73,71,72,84,61,48,120,49,48,48,44,70,73,88,69,68,95,82,65,68,73,85,83,95,88,61,48,120,50,48,48,48,48,44,70,73,88,69,68,95,82,65,68,73,85,83,95,89,61,48,120,50,48,48,48,48,48,48,44,70,73,88,69,68,95,87,73,68,84,72,61,48,120,50,48,48,44,70,73,88,69,68,95,88,61,48,120,52,44,70,73,88,69,68,95,88,95,79,70,70,83,69,84,61,48,120,52,48,44,70,73,88,69,68,95,89,61,48,120,56,44,70,73,88,69,68,95,89,95,79,70,70,83,69,84,61,48,120,56,48,44,70,73,88,69,68,95,90,61,48,120,52,48,48,48,44,83,67,65,76,69,68,95,67,69,78,84,69,82,95,88,61,48,120,52,48,48,48,48,44,83,67,65,76,69,68,95,67,69,78,84,69,82,95,89,61,48,120,56,48,48,48,48,44,83,67,65,76,69,68,95,68,69,80,84,72,61,48,120,50,48,48,48,44,83,67,65,76,69,68,95,72,69,73,71,72,84,61,48,120,52,48,48,44,83,67,65,76,69,68,95,82,65,68,73,85,83,95,88,61,48,120,49,48,48,48,48,44,83,67,65,76,69,68,95,82,65,68,73,85,83,95,89,61,48,120,49,48,48,48,48,48,48,44,83,67,65,76,69,68,95,87,73,68,84,72,61,48,120,56,48,48,44,83,67,65,76,69,68,95,88,61,48,120,49,44,83,67,65,76,69,68,95,88,95,79,70,70,83,69,84,61,48,120,49,48,44,83,67,65,76,69,68,95,89,61,48,120,50,44,83,67,65,76,69,68,95,89,95,79,70,70,83,69,84,61,48,120,50,48,44,83,67,65,76,69,68,95,90,61,48,120,56,48,48,48,44,83,84,65,84,85,83,95,67,72,65,78,71,69,95,72,61,48,120,52,48,48,48,48,48,44,83,84,65,84,85,83,95,67,72,65,78,71,69,95,86,61,48,120,56,48,48,48,48,48,10,99,46,68,82,76,58,68,79,87,78,61,48,120,49,44,69,65,83,84,61,48,120,50,44,76,69,70,84,61,48,120,51,44,78,79,82,84,72,61,48,120,48,44,78,79,82,84,72,95,69,65,83,84,61,48,120,52,44,78,79,82,84,72,95,87,69,83,84,61,48,120,53,44,82,73,71,72,84,61,48,120,50,44,83,79,85,84,72,61,48,120,49,44,83,79,85,84,72,95,69,65,83,84,61,48,120,54,44,83,79,85,84,72,95,87,69,83,84,61,48,120,55,44,85,80,61,48,120,48,44,87,69,83,84,61,48,120,51,10,99,46,69,68,71,69,58,65,76,76,61,48,120,102,102,44,66,79,84,84,79,77,61,48,120,56,44,66,79,84,84,79,77,95,76,69,70,84,61,48,120,52,48,44,66,79,84,84,79,77,95,82,73,71,72,84,61,48,120,56,48,44,76,69,70,84,61,48,120,50,44,82,73,71,72,84,61,48,120,52,44,84,79,80,61,48,120,49,44,84,79,80,95,76,69,70,84,61,48,120,49,48,44,84,79,80,95,82,73,71,72,84,61,48,120,50,48,10,99,46,69,82,70,58,78,111,116,105,102,105,101,100,61,48,120,52,48,48,48,48,48,48,48,10,99,46,69,82,82,58,65,99,99,101,115,115,77,101,109,111,114,121,61,48,120,52,98,44,65,99,99,101,115,115,79,98,106,101,99,116,61,48,120,53,51,44,65,99,99,101,115,115,83,101,109,97,112,104,111,114,101,61,48,120,55,51,44,65,99,116,105,118,97,116,101,61,48,120,52,50,44,65,100,100,67,108,97,115,115,61,48,120,52,49,44,65,108,108,111,99,77,101,109,111,114,121,61,48,120,53,52,44,65,108,108,111,99,83,101,109,97,112,104,111,114,101,61,48,120,55,50,44,65,108,114,101,97,100,121,68,101,102,105,110,101,100,61,48,120,98,54,44,65,108,114,101,97,100,121,76,111,99,107,101,100,61,48,120,57,99,44,65,114,103,115,61,48,120,49,52,44,65,114,114,97,121,70,117,108,108,61,48,120,50,100,44,66,117,102,102,101,114,79,118,101,114,102,108,111,119,61,48,120,53,99,44,66,117,115,121,61,48,120,56,98,44,67,97,110,99,101,108,108,101,100,61,48,120,51,44,67,97,114,100,82,101,97,100,101,114,85,110,97,118,97,105,108,97,98,108,101,61,48,120,57,102,44,67,97,114,100,82,101,97,100,101,114,85,110,107,110,111,119,110,61,48,120,57,100,44,67,111,109,112,114,101,115,115,105,111,110,61,48,120,97,100,44,67,111,110,110,101,99,116,105,111,110,65,98,111,114,116,101,100,61,48,120,56,99,44,67,111,110,110,101,99,116,105,111,110,82,101,102,117,115,101,100,61,48,120,56,51,44,67,111,110,115,116,114,97,105,110,116,86,105,111,108,97,116,105,111,110,61,48,120,56,56,44,67,111,110,116,105,110,117,101,61,48,120,53,44,67,111,114,101,86,101,114,115,105,111,110,61,48,120,50,54,44,67,114,101,97,116,101,70,105,108,101,61,48,120,55,52,44,67,114,101,97,116,101,79,98,106,101,99,116,61,48,120,54,53,44,67,114,101,97,116,101,82,101,115,111,117,114,99,101,61,48,120,98,50,44,68,97,116,97,83,105,122,101,61,48,120,56,97,44,68,101,97,99,116,105,118,97,116,101,100,61,48,120,57,97,44,68,101,97,100,76,111,99,107,61,48,120,51,101,44,68,101,99,111,109,112,114,101,115,115,105,111,110,61,48,120,97,99,44,68,101,108,101,116,101,70,105,108,101,61,48,120,55,53,44,68,105,114,69,109,112,116,121,61,48,120,56,44,68,105,115,99,111,110,110,101,99,116,101,100,61,48,120,56,54,44,68,111,78,111,116,69,120,112,117,110,103,101,61,48,120,51,48,44,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,55,56,44,68,111,117,98,108,101,73,110,105,116,61,48,120,52,51,44,68,114,97,119,61,48,120,52,56,44,69,78,68,61,48,120,98,101,44,69,109,112,116,121,83,116,114,105,110,103,61,48,120,54,100,44,69,110,100,79,102,70,105,108,101,61,48,120,55,101,44,69,110,116,114,121,77,105,115,115,105,110,103,72,101,97,100,101,114,61,48,120,51,97,44,69,120,97,109,105,110,101,70,97,105,108,101,100,61,48,120,49,57,44,69,120,99,101,112,116,105,111,110,61,48,120,97,51,44,69,120,99,101,112,116,105,111,110,84,104,114,101,115,104,111,108,100,61,48,120,57,44,69,120,99,108,117,115,105,118,101,68,101,110,105,101,100,61,48,120,53,51,44,69,120,101,99,86,105,111,108,97,116,105,111,110,61,48,120,56,102,44,69,120,105,115,116,115,61,48,120,55,97,44,69,120,112,101,99,116,101,100,70,105,108,101,61,48,120,54,102,44,69,120,112,101,99,116,101,100,70,111,108,100,101,114,61,48,120,97,101,44,70,97,105,108,101,100,61,48,120,100,44,70,97,108,115,101,61,48,120,49,44,70,105,101,108,100,78,111,116,83,101,116,61,48,120,52,52,44,70,105,101,108,100,83,101,97,114,99,104,61,48,120,51,50,44,70,105,101,108,100,84,121,112,101,77,105,115,109,97,116,99,104,61,48,120,53,97,44,70,105,108,101,61,48,120,101,44,70,105,108,101,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,49,50,44,70,105,108,101,69,120,105,115,116,115,61,48,120,54,51,44,70,105,108,101,78,111,116,70,111,117,110,100,61,48,120,49,50,44,70,105,108,101,82,101,97,100,70,108,97,103,61,48,120,52,54,44,70,105,108,101,87,114,105,116,101,70,108,97,103,61,48,120,52,55,44,70,105,110,105,115,104,101,100,61,48,120,55,101,44,70,117,110,99,116,105,111,110,61,48,120,98,53,44,71,101,116,70,105,101,108,100,61,48,120,53,54,44,71,101,116,83,117,114,102,97,99,101,73,110,102,111,61,48,120,55,100,44,72,111,115,116,78,111,116,70,111,117,110,100,61,48,120,56,49,44,72,111,115,116,85,110,114,101,97,99,104,97,98,108,101,61,48,120,56,53,44,73,100,101,110,116,105,99,97,108,80,97,116,104,115,61,48,120,55,57,44,73,108,108,101,103,97,108,65,99,116,105,111,110,65,116,116,101,109,112,116,61,48,120,51,57,44,73,108,108,101,103,97,108,65,99,116,105,111,110,73,68,61,48,120,51,55,44,73,108,108,101,103,97,108,65,100,100,114,101,115,115,61,48,120,57,49,44,73,108,108,101,103,97,108,77,101,116,104,111,100,73,68,61,48,120,51,54,44,73,109,109,117,116,97,98,108,101,61,48,120,97,102,44,73,110,85,115,101,61,48,120,99,44,73,110,105,116,61,48,120,50,49,44,73,110,105,116,77,111,100,117,108,101,61,48,120,49,49,44,73,110,112,117,116,79,117,116,112,117,116,61,48,120,57,52,44,73,110,116,101,103,114,105,116,121,86,105,111,108,97,116,105,111,110,61,48,120,56,56,44,73,110,118,97,108,105,100,68,97,116,97,61,48,120,102,44,73,110,118,97,108,105,100,68,105,109,101,110,115,105,111,110,61,48,120,53,57,44,73,110,118,97,108,105,100,72,84,84,80,82,101,115,112,111,110,115,101,61,48,120,97,49,44,73,110,118,97,108,105,100,72,97,110,100,108,101,61,48,120,57,54,44,73,110,118,97,108,105,100,79,98,106,101,99,116,61,48,120,56,101,44,73,110,118,97,108,105,100,80,97,116,104,61,48,120,51,51,44,73,110,118,97,108,105,100,82,101,102,101,114,101,110,99,101,61,48,120,97,50,44,73,110,118,97,108,105,100,83,116,97,116,101,61,48,120,56,48,44,73,110,118,97,108,105,100,85,82,73,61,48,120,56,50,44,73,110,118,97,108,105,100,86,97,108,117,101,61,48,120,57,56,44,76,105,109,105,116,101,100,83,117,99,99,101,115,115,61,48,120,50,44,76,105,115,116,67,104,105,108,100,114,101,110,61,48,120,54,97,44,76,111,97,100,77,111,100,117,108,101,61,48,120,57,53,44,76,111,99,107,61,48,120,49,56,44,76,111,99,107,70,97,105,108,101,100,61,48,120,49,56,44,76,111,99,107,77,117,116,101,120,61,48,120,97,97,44,76,111,99,107,82,101,113,117,105,114,101,100,61,48,120,57,98,44,76,111,99,107,101,100,61,48,120,57,99,44,76,111,111,112,61,48,120,54,50,44,76,111,115,116,67,108,97,115,115,61,48,120,49,97,44,76,111,115,116,79,119,110,101,114,61,48,120,50,102,44,76,111,119,67,97,112,97,99,105,116,121,61,48,120,50,48,44,77,97,114,107,101,100,70,111,114,68,101,108,101,116,105,111,110,61,48,120,51,53,44,77,101,109,111,114,121,61,48,120,49,100,44,77,101,109,111,114,121,67,111,114,114,117,112,116,61,48,120,51,49,44,77,101,109,111,114,121,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,51,100,44,77,101,109,111,114,121,73,110,102,111,61,48,120,54,54,44,77,105,115,109,97,116,99,104,61,48,120,53,101,44,77,105,115,115,105,110,103,67,108,97,115,115,61,48,120,52,53,44,77,105,115,115,105,110,103,67,108,97,115,115,78,97,109,101,61,48,120,50,97,44,77,105,115,115,105,110,103,80,97,116,104,61,48,120,52,99,44,77,111,100,117,108,101,73,110,105,116,70,97,105,108,101,100,61,48,120,51,99,44,77,111,100,117,108,101,77,105,115,115,105,110,103,73,110,105,116,61,48,120,51,98,44,77,111,100,117,108,101,77,105,115,115,105,110,103,78,97,109,101,61,48,120,52,48,44,77,111,100,117,108,101,79,112,101,110,70,97,105,108,101,100,61,48,120,51,56,44,78,101,101,100,79,119,110,101,114,61,48,120,50,52,44,78,101,101,100,87,105,100,116,104,72,101,105,103,104,116,61,48,120,50,55,44,78,101,103,97,116,105,118,101,67,108,97,115,115,73,68,61,48,120,50,57,44,78,101,103,97,116,105,118,101,83,117,98,67,108,97,115,115,73,68,61,48,120,50,56,44,78,101,116,119,111,114,107,85,110,114,101,97,99,104,97,98,108,101,61,48,120,56,52,44,78,101,119,79,98,106,101,99,116,61,48,120,53,53,44,78,111,65,99,116,105,111,110,61,48,120,49,98,44,78,111,68,97,116,97,61,48,120,49,53,44,78,111,70,105,101,108,100,65,99,99,101,115,115,61,48,120,53,55,44,78,111,77,97,116,99,104,105,110,103,79,98,106,101,99,116,61,48,120,52,97,44,78,111,77,101,100,105,97,73,110,115,101,114,116,101,100,61,48,120,57,101,44,78,111,77,101,109,111,114,121,61,48,120,97,44,78,111,77,101,116,104,111,100,115,61,48,120,52,57,44,78,111,80,101,114,109,105,115,115,105,111,110,61,48,120,50,50,44,78,111,80,111,105,110,116,101,114,61,48,120,98,44,78,111,83,101,97,114,99,104,82,101,115,117,108,116,61,48,120,52,101,44,78,111,83,116,97,116,115,61,48,120,49,102,44,78,111,83,117,112,112,111,114,116,61,48,120,49,99,44,78,111,116,70,111,117,110,100,61,48,120,49,48,44,78,111,116,73,110,105,116,105,97,108,105,115,101,100,61,48,120,54,55,44,78,111,116,76,111,99,107,101,100,61,48,120,52,100,44,78,111,116,80,111,115,115,105,98,108,101,61,48,120,98,51,44,78,111,116,104,105,110,103,68,111,110,101,61,48,120,52,44,78,111,116,105,102,105,101,100,61,48,120,52,48,48,48,48,48,48,48,44,78,117,108,108,65,114,103,115,61,48,120,56,100,44,79,98,106,101,99,116,67,111,114,114,117,112,116,61,48,120,53,48,44,79,98,106,101,99,116,69,120,105,115,116,115,61,48,120,54,101,44,79,98,115,111,108,101,116,101,61,48,120,98,49,44,79,98,116,97,105,110,77,101,116,104,111,100,61,48,120,50,99,44,79,107,97,121,61,48,120,48,44,79,112,101,110,70,105,108,101,61,48,120,55,54,44,79,112,101,110,71,76,61,48,120,97,53,44,79,117,116,79,102,66,111,117,110,100,115,61,48,120,53,102,44,79,117,116,79,102,68,97,116,97,61,48,120,55,101,44,79,117,116,79,102,82,97,110,103,101,61,48,120,50,98,44,79,117,116,79,102,83,112,97,99,101,61,48,120,55,99,44,79,117,116,115,105,100,101,77,97,105,110,84,104,114,101,97,100,61,48,120,97,54,44,79,119,110,101,114,78,101,101,100,115,66,105,116,109,97,112,61,48,120,50,53,44,79,119,110,101,114,80,97,115,115,84,104,114,111,117,103,104,61,48,120,53,49,44,80,101,114,109,105,115,115,105,111,110,68,101,110,105,101,100,61,48,120,50,50,44,80,101,114,109,105,115,115,105,111,110,115,61,48,120,50,50,44,80,114,111,120,121,83,83,76,84,117,110,110,101,108,61,48,120,97,48,44,81,117,101,114,121,61,48,120,50,101,44,82,101,97,100,61,48,120,49,54,44,82,101,97,100,70,105,108,101,84,111,66,117,102,102,101,114,61,48,120,98,48,44,82,101,97,100,79,110,108,121,61,48,120,55,55,44,82,101,97,108,108,111,99,77,101,109,111,114,121,61,48,120,54,49,44,82,101,99,117,114,115,105,111,110,61,48,120,57,48,44,82,101,100,105,109,101,110,115,105,111,110,61,48,120,55,49,44,82,101,102,114,101,115,104,61,48,120,54,57,44,82,101,115,105,122,101,61,48,120,55,48,44,82,101,115,111,108,118,101,80,97,116,104,61,48,120,54,52,44,82,101,115,111,108,118,101,83,121,109,98,111,108,61,48,120,98,52,44,82,101,115,111,117,114,99,101,69,120,105,115,116,115,61,48,120,54,56,44,82,101,116,114,121,61,48,120,55,44,83,97,110,105,116,121,70,97,105,108,117,114,101,61,48,120,55,98,44,83,99,104,101,109,97,86,105,111,108,97,116,105,111,110,61,48,120,56,57,44,83,101,97,114,99,104,61,48,120,49,48,44,83,101,99,117,114,105,116,121,61,48,120,57,55,44,83,101,101,107,61,48,120,54,48,44,83,101,114,118,105,99,101,85,110,97,118,97,105,108,97,98,108,101,61,48,120,57,57,44,83,101,116,70,105,101,108,100,61,48,120,51,52,44,83,101,116,86,97,108,117,101,78,111,116,65,114,114,97,121,61,48,120,98,99,44,83,101,116,86,97,108,117,101,78,111,116,70,117,110,99,116,105,111,110,61,48,120,98,97,44,83,101,116,86,97,108,117,101,78,111,116,76,111,111,107,117,112,61,48,120,98,100,44,83,101,116,86,97,108,117,101,78,111,116,78,117,109,101,114,105,99,61,48,120,98,55,44,83,101,116,86,97,108,117,101,78,111,116,79,98,106,101,99,116,61,48,120,98,57,44,83,101,116,86,97,108,117,101,78,111,116,80,111,105,110,116,101,114,61,48,120,98,98,44,83,101,116,86,97,108,117,101,78,111,116,83,116,114,105,110,103,61,48,120,98,56,44,83,101,116,86,111,108,117,109,101,61,48,120,97,98,44,83,107,105,112,61,48,120,54,44,83,109,97,108,108,77,97,115,107,61,48,120,54,99,44,83,116,97,116,101,109,101,110,116,85,110,115,97,116,105,115,102,105,101,100,61,48,120,52,102,44,83,116,114,105,110,103,70,111,114,109,97,116,61,48,120,55,102,44,83,121,110,116,97,120,61,48,120,55,102,44,83,121,115,116,101,109,67,97,108,108,61,48,120,54,98,44,83,121,115,116,101,109,67,111,114,114,117,112,116,61,48,120,50,51,44,83,121,115,116,101,109,76,111,99,107,101,100,61,48,120,51,102,44,84,97,115,107,83,116,105,108,108,69,120,105,115,116,115,61,48,120,56,55,44,84,101,114,109,105,110,97,116,101,61,48,120,57,44,84,104,114,101,97,100,65,108,114,101,97,100,121,65,99,116,105,118,101,61,48,120,97,52,44,84,104,114,101,97,100,78,111,116,76,111,99,107,101,100,61,48,120,97,57,44,84,105,109,101,79,117,116,61,48,120,49,101,44,84,114,117,101,61,48,120,48,44,85,110,98,97,108,97,110,99,101,100,88,77,76,61,48,120,57,50,44,85,110,100,101,102,105,110,101,100,70,105,101,108,100,61,48,120,52,52,44,85,110,114,101,99,111,103,110,105,115,101,100,70,105,101,108,100,84,121,112,101,61,48,120,53,98,44,85,110,115,117,112,112,111,114,116,101,100,70,105,101,108,100,61,48,120,53,100,44,85,110,115,117,112,112,111,114,116,101,100,79,119,110,101,114,61,48,120,53,50,44,85,115,101,83,117,98,67,108,97,115,115,61,48,120,97,55,44,86,105,114,116,117,97,108,86,111,108,117,109,101,61,48,120,53,56,44,87,111,117,108,100,66,108,111,99,107,61,48,120,57,51,44,87,114,105,116,101,61,48,120,49,55,44,87,114,111,110,103,67,108,97,115,115,61,48,120,56,101,44,87,114,111,110,103,79,98,106,101,99,116,84,121,112,101,61,48,120,56,101,44,87,114,111,110,103,84,121,112,101,61,48,120,97,56,44,87,114,111,110,103,86,101,114,115,105,111,110,61,48,120,49,51,10,99,46,69,86,71,58,65,78,68,82,79,73,68,61,48,120,100,44,65,80,80,61,48,120,99,44,65,85,68,73,79,61,48,120,56,44,67,76,65,83,83,61,48,120,98,44,68,73,83,80,76,65,89,61,48,120,53,44,69,78,68,61,48,120,101,44,70,73,76,69,83,89,83,84,69,77,61,48,120,49,44,71,85,73,61,48,120,52,44,72,65,82,68,87,65,82,69,61,48,120,55,44,73,79,61,48,120,54,44,78,69,84,87,79,82,75,61,48,120,50,44,80,79,87,69,82,61,48,120,97,44,83,89,83,84,69,77,61,48,120,51,44,85,83,69,82,61,48,120,57,10,99,46,70,66,75,58,67,79,80,89,95,70,73,76,69,61,48,120,50,44,68,69,76,69,84,69,95,70,73,76,69,61,48,120,51,44,77,79,86,69,95,70,73,76,69,61,48,120,49,10,99,46,70,68,58,65,76,76,79,67,61,48,120,50,48,44,65,82,82,65,89,61,48,120,49,48,48,48,44,65,82,82,65,89,83,73,90,69,61,48,120,56,48,44,66,85,70,70,69,82,61,48,120,50,48,48,44,66,85,70,83,73,90,69,61,48,120,56,48,44,66,89,84,69,61,48,120,49,48,48,48,48,48,48,44,67,80,80,61,48,120,52,48,48,48,44,67,85,83,84,79,77,61,48,120,56,48,48,48,44,68,79,85,66,76,69,61,48,120,56,48,48,48,48,48,48,48,44,68,79,85,66,76,69,82,69,83,85,76,84,61,48,120,56,48,48,48,48,49,48,48,44,69,82,82,79,82,61,48,120,56,48,48,44,70,76,65,71,83,61,48,120,52,48,44,70,76,79,65,84,61,48,120,49,48,48,48,48,48,48,48,44,70,85,78,67,84,73,79,78,61,48,120,50,48,48,48,48,48,48,44,70,85,78,67,84,73,79,78,80,84,82,61,48,120,97,48,48,48,48,48,48,44,73,61,48,120,52,48,48,44,73,78,73,84,61,48,120,52,48,48,44,76,65,82,71,69,61,48,120,52,48,48,48,48,48,48,44,76,65,82,71,69,82,69,83,85,76,84,61,48,120,52,48,48,48,49,48,48,44,76,79,67,65,76,61,48,120,50,44,76,79,78,71,61,48,120,52,48,48,48,48,48,48,48,44,76,79,78,71,82,69,83,85,76,84,61,48,120,52,48,48,48,48,49,48,48,44,76,79,79,75,85,80,61,48,120,56,48,44,79,66,74,69,67,84,61,48,120,49,44,79,66,74,69,67,84,73,68,61,48,120,52,48,48,48,48,48,48,49,44,79,66,74,69,67,84,80,84,82,61,48,120,56,48,48,48,48,48,49,44,80,79,73,78,84,69,82,61,48,120,56,48,48,48,48,48,48,44,80,82,73,86,65,84,69,61,48,120,49,48,48,48,48,44,80,84,82,61,48,120,56,48,48,48,48,48,48,44,80,84,82,66,85,70,70,69,82,61,48,120,56,48,48,48,50,48,48,44,80,84,82,82,69,83,85,76,84,61,48,120,56,48,48,48,49,48,48,44,80,84,82,83,73,90,69,61,48,120,56,48,44,80,84,82,95,68,79,85,66,76,69,82,69,83,85,76,84,61,48,120,56,56,48,48,48,49,48,48,44,80,84,82,95,76,65,82,71,69,82,69,83,85,76,84,61,48,120,99,48,48,48,49,48,48,44,80,84,82,95,76,79,78,71,82,69,83,85,76,84,61,48,120,52,56,48,48,48,49,48,48,44,82,61,48,120,49,48,48,44,82,69,65,68,61,48,120,49,48,48,44,82,69,83,79,85,82,67,69,61,48,120,50,48,48,48,44,82,69,83,85,76,84,61,48,120,49,48,48,44,82,71,66,61,48,120,56,48,48,48,48,44,82,73,61,48,120,53,48,48,44,82,87,61,48,120,51,48,48,44,83,67,65,76,69,68,61,48,120,50,48,48,48,48,48,44,83,84,82,61,48,120,56,48,48,48,48,48,44,83,84,82,73,78,71,61,48,120,56,48,48,48,48,48,44,83,84,82,82,69,83,85,76,84,61,48,120,56,48,48,49,48,48,44,83,84,82,85,67,84,61,48,120,49,48,44,83,89,78,79,78,89,77,61,48,120,50,48,48,48,48,44,83,89,83,84,69,77,61,48,120,49,48,48,48,48,44,84,65,71,83,61,48,120,52,48,48,44,85,78,73,84,61,48,120,50,48,48,48,48,48,48,48,44,85,78,83,73,71,78,69,68,61,48,120,52,48,48,48,48,44,86,65,82,84,65,71,83,61,48,120,52,48,44,86,73,82,84,85,65,76,61,48,120,56,44,86,79,73,68,61,48,120,48,44,86,79,76,65,84,73,76,69,61,48,120,48,44,87,61,48,120,50,48,48,44,87,79,82,68,61,48,120,52,48,48,48,48,48,44,87,82,73,84,69,61,48,120,50,48,48,10,99,46,70,68,66,58,67,79,77,80,82,69,83,83,95,70,73,76,69,61,48,120,50,44,68,69,67,79,77,80,82,69,83,83,95,70,73,76,69,61,48,120,49,44,68,69,67,79,77,80,82,69,83,83,95,79,66,74,69,67,84,61,48,120,52,44,82,69,77,79,86,69,95,70,73,76,69,61,48,120,51,10,99,46,70,68,76,58,70,69,69,68,66,65,67,75,61,48,120,49,10,99,46,70,68,84,58,65,67,67,69,83,83,69,68,61,48,120,50,44,65,82,67,72,73,86,69,68,61,48,120,51,44,67,82,69,65,84,69,68,61,48,120,49,44,77,79,68,73,70,73,69,68,61,48,120,48,10,99,46,70,70,82,58,65,66,79,82,84,61,48,120,50,44,67,79,78,84,73,78,85,69,61,48,120,48,44,79,75,65,89,61,48,120,48,44,83,75,73,80,61,48,120,49,10,99,46,70,76,58,65,80,80,82,79,88,73,77,65,84,69,61,48,120,49,48,44,66,85,70,70,69,82,61,48,120,52,48,44,68,69,86,73,67,69,61,48,120,52,48,48,44,68,73,82,69,67,84,79,82,89,61,48,120,56,44,69,88,67,76,85,68,69,95,70,73,76,69,83,61,48,120,49,48,48,48,44,69,88,67,76,85,68,69,95,70,79,76,68,69,82,83,61,48,120,50,48,48,48,44,70,73,76,69,61,48,120,49,48,48,44,70,79,76,68,69,82,61,48,120,56,44,76,73,78,75,61,48,120,50,48,44,76,79,79,80,61,48,120,56,48,44,78,69,87,61,48,120,50,44,82,69,65,68,61,48,120,52,44,82,69,83,69,84,95,68,65,84,69,61,48,120,50,48,48,44,83,84,82,69,65,77,61,48,120,56,48,48,44,87,82,73,84,69,61,48,120,49,10,99,46,70,79,70,58,83,77,65,82,84,95,78,65,77,69,83,61,48,120,49,10,99,46,73,68,84,89,80,69,58,70,85,78,67,84,73,79,78,61,48,120,51,44,71,76,79,66,65,76,61,48,120,50,44,77,69,83,83,65,71,69,61,48,120,49,10,99,46,74,69,84,58,65,66,83,95,88,89,61,48,120,49,98,44,65,78,65,76,79,71,50,95,88,89,61,48,120,49,54,44,65,78,65,76,79,71,50,95,90,61,48,120,49,55,44,65,78,65,76,79,71,95,88,89,61,48,120,49,52,44,65,78,65,76,79,71,95,90,61,48,120,49,53,44,66,85,84,84,79,78,95,49,61,48,120,50,44,66,85,84,84,79,78,95,49,48,61,48,120,98,44,66,85,84,84,79,78,95,50,61,48,120,51,44,66,85,84,84,79,78,95,51,61,48,120,52,44,66,85,84,84,79,78,95,52,61,48,120,53,44,66,85,84,84,79,78,95,53,61,48,120,54,44,66,85,84,84,79,78,95,54,61,48,120,55,44,66,85,84,84,79,78,95,55,61,48,120,56,44,66,85,84,84,79,78,95,56,61,48,120,57,44,66,85,84,84,79,78,95,57,61,48,120,97,44,66,85,84,84,79,78,95,83,69,76,69,67,84,61,48,120,102,44,66,85,84,84,79,78,95,83,84,65,82,84,61,48,120,101,44,67,82,79,83,83,69,68,95,73,78,61,48,120,49,99,44,67,82,79,83,83,69,68,95,79,85,84,61,48,120,49,100,44,68,69,86,73,67,69,95,84,73,76,84,95,88,89,61,48,120,49,102,44,68,69,86,73,67,69,95,84,73,76,84,95,90,61,48,120,50,48,44,68,73,71,73,84,65,76,95,88,89,61,48,120,49,44,68,73,83,80,76,65,89,95,69,68,71,69,61,48,120,50,49,44,69,78,68,61,48,120,50,50,44,76,69,70,84,95,66,85,77,80,69,82,95,49,61,48,120,49,48,44,76,69,70,84,95,66,85,77,80,69,82,95,50,61,48,120,49,49,44,76,77,66,61,48,120,50,44,77,77,66,61,48,120,52,44,80,69,78,95,84,73,76,84,95,88,89,61,48,120,49,97,44,80,82,69,83,83,85,82,69,61,48,120,49,101,44,82,73,71,72,84,95,66,85,77,80,69,82,95,49,61,48,120,49,50,44,82,73,71,72,84,95,66,85,77,80,69,82,95,50,61,48,120,49,51,44,82,77,66,61,48,120,51,44,84,82,73,71,71,69,82,95,76,69,70,84,61,48,120,99,44,84,82,73,71,71,69,82,95,82,73,71,72,84,61,48,120,100,44,87,72,69,69,76,61,48,120,49,56,44,87,72,69,69,76,95,84,73,76,84,61,48,120,49,57,10,99,46,74,84,89,80,69,58,65,78,65,76,79,71,61,48,120,50,48,44,65,78,67,72,79,82,69,68,61,48,120,50,44,66,85,84,84,79,78,61,48,120,56,48,44,67,82,79,83,83,73,78,71,61,48,120,56,44,68,66,76,95,67,76,73,67,75,61,48,120,50,48,48,44,68,73,71,73,84,65,76,61,48,120,49,48,44,68,82,65,71,71,69,68,61,48,120,52,44,68,82,65,71,95,73,84,69,77,61,48,120,56,48,48,44,69,88,84,95,77,79,86,69,77,69,78,84,61,48,120,52,48,44,77,79,86,69,77,69,78,84,61,48,120,49,48,48,44,82,69,80,69,65,84,69,68,61,48,120,52,48,48,44,83,69,67,79,78,68,65,82,89,61,48,120,49,10,99,46,75,69,89,58,65,61,48,120,49,44,65,80,79,83,84,82,79,80,72,69,61,48,120,50,98,44,65,84,61,48,120,56,97,44,66,61,48,120,50,44,66,65,67,75,61,48,120,56,54,44,66,65,67,75,83,80,65,67,69,61,48,120,54,57,44,66,65,67,75,95,83,76,65,83,72,61,48,120,50,102,44,66,82,69,65,75,61,48,120,55,98,44,67,61,48,120,51,44,67,65,76,76,61,48,120,56,55,44,67,65,77,69,82,65,61,48,120,56,57,44,67,65,78,67,69,76,61,48,120,55,97,44,67,65,80,83,95,76,79,67,75,61,48,120,52,54,44,67,76,69,65,82,61,48,120,54,101,44,67,79,77,77,65,61,48,120,50,99,44,68,61,48,120,52,44,68,69,76,69,84,69,61,48,120,54,100,44,68,79,84,61,48,120,50,100,44,68,79,87,78,61,48,120,54,49,44,69,61,48,120,53,44,69,73,71,72,84,61,48,120,50,50,44,69,78,68,61,48,120,55,50,44,69,78,68,95,67,65,76,76,61,48,120,56,56,44,69,78,84,69,82,61,48,120,54,98,44,69,81,85,65,76,83,61,48,120,50,55,44,69,83,67,65,80,69,61,48,120,54,99,44,69,88,69,67,85,84,69,61,48,120,55,52,44,70,61,48,120,54,44,70,49,61,48,120,52,99,44,70,49,48,61,48,120,53,53,44,70,49,49,61,48,120,53,54,44,70,49,50,61,48,120,53,55,44,70,49,51,61,48,120,53,56,44,70,49,52,61,48,120,53,57,44,70,49,53,61,48,120,53,97,44,70,49,54,61,48,120,53,98,44,70,49,55,61,48,120,53,99,44,70,49,56,61,48,120,56,48,44,70,49,57,61,48,120,56,49,44,70,50,61,48,120,52,100,44,70,50,48,61,48,120,56,50,44,70,51,61,48,120,52,101,44,70,52,61,48,120,52,102,44,70,53,61,48,120,53,48,44,70,54,61,48,120,53,49,44,70,55,61,48,120,53,50,44,70,56,61,48,120,53,51,44,70,57,61,48,120,53,52,44,70,73,78,68,61,48,120,55,57,44,70,73,86,69,61,48,120,49,102,44,70,79,82,87,65,82,68,61,48,120,57,48,44,70,79,85,82,61,48,120,49,101,44,71,61,48,120,55,44,72,61,48,120,56,44,72,69,76,80,61,48,120,52,51,44,72,79,77,69,61,48,120,54,102,44,73,61,48,120,57,44,73,78,83,69,82,84,61,48,120,55,53,44,74,61,48,120,97,44,75,61,48,120,98,44,76,61,48,120,99,44,76,69,70,84,61,48,120,54,51,44,76,69,78,83,95,70,79,67,85,83,61,48,120,56,99,44,76,69,83,83,95,71,82,69,65,84,69,82,61,48,120,53,102,44,76,73,83,84,95,69,78,68,61,48,120,57,54,44,76,95,65,76,84,61,48,120,52,56,44,76,95,67,79,77,77,65,78,68,61,48,120,52,97,44,76,95,67,79,78,84,82,79,76,61,48,120,52,49,44,76,95,83,72,73,70,84,61,48,120,52,52,44,76,95,83,81,85,65,82,69,61,48,120,50,56,44,77,61,48,120,100,44,77,65,67,82,79,61,48,120,53,100,44,77,69,78,85,61,48,120,55,56,44,77,73,78,85,83,61,48,120,50,54,44,77,85,84,69,61,48,120,57,50,44,78,61,48,120,101,44,78,69,88,84,61,48,120,56,101,44,78,73,78,69,61,48,120,50,51,44,78,80,95,48,61,48,120,51,49,44,78,80,95,49,61,48,120,51,50,44,78,80,95,50,61,48,120,51,51,44,78,80,95,51,61,48,120,51,52,44,78,80,95,52,61,48,120,51,53,44,78,80,95,53,61,48,120,51,54,44,78,80,95,54,61,48,120,51,55,44,78,80,95,55,61,48,120,51,56,44,78,80,95,56,61,48,120,51,57,44,78,80,95,57,61,48,120,51,97,44,78,80,95,66,65,82,61,48,120,51,100,44,78,80,95,68,69,67,73,77,65,76,61,48,120,51,102,44,78,80,95,68,73,86,73,68,69,61,48,120,52,48,44,78,80,95,68,79,84,61,48,120,51,102,44,78,80,95,69,78,84,69,82,61,48,120,55,101,44,78,80,95,77,73,78,85,83,61,48,120,51,101,44,78,80,95,77,85,76,84,73,80,76,89,61,48,120,51,98,44,78,80,95,80,76,85,83,61,48,120,51,99,44,78,80,95,80,76,85,83,95,77,73,78,85,83,61,48,120,53,101,44,78,80,95,83,69,80,65,82,65,84,79,82,61,48,120,51,100,44,78,85,77,95,76,79,67,75,61,48,120,55,99,44,79,61,48,120,102,44,79,78,69,61,48,120,49,98,44,80,61,48,120,49,48,44,80,65,71,69,95,68,79,87,78,61,48,120,55,49,44,80,65,71,69,95,85,80,61,48,120,55,48,44,80,65,85,83,69,61,48,120,54,53,44,80,69,82,73,79,68,61,48,120,50,100,44,80,76,65,89,61,48,120,57,53,44,80,76,85,83,61,48,120,56,98,44,80,79,85,78,68,61,48,120,57,52,44,80,79,87,69,82,61,48,120,54,56,44,80,82,69,86,73,79,85,83,61,48,120,56,102,44,80,82,73,78,84,61,48,120,52,55,44,80,82,84,95,83,67,82,61,48,120,55,100,44,81,61,48,120,49,49,44,82,61,48,120,49,50,44,82,69,68,79,61,48,120,55,55,44,82,69,86,69,82,83,69,95,81,85,79,84,69,61,48,120,50,53,44,82,69,87,73,78,68,61,48,120,57,49,44,82,73,71,72,84,61,48,120,54,50,44,82,95,65,76,84,61,48,120,52,57,44,82,95,67,79,77,77,65,78,68,61,48,120,52,98,44,82,95,67,79,78,84,82,79,76,61,48,120,52,50,44,82,95,83,72,73,70,84,61,48,120,52,53,44,82,95,83,81,85,65,82,69,61,48,120,50,57,44,83,61,48,120,49,51,44,83,67,82,95,76,79,67,75,61,48,120,54,52,44,83,69,76,69,67,84,61,48,120,55,51,44,83,69,77,73,95,67,79,76,79,78,61,48,120,50,97,44,83,69,86,69,78,61,48,120,50,49,44,83,73,88,61,48,120,50,48,44,83,76,65,83,72,61,48,120,50,101,44,83,76,69,69,80,61,48,120,54,55,44,83,80,65,67,69,61,48,120,51,48,44,83,84,65,82,61,48,120,57,51,44,83,84,79,80,61,48,120,56,100,44,83,89,83,82,81,61,48,120,55,102,44,84,61,48,120,49,52,44,84,65,66,61,48,120,54,97,44,84,72,82,69,69,61,48,120,49,100,44,84,87,79,61,48,120,49,99,44,85,61,48,120,49,53,44,85,78,68,79,61,48,120,55,54,44,85,80,61,48,120,54,48,44,86,61,48,120,49,54,44,86,79,76,85,77,69,95,68,79,87,78,61,48,120,56,53,44,86,79,76,85,77,69,95,85,80,61,48,120,56,52,44,87,61,48,120,49,55,44,87,65,75,69,61,48,120,54,54,44,87,73,78,95,67,79,78,84,82,79,76,61,48,120,56,51,44,88,61,48,120,49,56,44,89,61,48,120,49,57,44,90,61,48,120,49,97,44,90,69,82,79,61,48,120,50,52,10,99,46,75,81,58,65,76,84,61,48,120,54,48,44,65,76,84,71,82,61,48,120,52,48,44,67,65,80,83,95,76,79,67,75,61,48,120,52,44,67,79,77,77,65,78,68,61,48,120,49,56,48,44,67,79,78,84,82,79,76,61,48,120,49,56,44,67,84,82,76,61,48,120,49,56,44,68,69,65,68,95,75,69,89,61,48,120,49,48,48,48,48,44,73,78,70,79,61,48,120,51,99,48,52,44,73,78,83,84,82,85,67,84,73,79,78,95,75,69,89,83,61,48,120,55,56,44,76,95,65,76,84,61,48,120,50,48,44,76,95,67,79,77,77,65,78,68,61,48,120,56,48,44,76,95,67,79,78,84,82,79,76,61,48,120,56,44,76,95,67,84,82,76,61,48,120,56,44,76,95,83,72,73,70,84,61,48,120,49,44,78,79,84,95,80,82,73,78,84,65,66,76,69,61,48,120,50,48,48,48,44,78,85,77,95,76,79,67,75,61,48,120,56,48,48,48,44,78,85,77,95,80,65,68,61,48,120,50,48,48,44,80,82,69,83,83,69,68,61,48,120,49,48,48,48,44,81,85,65,76,73,70,73,69,82,83,61,48,120,49,102,98,44,82,69,76,69,65,83,69,68,61,48,120,56,48,48,44,82,69,80,69,65,84,61,48,120,52,48,48,44,82,95,65,76,84,61,48,120,52,48,44,82,95,67,79,77,77,65,78,68,61,48,120,49,48,48,44,82,95,67,79,78,84,82,79,76,61,48,120,49,48,44,82,95,67,84,82,76,61,48,120,49,48,44,82,95,83,72,73,70,84,61,48,120,50,44,83,67,82,95,76,79,67,75,61,48,120,52,48,48,48,44,83,72,73,70,84,61,48,120,51,44,87,73,78,95,67,79,78,84,82,79,76,61,48,120,50,48,48,48,48,10,99,46,76,65,89,79,85,84,58,66,65,67,75,71,82,79,85,78,68,61,48,120,56,44,69,77,66,69,68,68,69,68,61,48,120,50,48,44,70,79,82,69,71,82,79,85,78,68,61,48,120,49,48,44,73,71,78,79,82,69,95,67,85,82,83,79,82,61,48,120,56,48,44,76,69,70,84,61,48,120,50,44,76,79,67,75,61,48,120,52,48,44,82,73,71,72,84,61,48,120,52,44,83,81,85,65,82,69,61,48,120,48,44,84,73,71,72,84,61,48,120,49,44,84,73,76,69,61,48,120,49,48,48,44,87,73,68,69,61,48,120,54,10,99,46,76,68,70,58,67,72,69,67,75,95,69,88,73,83,84,83,61,48,120,49,10,99,46,76,79,67,58,68,73,82,69,67,84,79,82,89,61,48,120,49,44,70,73,76,69,61,48,120,51,44,70,79,76,68,69,82,61,48,120,49,44,86,79,76,85,77,69,61,48,120,50,10,99,46,77,65,88,58,70,73,76,69,78,65,77,69,61,48,120,49,48,48,44,78,65,77,69,95,76,69,78,61,48,120,49,102,10,99,46,77,69,77,58,65,85,68,73,79,61,48,120,56,44,67,65,76,76,69,82,61,48,120,56,48,48,48,48,48,44,67,79,68,69,61,48,120,49,48,44,67,79,76,76,69,67,84,61,48,120,49,48,48,48,44,68,65,84,65,61,48,120,48,44,69,88,67,76,85,83,73,86,69,61,48,120,56,48,48,44,72,73,68,68,69,78,61,48,120,49,48,48,48,48,48,44,77,65,78,65,71,69,68,61,48,120,49,44,78,79,95,66,76,79,67,75,61,48,120,50,48,48,48,44,78,79,95,66,76,79,67,75,73,78,71,61,48,120,50,48,48,48,44,78,79,95,67,76,69,65,82,61,48,120,52,48,48,48,48,44,78,79,95,76,79,67,75,61,48,120,52,48,48,44,78,79,95,80,79,79,76,61,48,120,50,48,44,79,66,74,69,67,84,61,48,120,50,48,48,44,82,69,65,68,61,48,120,49,48,48,48,48,44,82,69,65,68,95,87,82,73,84,69,61,48,120,51,48,48,48,48,44,83,84,82,73,78,71,61,48,120,49,48,48,44,84,69,88,84,85,82,69,61,48,120,52,44,84,77,80,95,76,79,67,75,61,48,120,52,48,44,85,78,84,82,65,67,75,69,68,61,48,120,56,48,44,86,73,68,69,79,61,48,120,50,44,87,82,73,84,69,61,48,120,50,48,48,48,48,10,99,46,77,70,70,58,65,84,84,82,73,66,61,48,120,50,48,44,67,76,79,83,69,68,61,48,120,56,48,44,67,82,69,65,84,69,61,48,120,52,44,68,69,69,80,61,48,120,49,48,48,48,44,68,69,76,69,84,69,61,48,120,56,44,70,73,76,69,61,48,120,52,48,48,44,70,79,76,68,69,82,61,48,120,50,48,48,44,77,79,68,73,70,89,61,48,120,50,44,77,79,86,69,68,61,48,120,49,48,44,79,80,69,78,69,68,61,48,120,52,48,44,82,69,65,68,61,48,120,49,44,82,69,78,65,77,69,61,48,120,49,48,44,83,69,76,70,61,48,120,56,48,48,44,85,78,77,79,85,78,84,61,48,120,49,48,48,44,87,82,73,84,69,61,48,120,50,10,99,46,77,72,70,58,68,69,70,65,85,76,84,61,48,120,50,44,83,84,65,84,73,67,61,48,120,49,44,83,84,82,85,67,84,85,82,69,61,48,120,50,10,99,46,77,79,70,58,76,73,78,75,95,76,73,66,82,65,82,89,61,48,120,49,44,83,84,65,84,73,67,61,48,120,50,44,83,89,83,84,69,77,95,80,82,79,66,69,61,48,120,52,10,99,46,77,79,86,69,58,65,76,76,61,48,120,102,44,68,79,87,78,61,48,120,49,44,76,69,70,84,61,48,120,52,44,82,73,71,72,84,61,48,120,56,44,85,80,61,48,120,50,10,99,46,77,83,70,58,65,68,68,61,48,120,56,44,65,68,68,82,69,83,83,61,48,120,49,48,44,77,69,83,83,65,71,69,95,73,68,61,48,120,50,48,44,78,79,95,68,85,80,76,73,67,65,84,69,61,48,120,52,44,85,80,68,65,84,69,61,48,120,50,44,87,65,73,84,61,48,120,49,10,99,46,77,83,71,73,68,58,65,67,84,73,79,78,61,48,120,54,51,44,66,82,69,65,75,61,48,120,54,52,44,67,79,77,77,65,78,68,61,48,120,54,53,44,67,79,82,69,95,69,78,68,61,48,120,54,52,44,68,69,66,85,71,61,48,120,53,102,44,69,86,69,78,84,61,48,120,53,101,44,70,82,69,69,61,48,120,54,50,44,81,85,73,84,61,48,120,51,101,56,44,84,72,82,69,65,68,95,65,67,84,73,79,78,61,48,120,53,98,44,84,72,82,69,65,68,95,67,65,76,76,66,65,67,75,61,48,120,53,99,44,86,65,76,73,68,65,84,69,95,80,82,79,67,69,83,83,61,48,120,53,100,44,87,65,73,84,95,70,79,82,95,79,66,74,69,67,84,83,61,48,120,53,97,10,99,46,77,84,70,58,65,78,73,77,61,48,120,56,44,82,69,76,65,84,73,86,69,61,48,120,49,48,44,88,61,48,120,49,44,89,61,48,120,50,44,90,61,48,120,52,10,99,46,78,69,84,77,83,71,58,69,78,68,61,48,120,49,44,83,84,65,82,84,61,48,120,48,10,99,46,78,70,58,67,79,76,76,69,67,84,61,48,120,56,48,44,70,82,69,69,61,48,120,49,48,44,70,82,69,69,95,79,78,95,85,78,76,79,67,75,61,48,120,56,44,73,78,73,84,73,65,76,73,83,69,68,61,48,120,50,44,76,79,67,65,76,61,48,120,52,44,77,69,83,83,65,71,69,61,48,120,50,48,48,44,78,65,77,69,61,48,120,56,48,48,48,48,48,48,48,44,80,82,73,86,65,84,69,61,48,120,48,44,82,69,67,76,65,83,83,69,68,61,48,120,49,48,48,44,83,73,71,78,65,76,76,69,68,61,48,120,52,48,48,44,83,85,80,80,82,69,83,83,95,76,79,71,61,48,120,52,48,44,84,73,77,69,82,95,83,85,66,61,48,120,50,48,44,85,78,73,81,85,69,61,48,120,52,48,48,48,48,48,48,48,44,85,78,84,82,65,67,75,69,68,61,48,120,49,10,99,46,79,80,70,58,65,82,71,83,61,48,120,52,48,44,68,69,84,65,73,76,61,48,120,52,44,69,82,82,79,82,61,48,120,56,48,44,77,65,88,95,68,69,80,84,72,61,48,120,50,44,77,79,68,85,76,69,95,80,65,84,72,61,48,120,52,48,48,44,79,80,84,73,79,78,83,61,48,120,49,44,80,82,73,86,73,76,69,71,69,68,61,48,120,49,48,48,44,82,79,79,84,95,80,65,84,72,61,48,120,56,48,48,44,83,67,65,78,95,77,79,68,85,76,69,83,61,48,120,49,48,48,48,44,83,72,79,87,95,69,82,82,79,82,83,61,48,120,50,48,44,83,72,79,87,95,73,79,61,48,120,49,48,44,83,72,79,87,95,77,69,77,79,82,89,61,48,120,56,44,83,89,83,84,69,77,95,80,65,84,72,61,48,120,50,48,48,10,99,46,80,69,82,77,73,84,58,65,76,76,95,68,69,76,69,84,69,61,48,120,56,56,56,44,65,76,76,95,69,88,69,67,61,48,120,52,52,52,44,65,76,76,95,82,69,65,68,61,48,120,49,49,49,44,65,76,76,95,87,82,73,84,69,61,48,120,50,50,50,44,65,82,67,72,73,86,69,61,48,120,50,48,48,48,44,68,69,76,69,84,69,61,48,120,56,44,69,86,69,82,89,79,78,69,95,65,67,67,69,83,83,61,48,120,102,102,102,44,69,86,69,82,89,79,78,69,95,68,69,76,69,84,69,61,48,120,56,56,56,44,69,86,69,82,89,79,78,69,95,69,88,69,67,61,48,120,52,52,52,44,69,86,69,82,89,79,78,69,95,82,69,65,68,61,48,120,49,49,49,44,69,86,69,82,89,79,78,69,95,82,69,65,68,87,82,73,84,69,61,48,120,51,51,51,44,69,86,69,82,89,79,78,69,95,87,82,73,84,69,61,48,120,50,50,50,44,69,88,69,67,61,48,120,52,44,71,82,79,85,80,61,48,120,102,48,44,71,82,79,85,80,73,68,61,48,120,49,48,48,48,48,44,71,82,79,85,80,95,68,69,76,69,84,69,61,48,120,56,48,44,71,82,79,85,80,95,69,88,69,67,61,48,120,52,48,44,71,82,79,85,80,95,82,69,65,68,61,48,120,49,48,44,71,82,79,85,80,95,87,82,73,84,69,61,48,120,50,48,44,72,73,68,68,69,78,61,48,120,49,48,48,48,44,73,78,72,69,82,73,84,61,48,120,50,48,48,48,48,44,78,69,84,87,79,82,75,61,48,120,56,48,48,48,48,44,79,70,70,76,73,78,69,61,48,120,52,48,48,48,48,44,79,84,72,69,82,83,61,48,120,102,48,48,44,79,84,72,69,82,83,95,68,69,76,69,84,69,61,48,120,56,48,48,44,79,84,72,69,82,83,95,69,88,69,67,61,48,120,52,48,48,44,79,84,72,69,82,83,95,82,69,65,68,61,48,120,49,48,48,44,79,84,72,69,82,83,95,87,82,73,84,69,61,48,120,50,48,48,44,80,65,83,83,87,79,82,68,61,48,120,52,48,48,48,44,82,69,65,68,61,48,120,49,44,85,83,69,82,61,48,120,102,44,85,83,69,82,73,68,61,48,120,56,48,48,48,44,85,83,69,82,95,69,88,69,67,61,48,120,52,44,85,83,69,82,95,82,69,65,68,61,48,120,49,44,85,83,69,82,95,87,82,73,84,69,61,48,120,50,44,87,82,73,84,69,61,48,120,50,10,99,46,80,77,70,58,83,89,83,84,69,77,95,78,79,95,66,82,69,65,75,61,48,120,49,10,99,46,80,84,67,58,67,82,79,83,83,72,65,73,82,61,48,120,97,44,67,85,83,84,79,77,61,48,120,49,55,44,68,69,70,65,85,76,84,61,48,120,49,44,68,82,65,71,71,65,66,76,69,61,48,120,49,56,44,69,78,68,61,48,120,49,57,44,72,65,78,68,61,48,120,49,48,44,72,65,78,68,95,76,69,70,84,61,48,120,49,49,44,72,65,78,68,95,82,73,71,72,84,61,48,120,49,50,44,73,78,86,73,83,73,66,76,69,61,48,120,49,54,44,77,65,71,78,73,70,73,69,82,61,48,120,102,44,78,79,95,67,72,65,78,71,69,61,48,120,48,44,80,65,73,78,84,66,82,85,83,72,61,48,120,49,52,44,83,73,90,69,95,66,79,84,84,79,77,61,48,120,57,44,83,73,90,69,95,66,79,84,84,79,77,95,76,69,70,84,61,48,120,50,44,83,73,90,69,95,66,79,84,84,79,77,95,82,73,71,72,84,61,48,120,51,44,83,73,90,69,95,76,69,70,84,61,48,120,54,44,83,73,90,69,95,82,73,71,72,84,61,48,120,55,44,83,73,90,69,95,84,79,80,61,48,120,56,44,83,73,90,69,95,84,79,80,95,76,69,70,84,61,48,120,52,44,83,73,90,69,95,84,79,80,95,82,73,71,72,84,61,48,120,53,44,83,73,90,73,78,71,61,48,120,99,44,83,76,69,69,80,61,48,120,98,44,83,80,76,73,84,95,72,79,82,73,90,79,78,84,65,76,61,48,120,101,44,83,80,76,73,84,95,86,69,82,84,73,67,65,76,61,48,120,100,44,83,84,79,80,61,48,120,49,53,44,84,69,88,84,61,48,120,49,51,10,99,46,82,68,70,58,65,82,67,72,73,86,69,61,48,120,50,48,48,48,44,68,65,84,69,61,48,120,50,44,70,73,76,69,61,48,120,56,44,70,73,76,69,83,61,48,120,56,44,70,79,76,68,69,82,61,48,120,49,48,44,70,79,76,68,69,82,83,61,48,120,49,48,44,72,73,68,68,69,78,61,48,120,49,48,48,44,76,73,78,75,61,48,120,52,48,44,79,80,69,78,68,73,82,61,48,120,52,48,48,48,44,80,69,82,77,73,83,83,73,79,78,83,61,48,120,52,44,81,85,65,76,73,70,73,69,68,61,48,120,50,48,48,44,81,85,65,76,73,70,89,61,48,120,50,48,48,44,82,69,65,68,95,65,76,76,61,48,120,49,102,44,82,69,65,68,95,79,78,76,89,61,48,120,49,48,48,48,44,83,73,90,69,61,48,120,49,44,83,84,82,69,65,77,61,48,120,56,48,48,44,84,65,71,83,61,48,120,56,48,44,84,73,77,69,61,48,120,50,44,86,73,82,84,85,65,76,61,48,120,52,48,48,44,86,79,76,85,77,69,61,48,120,50,48,10,99,46,82,69,83,58,67,79,78,83,79,76,69,95,70,68,61,48,120,50,44,67,79,82,69,95,73,68,76,61,48,120,56,44,67,80,85,95,83,80,69,69,68,61,48,120,49,54,44,68,73,83,80,76,65,89,95,68,82,73,86,69,82,61,48,120,53,44,69,88,67,69,80,84,73,79,78,95,72,65,78,68,76,69,82,61,48,120,49,49,44,70,82,69,69,95,77,69,77,79,82,89,61,48,120,49,55,44,70,82,69,69,95,83,87,65,80,61,48,120,49,44,74,78,73,95,69,78,86,61,48,120,101,44,75,69,89,95,83,84,65,84,69,61,48,120,51,44,76,79,71,95,68,69,80,84,72,61,48,120,100,44,76,79,71,95,76,69,86,69,76,61,48,120,97,44,77,65,88,95,80,82,79,67,69,83,83,69,83,61,48,120,99,44,78,69,84,95,80,82,79,67,69,83,83,73,78,71,61,48,120,49,50,44,79,80,69,78,95,73,78,70,79,61,48,120,49,48,44,80,82,73,86,73,76,69,71,69,68,61,48,120,55,44,80,82,73,86,73,76,69,71,69,68,95,85,83,69,82,61,48,120,54,44,80,82,79,67,69,83,83,95,83,84,65,84,69,61,48,120,49,51,44,83,84,65,84,73,67,95,66,85,73,76,68,61,48,120,57,44,84,72,82,69,65,68,95,73,68,61,48,120,102,44,84,79,84,65,76,95,77,69,77,79,82,89,61,48,120,49,52,44,84,79,84,65,76,95,83,72,65,82,69,68,95,77,69,77,79,82,89,61,48,120,98,44,84,79,84,65,76,95,83,87,65,80,61,48,120,49,53,44,85,83,69,82,95,73,68,61,48,120,52,10,99,46,82,70,68,58,65,76,76,79,87,95,82,69,67,85,82,83,73,79,78,61,48,120,50,48,44,65,76,87,65,89,83,95,67,65,76,76,61,48,120,49,48,48,44,69,88,67,69,80,84,61,48,120,50,44,82,69,65,68,61,48,120,52,44,82,69,67,65,76,76,61,48,120,56,48,44,82,69,77,79,86,69,61,48,120,56,44,83,79,67,75,69,84,61,48,120,52,48,44,83,84,79,80,95,82,69,67,85,82,83,69,61,48,120,49,48,44,87,82,73,84,69,61,48,120,49,10,99,46,82,80,58,77,79,68,85,76,69,95,80,65,84,72,61,48,120,49,44,82,79,79,84,95,80,65,84,72,61,48,120,51,44,83,89,83,84,69,77,95,80,65,84,72,61,48,120,50,10,99,46,82,83,70,58,65,80,80,82,79,88,73,77,65,84,69,61,48,120,52,44,67,65,83,69,95,83,69,78,83,73,84,73,86,69,61,48,120,50,48,44,67,72,69,67,75,95,86,73,82,84,85,65,76,61,48,120,50,44,78,79,95,68,69,69,80,95,83,67,65,78,61,48,120,56,44,78,79,95,70,73,76,69,95,67,72,69,67,75,61,48,120,49,44,80,65,84,72,61,48,120,49,48,10,99,46,83,67,70,58,69,88,73,84,95,79,78,95,69,82,82,79,82,61,48,120,49,44,76,79,71,95,65,76,76,61,48,120,50,10,99,46,83,69,69,75,58,67,85,82,82,69,78,84,61,48,120,49,44,69,78,68,61,48,120,50,44,82,69,76,65,84,73,86,69,61,48,120,51,44,83,84,65,82,84,61,48,120,48,10,99,46,83,84,82,58,67,65,83,69,61,48,120,49,44,77,65,84,67,72,95,67,65,83,69,61,48,120,49,44,77,65,84,67,72,95,76,69,78,61,48,120,50,10,99,46,83,84,84,58,70,76,79,65,84,61,48,120,50,44,72,69,88,61,48,120,51,44,78,85,77,66,69,82,61,48,120,49,44,83,84,82,73,78,71,61,48,120,52,10,99,46,84,72,70,58,65,85,84,79,95,70,82,69,69,61,48,120,49,10,99,46,84,79,73,58,65,78,68,82,79,73,68,95,65,83,83,69,84,77,71,82,61,48,120,52,44,65,78,68,82,79,73,68,95,67,76,65,83,83,61,48,120,51,44,65,78,68,82,79,73,68,95,69,78,86,61,48,120,50,44,76,79,67,65,76,95,67,65,67,72,69,61,48,120,48,44,76,79,67,65,76,95,83,84,79,82,65,71,69,61,48,120,49,10,99,46,84,83,70,58,65,84,84,65,67,72,69,68,61,48,120,49,48,48,44,68,69,84,65,67,72,69,68,61,48,120,56,48,44,70,79,82,69,73,71,78,61,48,120,49,44,76,79,71,95,65,76,76,61,48,120,50,48,44,80,73,80,69,61,48,120,50,48,48,44,80,82,73,86,73,76,69,71,69,68,61,48,120,56,44,81,85,73,69,84,61,48,120,52,48,44,82,69,83,69,84,95,80,65,84,72,61,48,120,52,44,83,72,69,76,76,61,48,120,49,48,44,87,65,73,84,61,48,120,50,10,99,46,84,83,84,65,84,69,58,80,65,85,83,69,68,61,48,120,49,44,82,85,78,78,73,78,71,61,48,120,48,44,83,84,79,80,80,73,78,71,61,48,120,50,44,84,69,82,77,73,78,65,84,69,68,61,48,120,51,10,99,46,86,65,83,58,67,65,83,69,95,83,69,78,83,73,84,73,86,69,61,48,120,102,44,67,76,79,83,69,95,68,73,82,61,48,120,54,44,67,82,69,65,84,69,95,76,73,78,75,61,48,120,49,49,44,68,69,76,69,84,69,61,48,120,51,44,68,69,82,69,71,73,83,84,69,82,61,48,120,49,44,68,82,73,86,69,82,95,83,73,90,69,61,48,120,49,50,44,71,69,84,95,68,69,86,73,67,69,95,73,78,70,79,61,48,120,98,44,71,69,84,95,73,78,70,79,61,48,120,97,44,73,68,69,78,84,73,70,89,95,70,73,76,69,61,48,120,99,44,73,71,78,79,82,69,95,70,73,76,69,61,48,120,57,44,77,65,75,69,95,68,73,82,61,48,120,100,44,79,80,69,78,95,68,73,82,61,48,120,53,44,82,69,65,68,95,76,73,78,75,61,48,120,49,48,44,82,69,78,65,77,69,61,48,120,52,44,83,65,77,69,95,70,73,76,69,61,48,120,101,44,83,67,65,78,95,68,73,82,61,48,120,50,44,84,69,83,84,95,80,65,84,72,61,48,120,55,44,87,65,84,67,72,95,80,65,84,72,61,48,120,56,10,99,46,86,76,70,58,65,80,73,61,48,120,50,48,44,66,82,65,78,67,72,61,48,120,49,44,67,82,73,84,73,67,65,76,61,48,120,56,44,68,69,84,65,73,76,61,48,120,52,48,44,69,82,82,79,82,61,48,120,50,44,70,85,78,67,84,73,79,78,61,48,120,49,48,48,44,73,78,70,79,61,48,120,49,48,44,84,82,65,67,69,61,48,120,56,48,44,87,65,82,78,73,78,71,61,48,120,52,10,99,46,86,79,76,85,77,69,58,72,73,68,68,69,78,61,48,120,52,44,80,82,73,79,82,73,84,89,61,48,120,50,44,82,69,80,76,65,67,69,61,48,120,49,44,83,89,83,84,69,77,61,48,120,56,10,0 }; +char glIDL[] = { 115,46,73,110,112,117,116,69,118,101,110,116,58,112,78,101,120,116,58,73,110,112,117,116,69,118,101,110,116,44,100,86,97,108,117,101,44,120,84,105,109,101,115,116,97,109,112,44,108,82,101,99,105,112,105,101,110,116,73,68,44,108,79,118,101,114,73,68,44,100,65,98,115,88,44,100,65,98,115,89,44,100,88,44,100,89,44,108,68,101,118,105,99,101,73,68,44,108,84,121,112,101,44,108,70,108,97,103,115,44,108,77,97,115,107,10,115,46,100,99,82,101,113,117,101,115,116,58,108,73,116,101,109,44,99,80,114,101,102,101,114,101,110,99,101,91,52,93,10,115,46,100,99,65,117,100,105,111,58,108,83,105,122,101,44,108,70,111,114,109,97,116,10,115,46,100,99,75,101,121,69,110,116,114,121,58,108,70,108,97,103,115,44,108,86,97,108,117,101,44,120,84,105,109,101,115,116,97,109,112,44,108,85,110,105,99,111,100,101,10,115,46,100,99,68,101,118,105,99,101,73,110,112,117,116,58,100,86,97,108,117,101,115,91,50,93,44,120,84,105,109,101,115,116,97,109,112,44,108,68,101,118,105,99,101,73,68,44,108,70,108,97,103,115,44,108,84,121,112,101,10,115,46,68,97,116,101,84,105,109,101,58,119,89,101,97,114,44,99,77,111,110,116,104,44,99,68,97,121,44,99,72,111,117,114,44,99,77,105,110,117,116,101,44,99,83,101,99,111,110,100,44,99,84,105,109,101,90,111,110,101,10,115,46,72,83,86,58,100,72,117,101,44,100,83,97,116,117,114,97,116,105,111,110,44,100,86,97,108,117,101,44,100,65,108,112,104,97,10,115,46,70,82,71,66,58,102,82,101,100,44,102,71,114,101,101,110,44,102,66,108,117,101,44,102,65,108,112,104,97,10,115,46,82,71,66,56,58,117,99,82,101,100,44,117,99,71,114,101,101,110,44,117,99,66,108,117,101,44,117,99,65,108,112,104,97,10,115,46,82,71,66,49,54,58,117,119,82,101,100,44,117,119,71,114,101,101,110,44,117,119,66,108,117,101,44,117,119,65,108,112,104,97,10,115,46,82,71,66,51,50,58,117,108,82,101,100,44,117,108,71,114,101,101,110,44,117,108,66,108,117,101,44,117,108,65,108,112,104,97,10,115,46,82,71,66,80,97,108,101,116,116,101,58,108,65,109,116,67,111,108,111,117,114,115,44,101,67,111,108,58,82,71,66,56,91,50,53,54,93,10,115,46,67,111,108,111,117,114,70,111,114,109,97,116,58,117,99,82,101,100,83,104,105,102,116,44,117,99,71,114,101,101,110,83,104,105,102,116,44,117,99,66,108,117,101,83,104,105,102,116,44,117,99,65,108,112,104,97,83,104,105,102,116,44,117,99,82,101,100,77,97,115,107,44,117,99,71,114,101,101,110,77,97,115,107,44,117,99,66,108,117,101,77,97,115,107,44,117,99,65,108,112,104,97,77,97,115,107,44,117,99,82,101,100,80,111,115,44,117,99,71,114,101,101,110,80,111,115,44,117,99,66,108,117,101,80,111,115,44,117,99,65,108,112,104,97,80,111,115,44,117,99,66,105,116,115,80,101,114,80,105,120,101,108,10,115,46,67,108,105,112,82,101,99,116,97,110,103,108,101,58,108,76,101,102,116,44,108,84,111,112,44,108,82,105,103,104,116,44,108,66,111,116,116,111,109,10,115,46,69,100,103,101,115,58,108,76,101,102,116,44,108,84,111,112,44,108,82,105,103,104,116,44,108,66,111,116,116,111,109,10,115,46,79,98,106,101,99,116,83,105,103,110,97,108,58,111,79,98,106,101,99,116,10,115,46,70,117,110,99,116,105,111,110,70,105,101,108,100,58,115,78,97,109,101,44,117,108,84,121,112,101,10,115,46,70,117,110,99,116,105,111,110,58,112,65,100,100,114,101,115,115,44,115,78,97,109,101,44,112,65,114,103,115,58,70,117,110,99,116,105,111,110,70,105,101,108,100,10,115,46,70,105,101,108,100,65,114,114,97,121,58,115,78,97,109,101,44,112,71,101,116,70,105,101,108,100,44,112,83,101,116,70,105,101,108,100,44,109,65,114,103,44,117,108,70,108,97,103,115,10,115,46,70,105,101,108,100,68,101,102,58,115,78,97,109,101,44,108,86,97,108,117,101,10,115,46,83,121,115,116,101,109,83,116,97,116,101,58,115,80,108,97,116,102,111,114,109,44,108,67,111,110,115,111,108,101,70,68,44,108,83,116,97,103,101,10,115,46,85,110,105,116,58,100,86,97,108,117,101,44,117,108,84,121,112,101,10,115,46,65,99,116,105,111,110,65,114,114,97,121,58,112,82,111,117,116,105,110,101,44,108,65,99,116,105,111,110,67,111,100,101,10,115,46,65,99,116,105,111,110,84,97,98,108,101,58,117,108,72,97,115,104,44,108,83,105,122,101,44,115,78,97,109,101,44,112,65,114,103,115,58,70,117,110,99,116,105,111,110,70,105,101,108,100,10,115,46,67,104,105,108,100,69,110,116,114,121,58,108,79,98,106,101,99,116,73,68,44,117,108,67,108,97,115,115,73,68,10,115,46,77,101,115,115,97,103,101,58,120,84,105,109,101,44,108,85,73,68,44,108,84,121,112,101,44,108,83,105,122,101,10,115,46,77,101,109,73,110,102,111,58,112,83,116,97,114,116,44,108,79,98,106,101,99,116,73,68,44,117,108,83,105,122,101,44,108,70,108,97,103,115,44,108,77,101,109,111,114,121,73,68,44,119,65,99,99,101,115,115,67,111,117,110,116,10,115,46,67,111,109,112,114,101,115,115,105,111,110,70,101,101,100,98,97,99,107,58,108,70,101,101,100,98,97,99,107,73,68,44,108,73,110,100,101,120,44,115,80,97,116,104,44,115,68,101,115,116,44,120,80,114,111,103,114,101,115,115,44,120,79,114,105,103,105,110,97,108,83,105,122,101,44,120,67,111,109,112,114,101,115,115,101,100,83,105,122,101,44,119,89,101,97,114,44,119,77,111,110,116,104,44,119,68,97,121,44,119,72,111,117,114,44,119,77,105,110,117,116,101,44,119,83,101,99,111,110,100,10,115,46,67,111,109,112,114,101,115,115,101,100,73,116,101,109,58,120,79,114,105,103,105,110,97,108,83,105,122,101,44,120,67,111,109,112,114,101,115,115,101,100,83,105,122,101,44,112,78,101,120,116,58,67,111,109,112,114,101,115,115,101,100,73,116,101,109,44,115,80,97,116,104,44,108,80,101,114,109,105,115,115,105,111,110,115,44,108,85,115,101,114,73,68,44,108,71,114,111,117,112,73,68,44,108,79,116,104,101,114,115,73,68,44,108,70,108,97,103,115,44,101,67,114,101,97,116,101,100,58,68,97,116,101,84,105,109,101,44,101,77,111,100,105,102,105,101,100,58,68,97,116,101,84,105,109,101,10,115,46,70,105,108,101,73,110,102,111,58,120,83,105,122,101,44,120,84,105,109,101,83,116,97,109,112,44,112,78,101,120,116,58,70,105,108,101,73,110,102,111,44,115,78,97,109,101,44,108,70,108,97,103,115,44,108,80,101,114,109,105,115,115,105,111,110,115,44,108,85,115,101,114,73,68,44,108,71,114,111,117,112,73,68,44,101,67,114,101,97,116,101,100,58,68,97,116,101,84,105,109,101,44,101,77,111,100,105,102,105,101,100,58,68,97,116,101,84,105,109,101,10,115,46,68,105,114,73,110,102,111,58,112,73,110,102,111,58,70,105,108,101,73,110,102,111,10,115,46,70,105,108,101,70,101,101,100,98,97,99,107,58,120,83,105,122,101,44,120,80,111,115,105,116,105,111,110,44,115,80,97,116,104,44,115,68,101,115,116,44,108,70,101,101,100,98,97,99,107,73,68,44,99,82,101,115,101,114,118,101,100,91,51,50,93,10,115,46,70,105,101,108,100,58,109,65,114,103,44,112,71,101,116,86,97,108,117,101,44,112,83,101,116,86,97,108,117,101,44,112,87,114,105,116,101,86,97,108,117,101,44,115,78,97,109,101,44,117,108,70,105,101,108,100,73,68,44,117,119,79,102,102,115,101,116,44,117,119,73,110,100,101,120,44,117,108,70,108,97,103,115,10,99,46,65,67,58,65,99,116,105,118,97,116,101,61,48,120,50,44,67,108,101,97,114,61,48,120,52,44,67,108,105,112,98,111,97,114,100,61,48,120,50,100,44,67,111,112,121,68,97,116,97,61,48,120,55,44,68,97,116,97,70,101,101,100,61,48,120,56,44,68,101,97,99,116,105,118,97,116,101,61,48,120,57,44,68,105,115,97,98,108,101,61,48,120,50,102,44,68,114,97,103,68,114,111,112,61,48,120,49,48,44,68,114,97,119,61,48,120,97,44,69,78,68,61,48,120,51,49,44,69,110,97,98,108,101,61,48,120,54,44,70,108,117,115,104,61,48,120,98,44,70,111,99,117,115,61,48,120,99,44,70,114,101,101,61,48,120,100,44,70,114,101,101,87,97,114,110,105,110,103,61,48,120,53,44,71,101,116,75,101,121,61,48,120,102,44,72,105,100,101,61,48,120,49,49,44,73,110,105,116,61,48,120,49,50,44,76,111,99,107,61,48,120,49,51,44,76,111,115,116,70,111,99,117,115,61,48,120,49,52,44,77,111,118,101,61,48,120,49,53,44,77,111,118,101,84,111,66,97,99,107,61,48,120,49,54,44,77,111,118,101,84,111,70,114,111,110,116,61,48,120,49,55,44,77,111,118,101,84,111,80,111,105,110,116,61,48,120,50,51,44,78,101,119,67,104,105,108,100,61,48,120,49,56,44,78,101,119,79,98,106,101,99,116,61,48,120,49,97,44,78,101,119,79,119,110,101,114,61,48,120,49,57,44,78,101,119,80,108,97,99,101,109,101,110,116,61,48,120,51,48,44,78,101,120,116,61,48,120,50,57,44,80,114,101,118,61,48,120,50,97,44,81,117,101,114,121,61,48,120,49,99,44,82,101,97,100,61,48,120,49,100,44,82,101,100,105,109,101,110,115,105,111,110,61,48,120,51,44,82,101,100,111,61,48,120,49,98,44,82,101,102,114,101,115,104,61,48,120,50,101,44,82,101,110,97,109,101,61,48,120,49,101,44,82,101,115,101,116,61,48,120,49,102,44,82,101,115,105,122,101,61,48,120,50,48,44,83,97,118,101,73,109,97,103,101,61,48,120,50,49,44,83,97,118,101,83,101,116,116,105,110,103,115,61,48,120,101,44,83,97,118,101,84,111,79,98,106,101,99,116,61,48,120,50,50,44,83,101,101,107,61,48,120,50,52,44,83,101,116,70,105,101,108,100,61,48,120,50,99,44,83,101,116,75,101,121,61,48,120,50,53,44,83,104,111,119,61,48,120,50,54,44,83,105,103,110,97,108,61,48,120,49,44,85,110,100,111,61,48,120,50,55,44,85,110,108,111,99,107,61,48,120,50,56,44,87,114,105,116,101,61,48,120,50,98,10,99,46,65,76,73,71,78,58,66,79,84,84,79,77,61,48,120,50,48,44,67,69,78,84,69,82,61,48,120,99,44,72,79,82,73,90,79,78,84,65,76,61,48,120,52,44,76,69,70,84,61,48,120,49,44,77,73,68,68,76,69,61,48,120,99,44,82,73,71,72,84,61,48,120,50,44,84,79,80,61,48,120,49,48,44,86,69,82,84,73,67,65,76,61,48,120,56,10,99,46,67,67,70,58,65,85,68,73,79,61,48,120,56,48,44,67,79,77,77,65,78,68,61,48,120,49,44,68,65,84,65,61,48,120,49,48,48,44,70,73,76,69,83,89,83,84,69,77,61,48,120,50,44,71,82,65,80,72,73,67,83,61,48,120,52,44,71,85,73,61,48,120,56,44,73,79,61,48,120,49,48,44,77,73,83,67,61,48,120,50,48,48,44,77,85,76,84,73,77,69,68,73,65,61,48,120,56,48,48,44,78,69,84,87,79,82,75,61,48,120,52,48,48,44,83,89,83,84,69,77,61,48,120,50,48,44,84,79,79,76,61,48,120,52,48,10,99,46,67,70,58,68,69,70,76,65,84,69,61,48,120,51,44,71,90,73,80,61,48,120,49,44,90,76,73,66,61,48,120,50,10,99,46,67,76,70,58,73,78,72,69,82,73,84,95,76,79,67,65,76,61,48,120,49,44,78,79,95,79,87,78,69,82,83,72,73,80,61,48,120,50,10,99,46,67,76,73,80,77,79,68,69,58,67,79,80,89,61,48,120,50,44,67,85,84,61,48,120,49,44,80,65,83,84,69,61,48,120,52,10,99,46,67,77,70,58,65,80,80,76,89,95,83,69,67,85,82,73,84,89,61,48,120,50,48,44,67,82,69,65,84,69,95,70,73,76,69,61,48,120,52,44,78,69,87,61,48,120,50,44,78,79,95,76,73,78,75,83,61,48,120,49,48,44,80,65,83,83,87,79,82,68,61,48,120,49,44,82,69,65,68,95,79,78,76,89,61,48,120,56,10,99,46,67,78,70,58,65,85,84,79,95,83,65,86,69,61,48,120,50,44,78,69,87,61,48,120,56,44,79,80,84,73,79,78,65,76,95,70,73,76,69,83,61,48,120,52,44,83,84,82,73,80,95,81,85,79,84,69,83,61,48,120,49,10,99,46,67,79,78,58,68,80,65,68,95,68,79,87,78,61,48,120,50,48,44,68,80,65,68,95,76,69,70,84,61,48,120,52,48,44,68,80,65,68,95,82,73,71,72,84,61,48,120,56,48,44,68,80,65,68,95,85,80,61,48,120,49,48,44,71,65,77,69,80,65,68,95,69,61,48,120,50,44,71,65,77,69,80,65,68,95,78,61,48,120,56,44,71,65,77,69,80,65,68,95,83,61,48,120,49,44,71,65,77,69,80,65,68,95,87,61,48,120,52,44,76,69,70,84,95,66,85,77,80,69,82,95,49,61,48,120,52,48,48,44,76,69,70,84,95,66,85,77,80,69,82,95,50,61,48,120,56,48,48,44,76,69,70,84,95,84,72,85,77,66,61,48,120,52,48,48,48,44,82,73,71,72,84,95,66,85,77,80,69,82,95,49,61,48,120,49,48,48,48,44,82,73,71,72,84,95,66,85,77,80,69,82,95,50,61,48,120,50,48,48,48,44,82,73,71,72,84,95,84,72,85,77,66,61,48,120,56,48,48,48,44,83,69,76,69,67,84,61,48,120,50,48,48,44,83,84,65,82,84,61,48,120,49,48,48,10,99,46,68,65,84,65,58,65,85,68,73,79,61,48,120,53,44,67,79,78,84,69,78,84,61,48,120,98,44,68,69,86,73,67,69,95,73,78,80,85,84,61,48,120,51,44,70,73,76,69,61,48,120,97,44,73,77,65,71,69,61,48,120,55,44,73,78,80,85,84,95,82,69,65,68,89,61,48,120,99,44,82,65,87,61,48,120,50,44,82,69,67,69,73,80,84,61,48,120,57,44,82,69,67,79,82,68,61,48,120,54,44,82,69,81,85,69,83,84,61,48,120,56,44,84,69,88,84,61,48,120,49,44,88,77,76,61,48,120,52,10,99,46,68,69,86,73,67,69,58,66,79,79,75,77,65,82,75,61,48,120,52,48,48,48,48,44,67,79,77,80,65,67,84,95,68,73,83,67,61,48,120,49,44,70,73,88,69,68,61,48,120,56,48,48,48,44,70,76,79,80,80,89,95,68,73,83,75,61,48,120,52,44,72,65,82,68,95,68,73,83,75,61,48,120,50,44,77,69,77,79,82,89,61,48,120,49,48,48,48,44,77,79,68,69,77,61,48,120,50,48,48,48,44,78,69,84,87,79,82,75,61,48,120,56,48,44,80,82,73,78,84,69,82,61,48,120,50,48,48,44,80,82,73,78,84,69,82,95,51,68,61,48,120,49,48,48,48,48,44,82,69,65,68,61,48,120,56,44,82,69,77,79,86,65,66,76,69,61,48,120,50,48,44,82,69,77,79,86,69,65,66,76,69,61,48,120,50,48,44,83,67,65,78,78,69,82,61,48,120,52,48,48,44,83,67,65,78,78,69,82,95,51,68,61,48,120,50,48,48,48,48,44,83,79,70,84,87,65,82,69,61,48,120,52,48,44,84,65,80,69,61,48,120,49,48,48,44,84,69,77,80,79,82,65,82,89,61,48,120,56,48,48,44,85,83,66,61,48,120,52,48,48,48,44,87,82,73,84,69,61,48,120,49,48,10,99,46,68,77,70,58,70,73,88,69,68,95,67,69,78,84,69,82,95,88,61,48,120,49,48,48,48,48,48,44,70,73,88,69,68,95,67,69,78,84,69,82,95,89,61,48,120,50,48,48,48,48,48,44,70,73,88,69,68,95,68,69,80,84,72,61,48,120,49,48,48,48,44,70,73,88,69,68,95,72,69,73,71,72,84,61,48,120,49,48,48,44,70,73,88,69,68,95,82,65,68,73,85,83,95,88,61,48,120,50,48,48,48,48,44,70,73,88,69,68,95,82,65,68,73,85,83,95,89,61,48,120,50,48,48,48,48,48,48,44,70,73,88,69,68,95,87,73,68,84,72,61,48,120,50,48,48,44,70,73,88,69,68,95,88,61,48,120,52,44,70,73,88,69,68,95,88,95,79,70,70,83,69,84,61,48,120,52,48,44,70,73,88,69,68,95,89,61,48,120,56,44,70,73,88,69,68,95,89,95,79,70,70,83,69,84,61,48,120,56,48,44,70,73,88,69,68,95,90,61,48,120,52,48,48,48,44,83,67,65,76,69,68,95,67,69,78,84,69,82,95,88,61,48,120,52,48,48,48,48,44,83,67,65,76,69,68,95,67,69,78,84,69,82,95,89,61,48,120,56,48,48,48,48,44,83,67,65,76,69,68,95,68,69,80,84,72,61,48,120,50,48,48,48,44,83,67,65,76,69,68,95,72,69,73,71,72,84,61,48,120,52,48,48,44,83,67,65,76,69,68,95,82,65,68,73,85,83,95,88,61,48,120,49,48,48,48,48,44,83,67,65,76,69,68,95,82,65,68,73,85,83,95,89,61,48,120,49,48,48,48,48,48,48,44,83,67,65,76,69,68,95,87,73,68,84,72,61,48,120,56,48,48,44,83,67,65,76,69,68,95,88,61,48,120,49,44,83,67,65,76,69,68,95,88,95,79,70,70,83,69,84,61,48,120,49,48,44,83,67,65,76,69,68,95,89,61,48,120,50,44,83,67,65,76,69,68,95,89,95,79,70,70,83,69,84,61,48,120,50,48,44,83,67,65,76,69,68,95,90,61,48,120,56,48,48,48,44,83,84,65,84,85,83,95,67,72,65,78,71,69,95,72,61,48,120,52,48,48,48,48,48,44,83,84,65,84,85,83,95,67,72,65,78,71,69,95,86,61,48,120,56,48,48,48,48,48,10,99,46,68,82,76,58,68,79,87,78,61,48,120,49,44,69,65,83,84,61,48,120,50,44,76,69,70,84,61,48,120,51,44,78,79,82,84,72,61,48,120,48,44,78,79,82,84,72,95,69,65,83,84,61,48,120,52,44,78,79,82,84,72,95,87,69,83,84,61,48,120,53,44,82,73,71,72,84,61,48,120,50,44,83,79,85,84,72,61,48,120,49,44,83,79,85,84,72,95,69,65,83,84,61,48,120,54,44,83,79,85,84,72,95,87,69,83,84,61,48,120,55,44,85,80,61,48,120,48,44,87,69,83,84,61,48,120,51,10,99,46,69,68,71,69,58,65,76,76,61,48,120,102,102,44,66,79,84,84,79,77,61,48,120,56,44,66,79,84,84,79,77,95,76,69,70,84,61,48,120,52,48,44,66,79,84,84,79,77,95,82,73,71,72,84,61,48,120,56,48,44,76,69,70,84,61,48,120,50,44,82,73,71,72,84,61,48,120,52,44,84,79,80,61,48,120,49,44,84,79,80,95,76,69,70,84,61,48,120,49,48,44,84,79,80,95,82,73,71,72,84,61,48,120,50,48,10,99,46,69,82,70,58,78,111,116,105,102,105,101,100,61,48,120,52,48,48,48,48,48,48,48,10,99,46,69,82,82,58,65,99,99,101,115,115,77,101,109,111,114,121,61,48,120,52,98,44,65,99,99,101,115,115,79,98,106,101,99,116,61,48,120,53,51,44,65,99,99,101,115,115,83,101,109,97,112,104,111,114,101,61,48,120,55,51,44,65,99,116,105,118,97,116,101,61,48,120,52,50,44,65,100,100,67,108,97,115,115,61,48,120,52,49,44,65,108,108,111,99,77,101,109,111,114,121,61,48,120,53,52,44,65,108,108,111,99,83,101,109,97,112,104,111,114,101,61,48,120,55,50,44,65,108,114,101,97,100,121,68,101,102,105,110,101,100,61,48,120,98,54,44,65,108,114,101,97,100,121,76,111,99,107,101,100,61,48,120,57,99,44,65,114,103,115,61,48,120,49,52,44,65,114,114,97,121,70,117,108,108,61,48,120,50,100,44,66,117,102,102,101,114,79,118,101,114,102,108,111,119,61,48,120,53,99,44,66,117,115,121,61,48,120,56,98,44,67,97,110,99,101,108,108,101,100,61,48,120,51,44,67,97,114,100,82,101,97,100,101,114,85,110,97,118,97,105,108,97,98,108,101,61,48,120,57,102,44,67,97,114,100,82,101,97,100,101,114,85,110,107,110,111,119,110,61,48,120,57,100,44,67,111,109,112,114,101,115,115,105,111,110,61,48,120,97,100,44,67,111,110,110,101,99,116,105,111,110,65,98,111,114,116,101,100,61,48,120,56,99,44,67,111,110,110,101,99,116,105,111,110,82,101,102,117,115,101,100,61,48,120,56,51,44,67,111,110,115,116,114,97,105,110,116,86,105,111,108,97,116,105,111,110,61,48,120,56,56,44,67,111,110,116,105,110,117,101,61,48,120,53,44,67,111,114,101,86,101,114,115,105,111,110,61,48,120,50,54,44,67,114,101,97,116,101,70,105,108,101,61,48,120,55,52,44,67,114,101,97,116,101,79,98,106,101,99,116,61,48,120,54,53,44,67,114,101,97,116,101,82,101,115,111,117,114,99,101,61,48,120,98,50,44,68,97,116,97,83,105,122,101,61,48,120,56,97,44,68,101,97,99,116,105,118,97,116,101,100,61,48,120,57,97,44,68,101,97,100,76,111,99,107,61,48,120,51,101,44,68,101,99,111,109,112,114,101,115,115,105,111,110,61,48,120,97,99,44,68,101,108,101,116,101,70,105,108,101,61,48,120,55,53,44,68,105,114,69,109,112,116,121,61,48,120,56,44,68,105,115,99,111,110,110,101,99,116,101,100,61,48,120,56,54,44,68,111,78,111,116,69,120,112,117,110,103,101,61,48,120,51,48,44,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,55,56,44,68,111,117,98,108,101,73,110,105,116,61,48,120,52,51,44,68,114,97,119,61,48,120,52,56,44,69,78,68,61,48,120,98,101,44,69,109,112,116,121,83,116,114,105,110,103,61,48,120,54,100,44,69,110,100,79,102,70,105,108,101,61,48,120,55,101,44,69,110,116,114,121,77,105,115,115,105,110,103,72,101,97,100,101,114,61,48,120,51,97,44,69,120,97,109,105,110,101,70,97,105,108,101,100,61,48,120,49,57,44,69,120,99,101,112,116,105,111,110,61,48,120,97,51,44,69,120,99,101,112,116,105,111,110,84,104,114,101,115,104,111,108,100,61,48,120,57,44,69,120,99,108,117,115,105,118,101,68,101,110,105,101,100,61,48,120,53,51,44,69,120,101,99,86,105,111,108,97,116,105,111,110,61,48,120,56,102,44,69,120,105,115,116,115,61,48,120,55,97,44,69,120,112,101,99,116,101,100,70,105,108,101,61,48,120,54,102,44,69,120,112,101,99,116,101,100,70,111,108,100,101,114,61,48,120,97,101,44,70,97,105,108,101,100,61,48,120,100,44,70,97,108,115,101,61,48,120,49,44,70,105,101,108,100,78,111,116,83,101,116,61,48,120,52,52,44,70,105,101,108,100,83,101,97,114,99,104,61,48,120,51,50,44,70,105,101,108,100,84,121,112,101,77,105,115,109,97,116,99,104,61,48,120,53,97,44,70,105,108,101,61,48,120,101,44,70,105,108,101,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,49,50,44,70,105,108,101,69,120,105,115,116,115,61,48,120,54,51,44,70,105,108,101,78,111,116,70,111,117,110,100,61,48,120,49,50,44,70,105,108,101,82,101,97,100,70,108,97,103,61,48,120,52,54,44,70,105,108,101,87,114,105,116,101,70,108,97,103,61,48,120,52,55,44,70,105,110,105,115,104,101,100,61,48,120,55,101,44,70,117,110,99,116,105,111,110,61,48,120,98,53,44,71,101,116,70,105,101,108,100,61,48,120,53,54,44,71,101,116,83,117,114,102,97,99,101,73,110,102,111,61,48,120,55,100,44,72,111,115,116,78,111,116,70,111,117,110,100,61,48,120,56,49,44,72,111,115,116,85,110,114,101,97,99,104,97,98,108,101,61,48,120,56,53,44,73,100,101,110,116,105,99,97,108,80,97,116,104,115,61,48,120,55,57,44,73,108,108,101,103,97,108,65,99,116,105,111,110,65,116,116,101,109,112,116,61,48,120,51,57,44,73,108,108,101,103,97,108,65,99,116,105,111,110,73,68,61,48,120,51,55,44,73,108,108,101,103,97,108,65,100,100,114,101,115,115,61,48,120,57,49,44,73,108,108,101,103,97,108,77,101,116,104,111,100,73,68,61,48,120,51,54,44,73,109,109,117,116,97,98,108,101,61,48,120,97,102,44,73,110,85,115,101,61,48,120,99,44,73,110,105,116,61,48,120,50,49,44,73,110,105,116,77,111,100,117,108,101,61,48,120,49,49,44,73,110,112,117,116,79,117,116,112,117,116,61,48,120,57,52,44,73,110,116,101,103,114,105,116,121,86,105,111,108,97,116,105,111,110,61,48,120,56,56,44,73,110,118,97,108,105,100,68,97,116,97,61,48,120,102,44,73,110,118,97,108,105,100,68,105,109,101,110,115,105,111,110,61,48,120,53,57,44,73,110,118,97,108,105,100,72,84,84,80,82,101,115,112,111,110,115,101,61,48,120,97,49,44,73,110,118,97,108,105,100,72,97,110,100,108,101,61,48,120,57,54,44,73,110,118,97,108,105,100,79,98,106,101,99,116,61,48,120,56,101,44,73,110,118,97,108,105,100,80,97,116,104,61,48,120,51,51,44,73,110,118,97,108,105,100,82,101,102,101,114,101,110,99,101,61,48,120,97,50,44,73,110,118,97,108,105,100,83,116,97,116,101,61,48,120,56,48,44,73,110,118,97,108,105,100,85,82,73,61,48,120,56,50,44,73,110,118,97,108,105,100,86,97,108,117,101,61,48,120,57,56,44,76,105,109,105,116,101,100,83,117,99,99,101,115,115,61,48,120,50,44,76,105,115,116,67,104,105,108,100,114,101,110,61,48,120,54,97,44,76,111,97,100,77,111,100,117,108,101,61,48,120,57,53,44,76,111,99,107,61,48,120,49,56,44,76,111,99,107,70,97,105,108,101,100,61,48,120,49,56,44,76,111,99,107,77,117,116,101,120,61,48,120,97,97,44,76,111,99,107,82,101,113,117,105,114,101,100,61,48,120,57,98,44,76,111,99,107,101,100,61,48,120,57,99,44,76,111,111,112,61,48,120,54,50,44,76,111,115,116,67,108,97,115,115,61,48,120,49,97,44,76,111,115,116,79,119,110,101,114,61,48,120,50,102,44,76,111,119,67,97,112,97,99,105,116,121,61,48,120,50,48,44,77,97,114,107,101,100,70,111,114,68,101,108,101,116,105,111,110,61,48,120,51,53,44,77,101,109,111,114,121,61,48,120,49,100,44,77,101,109,111,114,121,67,111,114,114,117,112,116,61,48,120,51,49,44,77,101,109,111,114,121,68,111,101,115,78,111,116,69,120,105,115,116,61,48,120,51,100,44,77,101,109,111,114,121,73,110,102,111,61,48,120,54,54,44,77,105,115,109,97,116,99,104,61,48,120,53,101,44,77,105,115,115,105,110,103,67,108,97,115,115,61,48,120,52,53,44,77,105,115,115,105,110,103,67,108,97,115,115,78,97,109,101,61,48,120,50,97,44,77,105,115,115,105,110,103,80,97,116,104,61,48,120,52,99,44,77,111,100,117,108,101,73,110,105,116,70,97,105,108,101,100,61,48,120,51,99,44,77,111,100,117,108,101,77,105,115,115,105,110,103,73,110,105,116,61,48,120,51,98,44,77,111,100,117,108,101,77,105,115,115,105,110,103,78,97,109,101,61,48,120,52,48,44,77,111,100,117,108,101,79,112,101,110,70,97,105,108,101,100,61,48,120,51,56,44,78,101,101,100,79,119,110,101,114,61,48,120,50,52,44,78,101,101,100,87,105,100,116,104,72,101,105,103,104,116,61,48,120,50,55,44,78,101,103,97,116,105,118,101,67,108,97,115,115,73,68,61,48,120,50,57,44,78,101,103,97,116,105,118,101,83,117,98,67,108,97,115,115,73,68,61,48,120,50,56,44,78,101,116,119,111,114,107,85,110,114,101,97,99,104,97,98,108,101,61,48,120,56,52,44,78,101,119,79,98,106,101,99,116,61,48,120,53,53,44,78,111,65,99,116,105,111,110,61,48,120,49,98,44,78,111,68,97,116,97,61,48,120,49,53,44,78,111,70,105,101,108,100,65,99,99,101,115,115,61,48,120,53,55,44,78,111,77,97,116,99,104,105,110,103,79,98,106,101,99,116,61,48,120,52,97,44,78,111,77,101,100,105,97,73,110,115,101,114,116,101,100,61,48,120,57,101,44,78,111,77,101,109,111,114,121,61,48,120,97,44,78,111,77,101,116,104,111,100,115,61,48,120,52,57,44,78,111,80,101,114,109,105,115,115,105,111,110,61,48,120,50,50,44,78,111,80,111,105,110,116,101,114,61,48,120,98,44,78,111,83,101,97,114,99,104,82,101,115,117,108,116,61,48,120,52,101,44,78,111,83,116,97,116,115,61,48,120,49,102,44,78,111,83,117,112,112,111,114,116,61,48,120,49,99,44,78,111,116,70,111,117,110,100,61,48,120,49,48,44,78,111,116,73,110,105,116,105,97,108,105,115,101,100,61,48,120,54,55,44,78,111,116,76,111,99,107,101,100,61,48,120,52,100,44,78,111,116,80,111,115,115,105,98,108,101,61,48,120,98,51,44,78,111,116,104,105,110,103,68,111,110,101,61,48,120,52,44,78,111,116,105,102,105,101,100,61,48,120,52,48,48,48,48,48,48,48,44,78,117,108,108,65,114,103,115,61,48,120,56,100,44,79,98,106,101,99,116,67,111,114,114,117,112,116,61,48,120,53,48,44,79,98,106,101,99,116,69,120,105,115,116,115,61,48,120,54,101,44,79,98,115,111,108,101,116,101,61,48,120,98,49,44,79,98,116,97,105,110,77,101,116,104,111,100,61,48,120,50,99,44,79,107,97,121,61,48,120,48,44,79,112,101,110,70,105,108,101,61,48,120,55,54,44,79,112,101,110,71,76,61,48,120,97,53,44,79,117,116,79,102,66,111,117,110,100,115,61,48,120,53,102,44,79,117,116,79,102,68,97,116,97,61,48,120,55,101,44,79,117,116,79,102,82,97,110,103,101,61,48,120,50,98,44,79,117,116,79,102,83,112,97,99,101,61,48,120,55,99,44,79,117,116,115,105,100,101,77,97,105,110,84,104,114,101,97,100,61,48,120,97,54,44,79,119,110,101,114,78,101,101,100,115,66,105,116,109,97,112,61,48,120,50,53,44,79,119,110,101,114,80,97,115,115,84,104,114,111,117,103,104,61,48,120,53,49,44,80,101,114,109,105,115,115,105,111,110,68,101,110,105,101,100,61,48,120,50,50,44,80,101,114,109,105,115,115,105,111,110,115,61,48,120,50,50,44,80,114,111,120,121,83,83,76,84,117,110,110,101,108,61,48,120,97,48,44,81,117,101,114,121,61,48,120,50,101,44,82,101,97,100,61,48,120,49,54,44,82,101,97,100,70,105,108,101,84,111,66,117,102,102,101,114,61,48,120,98,48,44,82,101,97,100,79,110,108,121,61,48,120,55,55,44,82,101,97,108,108,111,99,77,101,109,111,114,121,61,48,120,54,49,44,82,101,99,117,114,115,105,111,110,61,48,120,57,48,44,82,101,100,105,109,101,110,115,105,111,110,61,48,120,55,49,44,82,101,102,114,101,115,104,61,48,120,54,57,44,82,101,115,105,122,101,61,48,120,55,48,44,82,101,115,111,108,118,101,80,97,116,104,61,48,120,54,52,44,82,101,115,111,108,118,101,83,121,109,98,111,108,61,48,120,98,52,44,82,101,115,111,117,114,99,101,69,120,105,115,116,115,61,48,120,54,56,44,82,101,116,114,121,61,48,120,55,44,83,97,110,105,116,121,70,97,105,108,117,114,101,61,48,120,55,98,44,83,99,104,101,109,97,86,105,111,108,97,116,105,111,110,61,48,120,56,57,44,83,101,97,114,99,104,61,48,120,49,48,44,83,101,99,117,114,105,116,121,61,48,120,57,55,44,83,101,101,107,61,48,120,54,48,44,83,101,114,118,105,99,101,85,110,97,118,97,105,108,97,98,108,101,61,48,120,57,57,44,83,101,116,70,105,101,108,100,61,48,120,51,52,44,83,101,116,86,97,108,117,101,78,111,116,65,114,114,97,121,61,48,120,98,99,44,83,101,116,86,97,108,117,101,78,111,116,70,117,110,99,116,105,111,110,61,48,120,98,97,44,83,101,116,86,97,108,117,101,78,111,116,76,111,111,107,117,112,61,48,120,98,100,44,83,101,116,86,97,108,117,101,78,111,116,78,117,109,101,114,105,99,61,48,120,98,55,44,83,101,116,86,97,108,117,101,78,111,116,79,98,106,101,99,116,61,48,120,98,57,44,83,101,116,86,97,108,117,101,78,111,116,80,111,105,110,116,101,114,61,48,120,98,98,44,83,101,116,86,97,108,117,101,78,111,116,83,116,114,105,110,103,61,48,120,98,56,44,83,101,116,86,111,108,117,109,101,61,48,120,97,98,44,83,107,105,112,61,48,120,54,44,83,109,97,108,108,77,97,115,107,61,48,120,54,99,44,83,116,97,116,101,109,101,110,116,85,110,115,97,116,105,115,102,105,101,100,61,48,120,52,102,44,83,116,114,105,110,103,70,111,114,109,97,116,61,48,120,55,102,44,83,121,110,116,97,120,61,48,120,55,102,44,83,121,115,116,101,109,67,97,108,108,61,48,120,54,98,44,83,121,115,116,101,109,67,111,114,114,117,112,116,61,48,120,50,51,44,83,121,115,116,101,109,76,111,99,107,101,100,61,48,120,51,102,44,84,97,115,107,83,116,105,108,108,69,120,105,115,116,115,61,48,120,56,55,44,84,101,114,109,105,110,97,116,101,61,48,120,57,44,84,104,114,101,97,100,65,108,114,101,97,100,121,65,99,116,105,118,101,61,48,120,97,52,44,84,104,114,101,97,100,78,111,116,76,111,99,107,101,100,61,48,120,97,57,44,84,105,109,101,79,117,116,61,48,120,49,101,44,84,114,117,101,61,48,120,48,44,85,110,98,97,108,97,110,99,101,100,88,77,76,61,48,120,57,50,44,85,110,100,101,102,105,110,101,100,70,105,101,108,100,61,48,120,52,52,44,85,110,114,101,99,111,103,110,105,115,101,100,70,105,101,108,100,84,121,112,101,61,48,120,53,98,44,85,110,115,117,112,112,111,114,116,101,100,70,105,101,108,100,61,48,120,53,100,44,85,110,115,117,112,112,111,114,116,101,100,79,119,110,101,114,61,48,120,53,50,44,85,115,101,83,117,98,67,108,97,115,115,61,48,120,97,55,44,86,105,114,116,117,97,108,86,111,108,117,109,101,61,48,120,53,56,44,87,111,117,108,100,66,108,111,99,107,61,48,120,57,51,44,87,114,105,116,101,61,48,120,49,55,44,87,114,111,110,103,67,108,97,115,115,61,48,120,56,101,44,87,114,111,110,103,79,98,106,101,99,116,84,121,112,101,61,48,120,56,101,44,87,114,111,110,103,84,121,112,101,61,48,120,97,56,44,87,114,111,110,103,86,101,114,115,105,111,110,61,48,120,49,51,10,99,46,69,86,71,58,65,78,68,82,79,73,68,61,48,120,100,44,65,80,80,61,48,120,99,44,65,85,68,73,79,61,48,120,56,44,67,76,65,83,83,61,48,120,98,44,68,73,83,80,76,65,89,61,48,120,53,44,69,78,68,61,48,120,101,44,70,73,76,69,83,89,83,84,69,77,61,48,120,49,44,71,85,73,61,48,120,52,44,72,65,82,68,87,65,82,69,61,48,120,55,44,73,79,61,48,120,54,44,78,69,84,87,79,82,75,61,48,120,50,44,80,79,87,69,82,61,48,120,97,44,83,89,83,84,69,77,61,48,120,51,44,85,83,69,82,61,48,120,57,10,99,46,70,66,75,58,67,79,80,89,95,70,73,76,69,61,48,120,50,44,68,69,76,69,84,69,95,70,73,76,69,61,48,120,51,44,77,79,86,69,95,70,73,76,69,61,48,120,49,10,99,46,70,68,58,65,76,76,79,67,61,48,120,50,48,44,65,82,82,65,89,61,48,120,49,48,48,48,44,65,82,82,65,89,83,73,90,69,61,48,120,56,48,44,66,85,70,70,69,82,61,48,120,50,48,48,44,66,85,70,83,73,90,69,61,48,120,56,48,44,66,89,84,69,61,48,120,49,48,48,48,48,48,48,44,67,80,80,61,48,120,52,48,48,48,44,67,85,83,84,79,77,61,48,120,56,48,48,48,44,68,79,85,66,76,69,61,48,120,56,48,48,48,48,48,48,48,44,68,79,85,66,76,69,82,69,83,85,76,84,61,48,120,56,48,48,48,48,49,48,48,44,69,82,82,79,82,61,48,120,56,48,48,44,70,76,65,71,83,61,48,120,52,48,44,70,76,79,65,84,61,48,120,49,48,48,48,48,48,48,48,44,70,85,78,67,84,73,79,78,61,48,120,50,48,48,48,48,48,48,44,70,85,78,67,84,73,79,78,80,84,82,61,48,120,97,48,48,48,48,48,48,44,73,61,48,120,52,48,48,44,73,78,73,84,61,48,120,52,48,48,44,76,65,82,71,69,61,48,120,52,48,48,48,48,48,48,44,76,65,82,71,69,82,69,83,85,76,84,61,48,120,52,48,48,48,49,48,48,44,76,79,67,65,76,61,48,120,50,44,76,79,78,71,61,48,120,52,48,48,48,48,48,48,48,44,76,79,78,71,82,69,83,85,76,84,61,48,120,52,48,48,48,48,49,48,48,44,76,79,79,75,85,80,61,48,120,56,48,44,79,66,74,69,67,84,61,48,120,49,44,79,66,74,69,67,84,73,68,61,48,120,52,48,48,48,48,48,48,49,44,79,66,74,69,67,84,80,84,82,61,48,120,56,48,48,48,48,48,49,44,80,79,73,78,84,69,82,61,48,120,56,48,48,48,48,48,48,44,80,82,73,86,65,84,69,61,48,120,49,48,48,48,48,44,80,84,82,61,48,120,56,48,48,48,48,48,48,44,80,84,82,66,85,70,70,69,82,61,48,120,56,48,48,48,50,48,48,44,80,84,82,82,69,83,85,76,84,61,48,120,56,48,48,48,49,48,48,44,80,84,82,83,73,90,69,61,48,120,56,48,44,80,84,82,95,68,79,85,66,76,69,82,69,83,85,76,84,61,48,120,56,56,48,48,48,49,48,48,44,80,84,82,95,76,65,82,71,69,82,69,83,85,76,84,61,48,120,99,48,48,48,49,48,48,44,80,84,82,95,76,79,78,71,82,69,83,85,76,84,61,48,120,52,56,48,48,48,49,48,48,44,82,61,48,120,49,48,48,44,82,69,65,68,61,48,120,49,48,48,44,82,69,83,79,85,82,67,69,61,48,120,50,48,48,48,44,82,69,83,85,76,84,61,48,120,49,48,48,44,82,71,66,61,48,120,56,48,48,48,48,44,82,73,61,48,120,53,48,48,44,82,87,61,48,120,51,48,48,44,83,67,65,76,69,68,61,48,120,50,48,48,48,48,48,44,83,84,82,61,48,120,56,48,48,48,48,48,44,83,84,82,73,78,71,61,48,120,56,48,48,48,48,48,44,83,84,82,82,69,83,85,76,84,61,48,120,56,48,48,49,48,48,44,83,84,82,85,67,84,61,48,120,49,48,44,83,89,78,79,78,89,77,61,48,120,50,48,48,48,48,44,83,89,83,84,69,77,61,48,120,49,48,48,48,48,44,84,65,71,83,61,48,120,52,48,48,44,85,78,73,84,61,48,120,50,48,48,48,48,48,48,48,44,85,78,83,73,71,78,69,68,61,48,120,52,48,48,48,48,44,86,65,82,84,65,71,83,61,48,120,52,48,44,86,73,82,84,85,65,76,61,48,120,56,44,86,79,73,68,61,48,120,48,44,86,79,76,65,84,73,76,69,61,48,120,48,44,87,61,48,120,50,48,48,44,87,79,82,68,61,48,120,52,48,48,48,48,48,44,87,82,73,84,69,61,48,120,50,48,48,10,99,46,70,68,66,58,67,79,77,80,82,69,83,83,95,70,73,76,69,61,48,120,50,44,68,69,67,79,77,80,82,69,83,83,95,70,73,76,69,61,48,120,49,44,68,69,67,79,77,80,82,69,83,83,95,79,66,74,69,67,84,61,48,120,52,44,82,69,77,79,86,69,95,70,73,76,69,61,48,120,51,10,99,46,70,68,76,58,70,69,69,68,66,65,67,75,61,48,120,49,10,99,46,70,68,84,58,65,67,67,69,83,83,69,68,61,48,120,50,44,65,82,67,72,73,86,69,68,61,48,120,51,44,67,82,69,65,84,69,68,61,48,120,49,44,77,79,68,73,70,73,69,68,61,48,120,48,10,99,46,70,70,82,58,65,66,79,82,84,61,48,120,50,44,67,79,78,84,73,78,85,69,61,48,120,48,44,79,75,65,89,61,48,120,48,44,83,75,73,80,61,48,120,49,10,99,46,70,76,58,65,80,80,82,79,88,73,77,65,84,69,61,48,120,49,48,44,66,85,70,70,69,82,61,48,120,52,48,44,68,69,86,73,67,69,61,48,120,52,48,48,44,68,73,82,69,67,84,79,82,89,61,48,120,56,44,69,88,67,76,85,68,69,95,70,73,76,69,83,61,48,120,49,48,48,48,44,69,88,67,76,85,68,69,95,70,79,76,68,69,82,83,61,48,120,50,48,48,48,44,70,73,76,69,61,48,120,49,48,48,44,70,79,76,68,69,82,61,48,120,56,44,76,73,78,75,61,48,120,50,48,44,76,79,79,80,61,48,120,56,48,44,78,69,87,61,48,120,50,44,82,69,65,68,61,48,120,52,44,82,69,83,69,84,95,68,65,84,69,61,48,120,50,48,48,44,83,84,82,69,65,77,61,48,120,56,48,48,44,87,82,73,84,69,61,48,120,49,10,99,46,70,79,70,58,83,77,65,82,84,95,78,65,77,69,83,61,48,120,49,10,99,46,73,68,84,89,80,69,58,70,85,78,67,84,73,79,78,61,48,120,51,44,71,76,79,66,65,76,61,48,120,50,44,77,69,83,83,65,71,69,61,48,120,49,10,99,46,74,69,84,58,65,66,83,95,88,89,61,48,120,101,44,66,85,84,84,79,78,95,49,61,48,120,49,44,66,85,84,84,79,78,95,49,48,61,48,120,97,44,66,85,84,84,79,78,95,50,61,48,120,50,44,66,85,84,84,79,78,95,51,61,48,120,51,44,66,85,84,84,79,78,95,52,61,48,120,52,44,66,85,84,84,79,78,95,53,61,48,120,53,44,66,85,84,84,79,78,95,54,61,48,120,54,44,66,85,84,84,79,78,95,55,61,48,120,55,44,66,85,84,84,79,78,95,56,61,48,120,56,44,66,85,84,84,79,78,95,57,61,48,120,57,44,67,82,79,83,83,69,68,95,73,78,61,48,120,102,44,67,82,79,83,83,69,68,95,79,85,84,61,48,120,49,48,44,68,69,86,73,67,69,95,84,73,76,84,95,88,89,61,48,120,49,50,44,68,69,86,73,67,69,95,84,73,76,84,95,90,61,48,120,49,51,44,68,73,83,80,76,65,89,95,69,68,71,69,61,48,120,49,52,44,69,78,68,61,48,120,49,53,44,76,77,66,61,48,120,49,44,77,77,66,61,48,120,51,44,80,69,78,95,84,73,76,84,95,88,89,61,48,120,100,44,80,82,69,83,83,85,82,69,61,48,120,49,49,44,82,77,66,61,48,120,50,44,87,72,69,69,76,61,48,120,98,44,87,72,69,69,76,95,84,73,76,84,61,48,120,99,10,99,46,74,84,89,80,69,58,65,78,65,76,79,71,61,48,120,50,48,44,65,78,67,72,79,82,69,68,61,48,120,50,44,66,85,84,84,79,78,61,48,120,56,48,44,67,82,79,83,83,73,78,71,61,48,120,56,44,68,66,76,95,67,76,73,67,75,61,48,120,50,48,48,44,68,73,71,73,84,65,76,61,48,120,49,48,44,68,82,65,71,71,69,68,61,48,120,52,44,68,82,65,71,95,73,84,69,77,61,48,120,56,48,48,44,69,88,84,95,77,79,86,69,77,69,78,84,61,48,120,52,48,44,77,79,86,69,77,69,78,84,61,48,120,49,48,48,44,82,69,80,69,65,84,69,68,61,48,120,52,48,48,44,83,69,67,79,78,68,65,82,89,61,48,120,49,10,99,46,75,69,89,58,65,61,48,120,49,44,65,80,79,83,84,82,79,80,72,69,61,48,120,50,98,44,65,84,61,48,120,56,97,44,66,61,48,120,50,44,66,65,67,75,61,48,120,56,54,44,66,65,67,75,83,80,65,67,69,61,48,120,54,57,44,66,65,67,75,95,83,76,65,83,72,61,48,120,50,102,44,66,82,69,65,75,61,48,120,55,98,44,67,61,48,120,51,44,67,65,76,76,61,48,120,56,55,44,67,65,77,69,82,65,61,48,120,56,57,44,67,65,78,67,69,76,61,48,120,55,97,44,67,65,80,83,95,76,79,67,75,61,48,120,52,54,44,67,76,69,65,82,61,48,120,54,101,44,67,79,77,77,65,61,48,120,50,99,44,68,61,48,120,52,44,68,69,76,69,84,69,61,48,120,54,100,44,68,79,84,61,48,120,50,100,44,68,79,87,78,61,48,120,54,49,44,69,61,48,120,53,44,69,73,71,72,84,61,48,120,50,50,44,69,78,68,61,48,120,55,50,44,69,78,68,95,67,65,76,76,61,48,120,56,56,44,69,78,84,69,82,61,48,120,54,98,44,69,81,85,65,76,83,61,48,120,50,55,44,69,83,67,65,80,69,61,48,120,54,99,44,69,88,69,67,85,84,69,61,48,120,55,52,44,70,61,48,120,54,44,70,49,61,48,120,52,99,44,70,49,48,61,48,120,53,53,44,70,49,49,61,48,120,53,54,44,70,49,50,61,48,120,53,55,44,70,49,51,61,48,120,53,56,44,70,49,52,61,48,120,53,57,44,70,49,53,61,48,120,53,97,44,70,49,54,61,48,120,53,98,44,70,49,55,61,48,120,53,99,44,70,49,56,61,48,120,56,48,44,70,49,57,61,48,120,56,49,44,70,50,61,48,120,52,100,44,70,50,48,61,48,120,56,50,44,70,51,61,48,120,52,101,44,70,52,61,48,120,52,102,44,70,53,61,48,120,53,48,44,70,54,61,48,120,53,49,44,70,55,61,48,120,53,50,44,70,56,61,48,120,53,51,44,70,57,61,48,120,53,52,44,70,73,78,68,61,48,120,55,57,44,70,73,86,69,61,48,120,49,102,44,70,79,82,87,65,82,68,61,48,120,57,48,44,70,79,85,82,61,48,120,49,101,44,71,61,48,120,55,44,72,61,48,120,56,44,72,69,76,80,61,48,120,52,51,44,72,79,77,69,61,48,120,54,102,44,73,61,48,120,57,44,73,78,83,69,82,84,61,48,120,55,53,44,74,61,48,120,97,44,75,61,48,120,98,44,76,61,48,120,99,44,76,69,70,84,61,48,120,54,51,44,76,69,78,83,95,70,79,67,85,83,61,48,120,56,99,44,76,69,83,83,95,71,82,69,65,84,69,82,61,48,120,53,102,44,76,73,83,84,95,69,78,68,61,48,120,57,54,44,76,95,65,76,84,61,48,120,52,56,44,76,95,67,79,77,77,65,78,68,61,48,120,52,97,44,76,95,67,79,78,84,82,79,76,61,48,120,52,49,44,76,95,83,72,73,70,84,61,48,120,52,52,44,76,95,83,81,85,65,82,69,61,48,120,50,56,44,77,61,48,120,100,44,77,65,67,82,79,61,48,120,53,100,44,77,69,78,85,61,48,120,55,56,44,77,73,78,85,83,61,48,120,50,54,44,77,85,84,69,61,48,120,57,50,44,78,61,48,120,101,44,78,69,88,84,61,48,120,56,101,44,78,73,78,69,61,48,120,50,51,44,78,80,95,48,61,48,120,51,49,44,78,80,95,49,61,48,120,51,50,44,78,80,95,50,61,48,120,51,51,44,78,80,95,51,61,48,120,51,52,44,78,80,95,52,61,48,120,51,53,44,78,80,95,53,61,48,120,51,54,44,78,80,95,54,61,48,120,51,55,44,78,80,95,55,61,48,120,51,56,44,78,80,95,56,61,48,120,51,57,44,78,80,95,57,61,48,120,51,97,44,78,80,95,66,65,82,61,48,120,51,100,44,78,80,95,68,69,67,73,77,65,76,61,48,120,51,102,44,78,80,95,68,73,86,73,68,69,61,48,120,52,48,44,78,80,95,68,79,84,61,48,120,51,102,44,78,80,95,69,78,84,69,82,61,48,120,55,101,44,78,80,95,77,73,78,85,83,61,48,120,51,101,44,78,80,95,77,85,76,84,73,80,76,89,61,48,120,51,98,44,78,80,95,80,76,85,83,61,48,120,51,99,44,78,80,95,80,76,85,83,95,77,73,78,85,83,61,48,120,53,101,44,78,80,95,83,69,80,65,82,65,84,79,82,61,48,120,51,100,44,78,85,77,95,76,79,67,75,61,48,120,55,99,44,79,61,48,120,102,44,79,78,69,61,48,120,49,98,44,80,61,48,120,49,48,44,80,65,71,69,95,68,79,87,78,61,48,120,55,49,44,80,65,71,69,95,85,80,61,48,120,55,48,44,80,65,85,83,69,61,48,120,54,53,44,80,69,82,73,79,68,61,48,120,50,100,44,80,76,65,89,61,48,120,57,53,44,80,76,85,83,61,48,120,56,98,44,80,79,85,78,68,61,48,120,57,52,44,80,79,87,69,82,61,48,120,54,56,44,80,82,69,86,73,79,85,83,61,48,120,56,102,44,80,82,73,78,84,61,48,120,52,55,44,80,82,84,95,83,67,82,61,48,120,55,100,44,81,61,48,120,49,49,44,82,61,48,120,49,50,44,82,69,68,79,61,48,120,55,55,44,82,69,86,69,82,83,69,95,81,85,79,84,69,61,48,120,50,53,44,82,69,87,73,78,68,61,48,120,57,49,44,82,73,71,72,84,61,48,120,54,50,44,82,95,65,76,84,61,48,120,52,57,44,82,95,67,79,77,77,65,78,68,61,48,120,52,98,44,82,95,67,79,78,84,82,79,76,61,48,120,52,50,44,82,95,83,72,73,70,84,61,48,120,52,53,44,82,95,83,81,85,65,82,69,61,48,120,50,57,44,83,61,48,120,49,51,44,83,67,82,95,76,79,67,75,61,48,120,54,52,44,83,69,76,69,67,84,61,48,120,55,51,44,83,69,77,73,95,67,79,76,79,78,61,48,120,50,97,44,83,69,86,69,78,61,48,120,50,49,44,83,73,88,61,48,120,50,48,44,83,76,65,83,72,61,48,120,50,101,44,83,76,69,69,80,61,48,120,54,55,44,83,80,65,67,69,61,48,120,51,48,44,83,84,65,82,61,48,120,57,51,44,83,84,79,80,61,48,120,56,100,44,83,89,83,82,81,61,48,120,55,102,44,84,61,48,120,49,52,44,84,65,66,61,48,120,54,97,44,84,72,82,69,69,61,48,120,49,100,44,84,87,79,61,48,120,49,99,44,85,61,48,120,49,53,44,85,78,68,79,61,48,120,55,54,44,85,80,61,48,120,54,48,44,86,61,48,120,49,54,44,86,79,76,85,77,69,95,68,79,87,78,61,48,120,56,53,44,86,79,76,85,77,69,95,85,80,61,48,120,56,52,44,87,61,48,120,49,55,44,87,65,75,69,61,48,120,54,54,44,87,73,78,95,67,79,78,84,82,79,76,61,48,120,56,51,44,88,61,48,120,49,56,44,89,61,48,120,49,57,44,90,61,48,120,49,97,44,90,69,82,79,61,48,120,50,52,10,99,46,75,81,58,65,76,84,61,48,120,54,48,44,65,76,84,71,82,61,48,120,52,48,44,67,65,80,83,95,76,79,67,75,61,48,120,52,44,67,79,77,77,65,78,68,61,48,120,49,56,48,44,67,79,78,84,82,79,76,61,48,120,49,56,44,67,84,82,76,61,48,120,49,56,44,68,69,65,68,95,75,69,89,61,48,120,49,48,48,48,48,44,73,78,70,79,61,48,120,51,99,48,52,44,73,78,83,84,82,85,67,84,73,79,78,95,75,69,89,83,61,48,120,55,56,44,76,95,65,76,84,61,48,120,50,48,44,76,95,67,79,77,77,65,78,68,61,48,120,56,48,44,76,95,67,79,78,84,82,79,76,61,48,120,56,44,76,95,67,84,82,76,61,48,120,56,44,76,95,83,72,73,70,84,61,48,120,49,44,78,79,84,95,80,82,73,78,84,65,66,76,69,61,48,120,50,48,48,48,44,78,85,77,95,76,79,67,75,61,48,120,56,48,48,48,44,78,85,77,95,80,65,68,61,48,120,50,48,48,44,80,82,69,83,83,69,68,61,48,120,49,48,48,48,44,81,85,65,76,73,70,73,69,82,83,61,48,120,49,102,98,44,82,69,76,69,65,83,69,68,61,48,120,56,48,48,44,82,69,80,69,65,84,61,48,120,52,48,48,44,82,95,65,76,84,61,48,120,52,48,44,82,95,67,79,77,77,65,78,68,61,48,120,49,48,48,44,82,95,67,79,78,84,82,79,76,61,48,120,49,48,44,82,95,67,84,82,76,61,48,120,49,48,44,82,95,83,72,73,70,84,61,48,120,50,44,83,67,82,95,76,79,67,75,61,48,120,52,48,48,48,44,83,72,73,70,84,61,48,120,51,44,87,73,78,95,67,79,78,84,82,79,76,61,48,120,50,48,48,48,48,10,99,46,76,65,89,79,85,84,58,66,65,67,75,71,82,79,85,78,68,61,48,120,56,44,69,77,66,69,68,68,69,68,61,48,120,50,48,44,70,79,82,69,71,82,79,85,78,68,61,48,120,49,48,44,73,71,78,79,82,69,95,67,85,82,83,79,82,61,48,120,56,48,44,76,69,70,84,61,48,120,50,44,76,79,67,75,61,48,120,52,48,44,82,73,71,72,84,61,48,120,52,44,83,81,85,65,82,69,61,48,120,48,44,84,73,71,72,84,61,48,120,49,44,84,73,76,69,61,48,120,49,48,48,44,87,73,68,69,61,48,120,54,10,99,46,76,68,70,58,67,72,69,67,75,95,69,88,73,83,84,83,61,48,120,49,10,99,46,76,79,67,58,68,73,82,69,67,84,79,82,89,61,48,120,49,44,70,73,76,69,61,48,120,51,44,70,79,76,68,69,82,61,48,120,49,44,86,79,76,85,77,69,61,48,120,50,10,99,46,77,65,88,58,70,73,76,69,78,65,77,69,61,48,120,49,48,48,44,78,65,77,69,95,76,69,78,61,48,120,49,102,10,99,46,77,69,77,58,65,85,68,73,79,61,48,120,56,44,67,65,76,76,69,82,61,48,120,56,48,48,48,48,48,44,67,79,68,69,61,48,120,49,48,44,67,79,76,76,69,67,84,61,48,120,49,48,48,48,44,68,65,84,65,61,48,120,48,44,69,88,67,76,85,83,73,86,69,61,48,120,56,48,48,44,72,73,68,68,69,78,61,48,120,49,48,48,48,48,48,44,77,65,78,65,71,69,68,61,48,120,49,44,78,79,95,66,76,79,67,75,61,48,120,50,48,48,48,44,78,79,95,66,76,79,67,75,73,78,71,61,48,120,50,48,48,48,44,78,79,95,67,76,69,65,82,61,48,120,52,48,48,48,48,44,78,79,95,76,79,67,75,61,48,120,52,48,48,44,78,79,95,80,79,79,76,61,48,120,50,48,44,79,66,74,69,67,84,61,48,120,50,48,48,44,82,69,65,68,61,48,120,49,48,48,48,48,44,82,69,65,68,95,87,82,73,84,69,61,48,120,51,48,48,48,48,44,83,84,82,73,78,71,61,48,120,49,48,48,44,84,69,88,84,85,82,69,61,48,120,52,44,84,77,80,95,76,79,67,75,61,48,120,52,48,44,85,78,84,82,65,67,75,69,68,61,48,120,56,48,44,86,73,68,69,79,61,48,120,50,44,87,82,73,84,69,61,48,120,50,48,48,48,48,10,99,46,77,70,70,58,65,84,84,82,73,66,61,48,120,50,48,44,67,76,79,83,69,68,61,48,120,56,48,44,67,82,69,65,84,69,61,48,120,52,44,68,69,69,80,61,48,120,49,48,48,48,44,68,69,76,69,84,69,61,48,120,56,44,70,73,76,69,61,48,120,52,48,48,44,70,79,76,68,69,82,61,48,120,50,48,48,44,77,79,68,73,70,89,61,48,120,50,44,77,79,86,69,68,61,48,120,49,48,44,79,80,69,78,69,68,61,48,120,52,48,44,82,69,65,68,61,48,120,49,44,82,69,78,65,77,69,61,48,120,49,48,44,83,69,76,70,61,48,120,56,48,48,44,85,78,77,79,85,78,84,61,48,120,49,48,48,44,87,82,73,84,69,61,48,120,50,10,99,46,77,72,70,58,68,69,70,65,85,76,84,61,48,120,50,44,83,84,65,84,73,67,61,48,120,49,44,83,84,82,85,67,84,85,82,69,61,48,120,50,10,99,46,77,79,70,58,76,73,78,75,95,76,73,66,82,65,82,89,61,48,120,49,44,83,84,65,84,73,67,61,48,120,50,44,83,89,83,84,69,77,95,80,82,79,66,69,61,48,120,52,10,99,46,77,79,86,69,58,65,76,76,61,48,120,102,44,68,79,87,78,61,48,120,49,44,76,69,70,84,61,48,120,52,44,82,73,71,72,84,61,48,120,56,44,85,80,61,48,120,50,10,99,46,77,83,70,58,65,68,68,61,48,120,56,44,65,68,68,82,69,83,83,61,48,120,49,48,44,77,69,83,83,65,71,69,95,73,68,61,48,120,50,48,44,78,79,95,68,85,80,76,73,67,65,84,69,61,48,120,52,44,85,80,68,65,84,69,61,48,120,50,44,87,65,73,84,61,48,120,49,10,99,46,77,83,71,73,68,58,65,67,84,73,79,78,61,48,120,54,51,44,66,82,69,65,75,61,48,120,54,52,44,67,79,77,77,65,78,68,61,48,120,54,53,44,67,79,82,69,95,69,78,68,61,48,120,54,52,44,68,69,66,85,71,61,48,120,53,102,44,69,86,69,78,84,61,48,120,53,101,44,70,82,69,69,61,48,120,54,50,44,81,85,73,84,61,48,120,51,101,56,44,84,72,82,69,65,68,95,65,67,84,73,79,78,61,48,120,53,98,44,84,72,82,69,65,68,95,67,65,76,76,66,65,67,75,61,48,120,53,99,44,86,65,76,73,68,65,84,69,95,80,82,79,67,69,83,83,61,48,120,53,100,44,87,65,73,84,95,70,79,82,95,79,66,74,69,67,84,83,61,48,120,53,97,10,99,46,77,84,70,58,65,78,73,77,61,48,120,56,44,82,69,76,65,84,73,86,69,61,48,120,49,48,44,88,61,48,120,49,44,89,61,48,120,50,44,90,61,48,120,52,10,99,46,78,69,84,77,83,71,58,69,78,68,61,48,120,49,44,83,84,65,82,84,61,48,120,48,10,99,46,78,70,58,67,79,76,76,69,67,84,61,48,120,56,48,44,70,82,69,69,61,48,120,49,48,44,70,82,69,69,95,79,78,95,85,78,76,79,67,75,61,48,120,56,44,73,78,73,84,73,65,76,73,83,69,68,61,48,120,50,44,76,79,67,65,76,61,48,120,52,44,77,69,83,83,65,71,69,61,48,120,50,48,48,44,78,65,77,69,61,48,120,56,48,48,48,48,48,48,48,44,80,82,73,86,65,84,69,61,48,120,48,44,82,69,67,76,65,83,83,69,68,61,48,120,49,48,48,44,83,73,71,78,65,76,76,69,68,61,48,120,52,48,48,44,83,85,80,80,82,69,83,83,95,76,79,71,61,48,120,52,48,44,84,73,77,69,82,95,83,85,66,61,48,120,50,48,44,85,78,73,81,85,69,61,48,120,52,48,48,48,48,48,48,48,44,85,78,84,82,65,67,75,69,68,61,48,120,49,10,99,46,79,80,70,58,65,82,71,83,61,48,120,52,48,44,68,69,84,65,73,76,61,48,120,52,44,69,82,82,79,82,61,48,120,56,48,44,77,65,88,95,68,69,80,84,72,61,48,120,50,44,77,79,68,85,76,69,95,80,65,84,72,61,48,120,52,48,48,44,79,80,84,73,79,78,83,61,48,120,49,44,80,82,73,86,73,76,69,71,69,68,61,48,120,49,48,48,44,82,79,79,84,95,80,65,84,72,61,48,120,56,48,48,44,83,67,65,78,95,77,79,68,85,76,69,83,61,48,120,49,48,48,48,44,83,72,79,87,95,69,82,82,79,82,83,61,48,120,50,48,44,83,72,79,87,95,73,79,61,48,120,49,48,44,83,72,79,87,95,77,69,77,79,82,89,61,48,120,56,44,83,89,83,84,69,77,95,80,65,84,72,61,48,120,50,48,48,10,99,46,80,69,82,77,73,84,58,65,76,76,95,68,69,76,69,84,69,61,48,120,56,56,56,44,65,76,76,95,69,88,69,67,61,48,120,52,52,52,44,65,76,76,95,82,69,65,68,61,48,120,49,49,49,44,65,76,76,95,87,82,73,84,69,61,48,120,50,50,50,44,65,82,67,72,73,86,69,61,48,120,50,48,48,48,44,68,69,76,69,84,69,61,48,120,56,44,69,86,69,82,89,79,78,69,95,65,67,67,69,83,83,61,48,120,102,102,102,44,69,86,69,82,89,79,78,69,95,68,69,76,69,84,69,61,48,120,56,56,56,44,69,86,69,82,89,79,78,69,95,69,88,69,67,61,48,120,52,52,52,44,69,86,69,82,89,79,78,69,95,82,69,65,68,61,48,120,49,49,49,44,69,86,69,82,89,79,78,69,95,82,69,65,68,87,82,73,84,69,61,48,120,51,51,51,44,69,86,69,82,89,79,78,69,95,87,82,73,84,69,61,48,120,50,50,50,44,69,88,69,67,61,48,120,52,44,71,82,79,85,80,61,48,120,102,48,44,71,82,79,85,80,73,68,61,48,120,49,48,48,48,48,44,71,82,79,85,80,95,68,69,76,69,84,69,61,48,120,56,48,44,71,82,79,85,80,95,69,88,69,67,61,48,120,52,48,44,71,82,79,85,80,95,82,69,65,68,61,48,120,49,48,44,71,82,79,85,80,95,87,82,73,84,69,61,48,120,50,48,44,72,73,68,68,69,78,61,48,120,49,48,48,48,44,73,78,72,69,82,73,84,61,48,120,50,48,48,48,48,44,78,69,84,87,79,82,75,61,48,120,56,48,48,48,48,44,79,70,70,76,73,78,69,61,48,120,52,48,48,48,48,44,79,84,72,69,82,83,61,48,120,102,48,48,44,79,84,72,69,82,83,95,68,69,76,69,84,69,61,48,120,56,48,48,44,79,84,72,69,82,83,95,69,88,69,67,61,48,120,52,48,48,44,79,84,72,69,82,83,95,82,69,65,68,61,48,120,49,48,48,44,79,84,72,69,82,83,95,87,82,73,84,69,61,48,120,50,48,48,44,80,65,83,83,87,79,82,68,61,48,120,52,48,48,48,44,82,69,65,68,61,48,120,49,44,85,83,69,82,61,48,120,102,44,85,83,69,82,73,68,61,48,120,56,48,48,48,44,85,83,69,82,95,69,88,69,67,61,48,120,52,44,85,83,69,82,95,82,69,65,68,61,48,120,49,44,85,83,69,82,95,87,82,73,84,69,61,48,120,50,44,87,82,73,84,69,61,48,120,50,10,99,46,80,77,70,58,83,89,83,84,69,77,95,78,79,95,66,82,69,65,75,61,48,120,49,10,99,46,80,84,67,58,67,82,79,83,83,72,65,73,82,61,48,120,97,44,67,85,83,84,79,77,61,48,120,49,55,44,68,69,70,65,85,76,84,61,48,120,49,44,68,82,65,71,71,65,66,76,69,61,48,120,49,56,44,69,78,68,61,48,120,49,57,44,72,65,78,68,61,48,120,49,48,44,72,65,78,68,95,76,69,70,84,61,48,120,49,49,44,72,65,78,68,95,82,73,71,72,84,61,48,120,49,50,44,73,78,86,73,83,73,66,76,69,61,48,120,49,54,44,77,65,71,78,73,70,73,69,82,61,48,120,102,44,78,79,95,67,72,65,78,71,69,61,48,120,48,44,80,65,73,78,84,66,82,85,83,72,61,48,120,49,52,44,83,73,90,69,95,66,79,84,84,79,77,61,48,120,57,44,83,73,90,69,95,66,79,84,84,79,77,95,76,69,70,84,61,48,120,50,44,83,73,90,69,95,66,79,84,84,79,77,95,82,73,71,72,84,61,48,120,51,44,83,73,90,69,95,76,69,70,84,61,48,120,54,44,83,73,90,69,95,82,73,71,72,84,61,48,120,55,44,83,73,90,69,95,84,79,80,61,48,120,56,44,83,73,90,69,95,84,79,80,95,76,69,70,84,61,48,120,52,44,83,73,90,69,95,84,79,80,95,82,73,71,72,84,61,48,120,53,44,83,73,90,73,78,71,61,48,120,99,44,83,76,69,69,80,61,48,120,98,44,83,80,76,73,84,95,72,79,82,73,90,79,78,84,65,76,61,48,120,101,44,83,80,76,73,84,95,86,69,82,84,73,67,65,76,61,48,120,100,44,83,84,79,80,61,48,120,49,53,44,84,69,88,84,61,48,120,49,51,10,99,46,82,68,70,58,65,82,67,72,73,86,69,61,48,120,50,48,48,48,44,68,65,84,69,61,48,120,50,44,70,73,76,69,61,48,120,56,44,70,73,76,69,83,61,48,120,56,44,70,79,76,68,69,82,61,48,120,49,48,44,70,79,76,68,69,82,83,61,48,120,49,48,44,72,73,68,68,69,78,61,48,120,49,48,48,44,76,73,78,75,61,48,120,52,48,44,79,80,69,78,68,73,82,61,48,120,52,48,48,48,44,80,69,82,77,73,83,83,73,79,78,83,61,48,120,52,44,81,85,65,76,73,70,73,69,68,61,48,120,50,48,48,44,81,85,65,76,73,70,89,61,48,120,50,48,48,44,82,69,65,68,95,65,76,76,61,48,120,49,102,44,82,69,65,68,95,79,78,76,89,61,48,120,49,48,48,48,44,83,73,90,69,61,48,120,49,44,83,84,82,69,65,77,61,48,120,56,48,48,44,84,65,71,83,61,48,120,56,48,44,84,73,77,69,61,48,120,50,44,86,73,82,84,85,65,76,61,48,120,52,48,48,44,86,79,76,85,77,69,61,48,120,50,48,10,99,46,82,69,83,58,67,79,78,83,79,76,69,95,70,68,61,48,120,50,44,67,79,82,69,95,73,68,76,61,48,120,56,44,67,80,85,95,83,80,69,69,68,61,48,120,49,54,44,68,73,83,80,76,65,89,95,68,82,73,86,69,82,61,48,120,53,44,69,88,67,69,80,84,73,79,78,95,72,65,78,68,76,69,82,61,48,120,49,49,44,70,82,69,69,95,77,69,77,79,82,89,61,48,120,49,55,44,70,82,69,69,95,83,87,65,80,61,48,120,49,44,74,78,73,95,69,78,86,61,48,120,101,44,75,69,89,95,83,84,65,84,69,61,48,120,51,44,76,79,71,95,68,69,80,84,72,61,48,120,100,44,76,79,71,95,76,69,86,69,76,61,48,120,97,44,77,65,88,95,80,82,79,67,69,83,83,69,83,61,48,120,99,44,78,69,84,95,80,82,79,67,69,83,83,73,78,71,61,48,120,49,50,44,79,80,69,78,95,73,78,70,79,61,48,120,49,48,44,80,82,73,86,73,76,69,71,69,68,61,48,120,55,44,80,82,73,86,73,76,69,71,69,68,95,85,83,69,82,61,48,120,54,44,80,82,79,67,69,83,83,95,83,84,65,84,69,61,48,120,49,51,44,83,84,65,84,73,67,95,66,85,73,76,68,61,48,120,57,44,84,72,82,69,65,68,95,73,68,61,48,120,102,44,84,79,84,65,76,95,77,69,77,79,82,89,61,48,120,49,52,44,84,79,84,65,76,95,83,72,65,82,69,68,95,77,69,77,79,82,89,61,48,120,98,44,84,79,84,65,76,95,83,87,65,80,61,48,120,49,53,44,85,83,69,82,95,73,68,61,48,120,52,10,99,46,82,70,68,58,65,76,76,79,87,95,82,69,67,85,82,83,73,79,78,61,48,120,50,48,44,65,76,87,65,89,83,95,67,65,76,76,61,48,120,49,48,48,44,69,88,67,69,80,84,61,48,120,50,44,82,69,65,68,61,48,120,52,44,82,69,67,65,76,76,61,48,120,56,48,44,82,69,77,79,86,69,61,48,120,56,44,83,79,67,75,69,84,61,48,120,52,48,44,83,84,79,80,95,82,69,67,85,82,83,69,61,48,120,49,48,44,87,82,73,84,69,61,48,120,49,10,99,46,82,80,58,77,79,68,85,76,69,95,80,65,84,72,61,48,120,49,44,82,79,79,84,95,80,65,84,72,61,48,120,51,44,83,89,83,84,69,77,95,80,65,84,72,61,48,120,50,10,99,46,82,83,70,58,65,80,80,82,79,88,73,77,65,84,69,61,48,120,52,44,67,65,83,69,95,83,69,78,83,73,84,73,86,69,61,48,120,50,48,44,67,72,69,67,75,95,86,73,82,84,85,65,76,61,48,120,50,44,78,79,95,68,69,69,80,95,83,67,65,78,61,48,120,56,44,78,79,95,70,73,76,69,95,67,72,69,67,75,61,48,120,49,44,80,65,84,72,61,48,120,49,48,10,99,46,83,67,70,58,69,88,73,84,95,79,78,95,69,82,82,79,82,61,48,120,49,44,76,79,71,95,65,76,76,61,48,120,50,10,99,46,83,69,69,75,58,67,85,82,82,69,78,84,61,48,120,49,44,69,78,68,61,48,120,50,44,82,69,76,65,84,73,86,69,61,48,120,51,44,83,84,65,82,84,61,48,120,48,10,99,46,83,84,82,58,67,65,83,69,61,48,120,49,44,77,65,84,67,72,95,67,65,83,69,61,48,120,49,44,77,65,84,67,72,95,76,69,78,61,48,120,50,10,99,46,83,84,84,58,70,76,79,65,84,61,48,120,50,44,72,69,88,61,48,120,51,44,78,85,77,66,69,82,61,48,120,49,44,83,84,82,73,78,71,61,48,120,52,10,99,46,84,72,70,58,65,85,84,79,95,70,82,69,69,61,48,120,49,10,99,46,84,79,73,58,65,78,68,82,79,73,68,95,65,83,83,69,84,77,71,82,61,48,120,52,44,65,78,68,82,79,73,68,95,67,76,65,83,83,61,48,120,51,44,65,78,68,82,79,73,68,95,69,78,86,61,48,120,50,44,76,79,67,65,76,95,67,65,67,72,69,61,48,120,48,44,76,79,67,65,76,95,83,84,79,82,65,71,69,61,48,120,49,10,99,46,84,83,70,58,65,84,84,65,67,72,69,68,61,48,120,49,48,48,44,68,69,84,65,67,72,69,68,61,48,120,56,48,44,70,79,82,69,73,71,78,61,48,120,49,44,76,79,71,95,65,76,76,61,48,120,50,48,44,80,73,80,69,61,48,120,50,48,48,44,80,82,73,86,73,76,69,71,69,68,61,48,120,56,44,81,85,73,69,84,61,48,120,52,48,44,82,69,83,69,84,95,80,65,84,72,61,48,120,52,44,83,72,69,76,76,61,48,120,49,48,44,87,65,73,84,61,48,120,50,10,99,46,84,83,84,65,84,69,58,80,65,85,83,69,68,61,48,120,49,44,82,85,78,78,73,78,71,61,48,120,48,44,83,84,79,80,80,73,78,71,61,48,120,50,44,84,69,82,77,73,78,65,84,69,68,61,48,120,51,10,99,46,86,65,83,58,67,65,83,69,95,83,69,78,83,73,84,73,86,69,61,48,120,102,44,67,76,79,83,69,95,68,73,82,61,48,120,54,44,67,82,69,65,84,69,95,76,73,78,75,61,48,120,49,49,44,68,69,76,69,84,69,61,48,120,51,44,68,69,82,69,71,73,83,84,69,82,61,48,120,49,44,68,82,73,86,69,82,95,83,73,90,69,61,48,120,49,50,44,71,69,84,95,68,69,86,73,67,69,95,73,78,70,79,61,48,120,98,44,71,69,84,95,73,78,70,79,61,48,120,97,44,73,68,69,78,84,73,70,89,95,70,73,76,69,61,48,120,99,44,73,71,78,79,82,69,95,70,73,76,69,61,48,120,57,44,77,65,75,69,95,68,73,82,61,48,120,100,44,79,80,69,78,95,68,73,82,61,48,120,53,44,82,69,65,68,95,76,73,78,75,61,48,120,49,48,44,82,69,78,65,77,69,61,48,120,52,44,83,65,77,69,95,70,73,76,69,61,48,120,101,44,83,67,65,78,95,68,73,82,61,48,120,50,44,84,69,83,84,95,80,65,84,72,61,48,120,55,44,87,65,84,67,72,95,80,65,84,72,61,48,120,56,10,99,46,86,76,70,58,65,80,73,61,48,120,50,48,44,66,82,65,78,67,72,61,48,120,49,44,67,82,73,84,73,67,65,76,61,48,120,56,44,68,69,84,65,73,76,61,48,120,52,48,44,69,82,82,79,82,61,48,120,50,44,70,85,78,67,84,73,79,78,61,48,120,49,48,48,44,73,78,70,79,61,48,120,49,48,44,84,82,65,67,69,61,48,120,56,48,44,87,65,82,78,73,78,71,61,48,120,52,10,99,46,86,79,76,85,77,69,58,72,73,68,68,69,78,61,48,120,52,44,80,82,73,79,82,73,84,89,61,48,120,50,44,82,69,80,76,65,67,69,61,48,120,49,44,83,89,83,84,69,77,61,48,120,56,10,0 }; diff --git a/src/core/lib_fields_read.cpp b/src/core/lib_fields_read.cpp index cc3136d7d..30cd752a7 100644 --- a/src/core/lib_fields_read.cpp +++ b/src/core/lib_fields_read.cpp @@ -520,14 +520,12 @@ ERR GetFieldVariable(OBJECTPTR Object, CSTRING FieldName, STRING Buffer, LONG Bu ERR copy_field_to_buffer(OBJECTPTR Object, Field *Field, LONG DestFlags, APTR Result, CSTRING Option, LONG *TotalElements) { - pf::Log log("GetField"); - //log.msg("[%s:%d] Name: %s, Flags: $%x", ((extMetaClass *)Object->Class)->Name, Object->UID, Field->Name, DestFlags); BYTE value[16]; // 128 bits of space APTR data; LONG array_size = -1; - LONG srcflags = Field->Flags; + auto srcflags = Field->Flags; if (!(DestFlags & (FD_UNIT|FD_LARGE|FD_LONG|FD_DOUBLE|FD_POINTER|FD_STRING|FD_ARRAY))) goto mismatch; @@ -622,6 +620,7 @@ ERR copy_field_to_buffer(OBJECTPTR Object, Field *Field, LONG DestFlags, APTR Re } else { if (array_size IS -1) { + pf::Log log("GetField"); log.warning("Array sizing not supported for field %s", Field->Name); return ERR::Failed; } @@ -732,13 +731,14 @@ ERR copy_field_to_buffer(OBJECTPTR Object, Field *Field, LONG DestFlags, APTR Re else goto mismatch; } else { - log.warning("I dont recognise field flags of $%.8x.", srcflags); - return ERR::UnrecognisedFieldType; + pf::Log log("GetField"); + return log.warning(ERR::UnrecognisedFieldType); } return ERR::Okay; mismatch: + pf::Log log("GetField"); log.warning("Mismatch while reading %s.%s (field $%.8x, requested $%.8x).", Object->className(), Field->Name, Field->Flags, DestFlags); return ERR::FieldTypeMismatch; } diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index 3a95220c5..1e5692e8a 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -14,12 +14,14 @@ set (CLASSES "${CMAKE_CURRENT_SOURCE_DIR}/class_bitmap.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/class_display.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/class_clipboard.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/class_controller.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/class_pointer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/class_surface/class_surface.cpp") set (DISPLAY_DEFS # Full paths are required for add_custom_command() dependencies to work correctly "${CMAKE_CURRENT_SOURCE_DIR}/class_bitmap_def.c" "${CMAKE_CURRENT_SOURCE_DIR}/class_clipboard_def.c" + "${CMAKE_CURRENT_SOURCE_DIR}/class_controller_def.c" "${CMAKE_CURRENT_SOURCE_DIR}/class_display_def.c" "${CMAKE_CURRENT_SOURCE_DIR}/class_pointer_def.c" "${CMAKE_CURRENT_SOURCE_DIR}/class_surface/surface_def.c") @@ -29,6 +31,7 @@ if (BUILD_DEFS) # Customised idl_c() equivalent, this is for defining the output ${DISPLAY_DEFS} "${DOCS}/modules/classes/bitmap.xml" "${DOCS}/modules/classes/clipboard.xml" + "${DOCS}/modules/classes/controller.xml" "${DOCS}/modules/classes/display.xml" "${DOCS}/modules/classes/pointer.xml" "${DOCS}/modules/classes/surface.xml" @@ -77,7 +80,6 @@ if (XDGA_INSTALLED) add_definitions ("-DXDGA_ENABLED") endif () - add_library (${MOD}) set_module_defaults (${MOD}) @@ -89,7 +91,7 @@ target_link_libraries (${MOD} PUBLIC unicode) target_link_libraries (${MOD} PUBLIC linear_rgb) if (WIN32) - target_link_libraries (${MOD} PRIVATE ole32 gdi32 uuid ${MATH_LINK}) + target_link_libraries (${MOD} PRIVATE ole32 gdi32 uuid xinput ${MATH_LINK}) target_sources (${MOD} PRIVATE ${FUNCTIONS} "win32/windows.cpp" "win32/clipboard.c" ${CLASSES}) add_compile_definitions ("WIN_DRAGDROP") elseif (ANDROID) diff --git a/src/display/class_controller.cpp b/src/display/class_controller.cpp new file mode 100644 index 000000000..6bce08b15 --- /dev/null +++ b/src/display/class_controller.cpp @@ -0,0 +1,124 @@ +/********************************************************************************************************************* + +-CLASS- +Controller: Provides support for reading state-based game controllers. + +Use the Controller class to read the state of game controllers that are recognised by the operating system. + +Unlike analog devices that stream input commands (e.g. mice), gamepad controllers maintain a state that can be read +at any time. The controller state is normally read at least once per frame, which can be achieved in the main +inner loop, or in a separate timer. + +Controller input management is governed by the @Display class. The `GRAB_CONTROLLERS` flag must be defined in the +active Display's Flags field in order to ensure that controller input can be received. Failure to do so may mean +that the Controller object appears to work but does not receive input. + +-END- + +*********************************************************************************************************************/ + +#include "defs.h" + +#ifdef _WIN32 +using namespace display; +#endif + +/********************************************************************************************************************* +-ACTION- +Query: Get the current controller state. +-END- +*********************************************************************************************************************/ + +static ERR CONTROLLER_Query(objController *Self) +{ +#ifdef _WIN32 + if (auto error = winReadController(Self->Port, (DOUBLE *)&Self->LeftTrigger, Self->Buttons); error IS ERR::Okay) { + return ERR::Okay; + } + else return error; +#else + return ERR::NoSupport; +#endif +} + +/********************************************************************************************************************* + +-FIELD- +LeftTrigger: Left trigger value between 0.0 and 1.0. + +-FIELD- +RightTrigger: Right trigger value between 0.0 and 1.0. + +-FIELD- +LeftStickX: Left analog stick value for X axis, between -1.0 and 1.0. + +-FIELD- +LeftStickY: Left analog stick value for Y axis, between -1.0 and 1.0. + +-FIELD- +RightStickX: Right analog stick value for X axis, between -1.0 and 1.0. + +-FIELD- +RightStickY: Right analog stick value for Y axis, between -1.0 and 1.0. + +-FIELD- +Buttons: JET button values expressed as bit-fields. + +-FIELD- +Port: The port number assigned to the controller. + +Set the port number to choose the controller that will be queried for state changes. The default of zero is assigned +to the primary controller. + +The port number can be changed at any time, so multiple controllers can be queried through one interface at the cost +of overwriting the previous state. Check #TotalPorts if your program supports more than one controller. + +-FIELD- +TotalPorts: Reports the total number of controllers connected to the system. + +*********************************************************************************************************************/ + +static ERR CONTROLLER_GET_TotalPorts(extSurface *Self, LONG &Value) +{ +#ifdef _WIN32 + if (glLastPort >= 0) Value = glLastPort; + else Value = 0; + return ERR::Okay; +#endif + + return ERR::NoSupport; +} + +//******************************************************************************************************************** + +#include "class_controller_def.c" + +static const FieldArray clFields[] = { + { "LeftTrigger", FDF_DOUBLE|FDF_R }, + { "RightTrigger", FDF_DOUBLE|FDF_R }, + { "LeftStickX", FDF_DOUBLE|FDF_R }, + { "LeftStickY", FDF_DOUBLE|FDF_R }, + { "RightStickX", FDF_DOUBLE|FDF_R }, + { "RightStickY", FDF_DOUBLE|FDF_R }, + { "Buttons", FDF_LONG|FDF_R }, + { "Port", FDF_LONG|FDF_RI }, + { "TotalPorts", FDF_VIRTUAL|FDF_LONG|FDF_R, CONTROLLER_GET_TotalPorts }, + END_FIELD +}; + +//******************************************************************************************************************** + +ERR create_controller_class(void) +{ + clController = objMetaClass::create::global( + fl::BaseClassID(CLASSID::CONTROLLER), + fl::ClassVersion(VER_CONTROLLER), + fl::Name("Controller"), + fl::Category(CCF::IO), + fl::Actions(clControllerActions), + fl::Fields(clFields), + fl::Size(sizeof(objController)), + fl::Path(MOD_PATH)); + + return clController ? ERR::Okay : ERR::AddClass; +} diff --git a/src/display/class_controller_def.c b/src/display/class_controller_def.c new file mode 100644 index 000000000..06e821161 --- /dev/null +++ b/src/display/class_controller_def.c @@ -0,0 +1,27 @@ +// Auto-generated by idl-c.fluid + +static const struct FieldDef clControllerButtons[] = { + { "GamepadS", 0x00000001 }, + { "GamepadE", 0x00000002 }, + { "GamepadW", 0x00000004 }, + { "GamepadN", 0x00000008 }, + { "DpadUp", 0x00000010 }, + { "DpadDown", 0x00000020 }, + { "DpadLeft", 0x00000040 }, + { "DpadRight", 0x00000080 }, + { "Start", 0x00000100 }, + { "Select", 0x00000200 }, + { "LeftBumper1", 0x00000400 }, + { "LeftBumper2", 0x00000800 }, + { "RightBumper1", 0x00001000 }, + { "RightBumper2", 0x00002000 }, + { "LeftThumb", 0x00004000 }, + { "RightThumb", 0x00008000 }, + { NULL, 0 } +}; + +static const struct ActionArray clControllerActions[] = { + { AC::Query, CONTROLLER_Query }, + { AC::NIL, NULL } +}; + diff --git a/src/display/class_display.cpp b/src/display/class_display.cpp index 4dd31494a..7bc4c86fa 100644 --- a/src/display/class_display.cpp +++ b/src/display/class_display.cpp @@ -1954,26 +1954,10 @@ BottomMargin: In hosted mode, indicates the bottom margin of the client window. If the display is hosted in a client window, the BottomMargin indicates the number of pixels between the client area and the bottom window edge. --FIELD- -CertificationDate: String describing the date of the graphics driver's certification. - -The string in this field describes the date on which the graphics card driver was certified. If this information is -not available from the driver, a `NULL` pointer is returned. - -*********************************************************************************************************************/ - -static ERR GET_CertificationDate(extDisplay *Self, STRING *Value) -{ - *Value = Self->CertificationDate; - return ERR::Okay; -} - -/********************************************************************************************************************* -FIELD- Chipset: String describing the graphics chipset. -The string in this field describes the graphic card's chipset. If this information is not retrievable, a `NULL` -pointer is returned. +This string describes the graphic card's chipset, if known. *********************************************************************************************************************/ @@ -2127,8 +2111,7 @@ static ERR SET_VDensity(extDisplay *Self, LONG Value) -FIELD- Display: String describing the display (e.g. model name of the monitor). -The string in this field describes the display device that is connected to the user's graphics card. If this -information is not detectable, a `NULL` pointer is returned. +This string describes the display device that is connected to the user's graphics card. *********************************************************************************************************************/ @@ -2144,8 +2127,7 @@ static ERR GET_Display(extDisplay *Self, CSTRING *Value) -FIELD- DisplayManufacturer: String describing the display manufacturer. -The string in this field returns the name of the manufacturer that created the user's display device. If this -information is not detectable, a `NULL` pointer is returned. +This string names the manufacturer of the user's display device. *********************************************************************************************************************/ @@ -2164,56 +2146,6 @@ DisplayType: In hosted mode, indicates the bottom margin of the client window. If the display is hosted in a client window, the #BottomMargin indicates the number of pixels between the client area and the bottom window edge. --FIELD- -DriverCopyright: String containing copyright information on the graphics driver software. - -The string in this field returns copyright information related to the graphics driver. If this information is not -available, a `NULL` pointer is returned. - -*********************************************************************************************************************/ - -static ERR GET_DriverCopyright(extDisplay *Self, CSTRING *Value) -{ - if (Self->DriverCopyright[0]) *Value = Self->DriverCopyright; - else *Value = NULL; - return ERR::Okay; -} - -/********************************************************************************************************************* - --FIELD- -DriverVersion: String describing the version of the graphics hardware driver. - -The string in this field describes the graphic driver's version number. If this information is not detectable, a `NULL` -pointer is returned. - -*********************************************************************************************************************/ - -static ERR GET_DriverVersion(extDisplay *Self, CSTRING *Value) -{ - if (Self->DriverVersion[0]) *Value = Self->DriverVersion; - else *Value = NULL; - return ERR::Okay; -} - -/********************************************************************************************************************* - --FIELD- -DriverVendor: String describing the vendor of the graphics driver. - -The string in this field returns the name of the vendor that supplied the graphics card driver. If this information is -not available, a `NULL` pointer is returned. - -*********************************************************************************************************************/ - -static ERR GET_DriverVendor(extDisplay *Self, CSTRING *Value) -{ - *Value = Self->DriverVendor; - return ERR::Okay; -} - -/********************************************************************************************************************* - -FIELD- Flags: Optional flag settings. @@ -2229,7 +2161,7 @@ static ERR SET_Flags(extDisplay *Self, SCR Value) if (Self->initialised()) { // Only flags that are explicitly supported here may be set post-initialisation. - #define ACCEPT_FLAGS (SCR::AUTO_SAVE) + static const SCR ACCEPT_FLAGS = SCR::AUTO_SAVE|SCR::GRAB_CONTROLLERS; auto accept = Value & ACCEPT_FLAGS; Self->Flags = (Self->Flags & (~ACCEPT_FLAGS)) | accept; @@ -2864,6 +2796,7 @@ void alloc_display_buffer(extDisplay *Self) #include "class_display_def.c" static const FieldArray DisplayFields[] = { + // Re-compile the FDL if making changes { "RefreshRate", FDF_DOUBLE|FDF_RW, NULL, SET_RefreshRate }, { "Bitmap", FDF_LOCAL|FDF_R, NULL, NULL, CLASSID::BITMAP }, { "Flags", FDF_LONGFLAGS|FDF_RW, NULL, SET_Flags, &clDisplayFlags }, @@ -2887,16 +2820,12 @@ static const FieldArray DisplayFields[] = { { "TopMargin", FDF_LONG|FDF_R }, { "BottomMargin", FDF_LONG|FDF_R }, // Virtual fields - { "CertificationDate", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_CertificationDate }, { "Chipset", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_Chipset }, { "Gamma", FDF_VIRTUAL|FDF_DOUBLE|FDF_ARRAY|FDF_RI, GET_Gamma, SET_Gamma }, { "HDensity", FDF_VIRTUAL|FDF_LONG|FDF_RW, GET_HDensity, SET_HDensity }, { "VDensity", FDF_VIRTUAL|FDF_LONG|FDF_RW, GET_VDensity, SET_VDensity }, { "Display", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_Display }, { "DisplayManufacturer", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_DisplayManufacturer }, - { "DriverCopyright", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_DriverCopyright }, - { "DriverVendor", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_DriverVendor }, - { "DriverVersion", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_DriverVersion }, { "InsideWidth", FDF_VIRTUAL|FDF_LONG|FDF_R, GET_InsideWidth }, { "InsideHeight", FDF_VIRTUAL|FDF_LONG|FDF_R, GET_InsideHeight }, { "Manufacturer", FDF_VIRTUAL|FDF_STRING|FDF_R, GET_Manufacturer }, diff --git a/src/display/class_display_def.c b/src/display/class_display_def.c index bad96b452..25445f9c9 100644 --- a/src/display/class_display_def.c +++ b/src/display/class_display_def.c @@ -10,6 +10,7 @@ static const struct FieldDef clDisplayFlags[] = { { "Borderless", 0x00000020 }, { "AlphaBlend", 0x00000040 }, { "Composite", 0x00000040 }, + { "GrabControllers", 0x00000080 }, { "Maxsize", 0x00100000 }, { "Refresh", 0x00200000 }, { "Hosted", 0x02000000 }, diff --git a/src/display/class_pointer.cpp b/src/display/class_pointer.cpp index bb7ce7e46..e32c3bfeb 100644 --- a/src/display/class_pointer.cpp +++ b/src/display/class_pointer.cpp @@ -351,14 +351,6 @@ static void process_ptr_movement(extPointer *Self, struct dcDeviceInput *Input) if (!userinput.Timestamp) userinput.Timestamp = PreciseTime(); - // All X/Y movement passed through the pointer object must be expressed in absolute coordinates. - - if ((userinput.Type IS JET::DIGITAL_XY) or (userinput.Type IS JET::ANALOG_XY)) { - userinput.Type = JET::ABS_XY; - userinput.X += Self->X; - userinput.Y += Self->Y; - } - bool moved = false, underlying_change = false; DOUBLE current_x = Self->X; DOUBLE current_y = Self->Y; diff --git a/src/display/class_surface/surface_def.c b/src/display/class_surface/surface_def.c index fb919e53c..a826a9389 100644 --- a/src/display/class_surface/surface_def.c +++ b/src/display/class_surface/surface_def.c @@ -178,42 +178,29 @@ static const struct FieldDef clSurfaceJTYPE[] = { }; static const struct FieldDef clSurfaceJET[] = { - { "DigitalXY", 0x00000001 }, - { "Button1", 0x00000002 }, - { "Lmb", 0x00000002 }, - { "Button2", 0x00000003 }, - { "Rmb", 0x00000003 }, - { "Button3", 0x00000004 }, - { "Mmb", 0x00000004 }, - { "Button4", 0x00000005 }, - { "Button5", 0x00000006 }, - { "Button6", 0x00000007 }, - { "Button7", 0x00000008 }, - { "Button8", 0x00000009 }, - { "Button9", 0x0000000a }, - { "Button10", 0x0000000b }, - { "TriggerLeft", 0x0000000c }, - { "TriggerRight", 0x0000000d }, - { "ButtonStart", 0x0000000e }, - { "ButtonSelect", 0x0000000f }, - { "LeftBumper1", 0x00000010 }, - { "LeftBumper2", 0x00000011 }, - { "RightBumper1", 0x00000012 }, - { "RightBumper2", 0x00000013 }, - { "AnalogXY", 0x00000014 }, - { "AnalogZ", 0x00000015 }, - { "Analog2XY", 0x00000016 }, - { "Analog2Z", 0x00000017 }, - { "Wheel", 0x00000018 }, - { "WheelTilt", 0x00000019 }, - { "PenTiltXY", 0x0000001a }, - { "AbsXY", 0x0000001b }, - { "CrossedIn", 0x0000001c }, - { "CrossedOut", 0x0000001d }, - { "Pressure", 0x0000001e }, - { "DeviceTiltXY", 0x0000001f }, - { "DeviceTiltZ", 0x00000020 }, - { "DisplayEdge", 0x00000021 }, + { "Button1", 0x00000001 }, + { "Lmb", 0x00000001 }, + { "Button2", 0x00000002 }, + { "Rmb", 0x00000002 }, + { "Button3", 0x00000003 }, + { "Mmb", 0x00000003 }, + { "Button4", 0x00000004 }, + { "Button5", 0x00000005 }, + { "Button6", 0x00000006 }, + { "Button7", 0x00000007 }, + { "Button8", 0x00000008 }, + { "Button9", 0x00000009 }, + { "Button10", 0x0000000a }, + { "Wheel", 0x0000000b }, + { "WheelTilt", 0x0000000c }, + { "PenTiltXY", 0x0000000d }, + { "AbsXY", 0x0000000e }, + { "CrossedIn", 0x0000000f }, + { "CrossedOut", 0x00000010 }, + { "Pressure", 0x00000011 }, + { "DeviceTiltXY", 0x00000012 }, + { "DeviceTiltZ", 0x00000013 }, + { "DisplayEdge", 0x00000014 }, { NULL, 0 } }; diff --git a/src/display/defs.h b/src/display/defs.h index 6a4d59194..79002afad 100644 --- a/src/display/defs.h +++ b/src/display/defs.h @@ -9,6 +9,7 @@ #define PRV_POINTER #define PRV_CLIPBOARD #define PRV_SURFACE +#define PRV_CONTROLLER //#define DBG_DRAW_ROUTINES // Use this if you want to debug any external code that is subscribed to surface drawing routines //#define FASTACCESS //#define DBG_LAYERS @@ -385,8 +386,9 @@ class extDisplay : public objDisplay { DOUBLE Gamma[3]; // Red, green, blue gamma radioactivity indicator std::vector Resolutions; FUNCTION ResizeFeedback; - LONG BmpXOffset; // X offset for scrolling - LONG BmpYOffset; // Y offset for scrolling + LONG ControllerPorts; + LONG VDensity; // Cached DPI value, if calculable. + LONG HDensity; #ifdef __xwindows__ union { APTR WindowHandle; @@ -399,26 +401,16 @@ class extDisplay : public objDisplay { APTR WindowHandle; #endif WORD Opacity; - LONG VDensity; // Cached DPI value, if calculable. - LONG HDensity; - char DriverVendor[60]; - char DriverCopyright[80]; char Manufacturer[60]; char Chipset[40]; - char DAC[32]; - char Clock[32]; - char DriverVersion[16]; - char CertificationDate[20]; char Display[32]; char DisplayManufacturer[60]; - #ifdef _WIN32 - APTR OldProcedure; - #endif }; extern void clean_clipboard(void); extern ERR create_bitmap_class(void); extern ERR create_clipboard_class(void); +extern ERR create_controller_class(void); extern ERR create_display_class(void); extern ERR create_pointer_class(void); extern ERR create_surface_class(void); @@ -462,7 +454,7 @@ extern void print_layer_list(STRING Function, SurfaceControl *Ctl, LONG POI) extern bool glSixBitDisplay; extern OBJECTPTR glModule; -extern OBJECTPTR clDisplay, clPointer, clBitmap, clClipboard, clSurface; +extern OBJECTPTR clDisplay, clPointer, clBitmap, clClipboard, clSurface, clController; extern OBJECTID glPointerID; extern DISPLAYINFO glDisplayInfo; extern APTR glDither; @@ -482,6 +474,7 @@ extern char glpDPMS[20]; extern UBYTE *glDemultiply; extern std::array glAlphaLookup; extern std::list glClips; +extern int glLastPort; extern std::unordered_map glWindowHooks; extern std::vector glFocusList; diff --git a/src/display/display-driver.cpp b/src/display/display-driver.cpp index 1c1e35668..2fb842eb5 100644 --- a/src/display/display-driver.cpp +++ b/src/display/display-driver.cpp @@ -105,7 +105,6 @@ static void android_term_window(LONG); const InputType glInputType[LONG(JET::END)] = { { JTYPE::NIL, JTYPE::NIL }, // UNUSED - { JTYPE::DIGITAL|JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::DIGITAL_XY { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_1 { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_2 { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_3 @@ -116,33 +115,20 @@ const InputType glInputType[LONG(JET::END)] = { { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_8 { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_9 { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_10 - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::TRIGGER_LEFT - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::TRIGGER_RIGHT - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_START - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::BUTTON_SELECT - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::LEFT_BUMPER_1 - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::LEFT_BUMPER_2 - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::RIGHT_BUMPER_1 - { JTYPE::BUTTON, JTYPE::BUTTON }, // JET::RIGHT_BUMPER_2 - { JTYPE::ANALOG|JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ANALOG_XY - { JTYPE::ANALOG|JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ANALOG_Z - { JTYPE::ANALOG|JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ANALOG2_XY - { JTYPE::ANALOG|JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ANALOG2_Z { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::WHEEL { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::WHEEL_TILT { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::PEN_TILT_XY - { JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ABS_XY - { JTYPE::CROSSING, JTYPE::CROSSING }, // JET::CROSSING_IN - { JTYPE::CROSSING, JTYPE::CROSSING }, // JET::CROSSING_OUT + { JTYPE::MOVEMENT, JTYPE::MOVEMENT }, // JET::ABS_XY + { JTYPE::CROSSING, JTYPE::CROSSING }, // JET::CROSSING_IN + { JTYPE::CROSSING, JTYPE::CROSSING }, // JET::CROSSING_OUT { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::PRESSURE { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::DEVICE_TILT_XY { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT }, // JET::DEVICE_TILT_Z - { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT } // JET::DISPLAY_EDGE + { JTYPE::EXT_MOVEMENT, JTYPE::EXT_MOVEMENT } // JET::DISPLAY_EDGE }; const CSTRING glInputNames[LONG(JET::END)] = { "", - "DIGITAL_XY", "BUTTON_1", "BUTTON_2", "BUTTON_3", @@ -153,18 +139,6 @@ const CSTRING glInputNames[LONG(JET::END)] = { "BUTTON_8", "BUTTON_9", "BUTTON_10", - "TRIGGER_LEFT", - "TRIGGER_RIGHT", - "BUTTON_START", - "BUTTON_SELECT", - "LEFT_BUMPER_1", - "LEFT_BUMPER_2", - "RIGHT_BUMPER_1", - "RIGHT_BUMPER_2", - "ANALOG_XY", - "ANALOG_Z", - "ANALOG2_XY", - "ANALOG2_Z", "WHEEL", "WHEEL_TILT", "PEN_TILT_XY", @@ -207,7 +181,7 @@ struct CoreBase *CoreBase; ColourFormat glColourFormat; bool glHeadless = false; OBJECTPTR glModule = NULL; -OBJECTPTR clDisplay = NULL, clPointer = NULL, clBitmap = NULL, clClipboard = NULL, clSurface = NULL; +OBJECTPTR clDisplay = NULL, clPointer = NULL, clBitmap = NULL, clClipboard = NULL, clSurface = NULL, clController = NULL; OBJECTID glPointerID = 0; DISPLAYINFO glDisplayInfo; APTR glDither = NULL; @@ -222,6 +196,7 @@ LONG glpMaximise = FALSE, glpFullScreen = FALSE; SWIN glpWindowType = SWIN::HOST; char glpDPMS[20] = "Standby"; UBYTE *glDemultiply = NULL; +int glLastPort = -1; std::vector glFocusList; std::recursive_mutex glFocusLock; @@ -847,6 +822,7 @@ static ERR MODInit(OBJECTPTR argModule, struct CoreBase *argCoreBase) create_bitmap_class(); create_clipboard_class(); create_surface_class(); + create_controller_class(); return ERR::Okay; } #endif @@ -1085,6 +1061,7 @@ static ERR MODInit(OBJECTPTR argModule, struct CoreBase *argCoreBase) if (create_bitmap_class() != ERR::Okay) return log.warning(ERR::AddClass); if (create_clipboard_class() != ERR::Okay) return log.warning(ERR::AddClass); if (create_surface_class() != ERR::Okay) return log.warning(ERR::AddClass); + if (create_controller_class() != ERR::Okay) return log.warning(ERR::AddClass); // Initialise 64K alpha blending table, for cutting down on multiplications. @@ -1256,6 +1233,7 @@ static ERR MODExpunge(void) if (clBitmap) { FreeResource(clBitmap); clBitmap = NULL; } if (clClipboard) { FreeResource(clClipboard); clClipboard = NULL; } if (clSurface) { FreeResource(clSurface); clSurface = NULL; } + if (clController) { FreeResource(clController); clController = NULL; } #ifdef _GLES_ free_egl(); diff --git a/src/display/display.fdl b/src/display/display.fdl index cdb598b98..3862a47b7 100644 --- a/src/display/display.fdl +++ b/src/display/display.fdl @@ -168,6 +168,7 @@ module({ name="Display", copyright="Paul Manias 2003-2024", version=1.0, status= "BIT_6: Display is limited to 6-bit output per colour gun.", "BORDERLESS: If display is hosted, create it as a popup / borderless window.", "ALPHA_BLEND|COMPOSITE: Enables alpha channel blending (if display is hosted and 32-bit).", + "GRAB_CONTROLLERS: Grab controllers for receiving input when the display has the focus.", { MAXIMISE = "0x80000000: Special win32 flag." }, { CUSTOM_WINDOW = "0x40000000: The display has been created with a custom window reference." }, { FLIPPABLE = "0x20000000: If `SCR::BUFFER` is used, this flag may be set by the display manager if it is possible to flip the buffer." }, @@ -488,6 +489,17 @@ module({ name="Display", copyright="Paul Manias 2003-2024", version=1.0, status= FUNCTION RequestHandler; ]]) + class('Controller', { src='class_controller.cpp', output='class_controller_def.c' }, [[ + double LeftTrigger # Left trigger value between 0.0 and 1.0 + double RightTrigger # Right trigger value between 0.0 and 1.0 + double LeftStickX # Left analog stick value for X axis, between -1.0 and 1.0 + double LeftStickY # Left analog stick value for Y axis, between -1.0 and 1.0 + double RightStickX # Right analog stick value for X axis, between -1.0 and 1.0 + double RightStickY # Right analog stick value for Y axis, between -1.0 and 1.0 + int(CON) Buttons # The state of available controller buttons. + int Port # The port number assigned to the controller. + ]]) + class("Pointer", { version=1.0, src="class_pointer.cpp", output="class_pointer_def.c", references={ 'PTC', 'PF' } }, [[ double Speed # Speed multiplier (%) double Acceleration # Acceleration level - keep between 0.0 and 3.0 diff --git a/src/display/idl.h b/src/display/idl.h index afe6f3665..8fb6b116b 100644 --- a/src/display/idl.h +++ b/src/display/idl.h @@ -1,2 +1,2 @@ #undef MOD_IDL -#define MOD_IDL "s.SurfaceInfo:pData,lParentID,lBitmapID,lDisplayID,lFlags,lX,lY,lWidth,lHeight,lAbsX,lAbsY,wLevel,cBitsPerPixel,cBytesPerPixel,lLineWidth\ns.SurfaceCoords:lX,lY,lWidth,lHeight,lAbsX,lAbsY\ns.xrMode:lWidth,lHeight,lDepth\ns.PixelFormat:ucRedShift,ucGreenShift,ucBlueShift,ucAlphaShift,ucRedMask,ucGreenMask,ucBlueMask,ucAlphaMask,ucRedPos,ucGreenPos,ucBluePos,ucAlphaPos\ns.DisplayInfo:lDisplay,lFlags,wWidth,wHeight,wBitsPerPixel,wBytesPerPixel,xAccelFlags,lAmtColours,ePixelFormat:PixelFormat,fMinRefresh,fMaxRefresh,fRefreshRate,lIndex,lHDensity,lVDensity\ns.CursorInfo:lWidth,lHeight,lFlags,wBitsPerPixel\ns.BitmapSurface:pData,wWidth,wHeight,lLineWidth,ucBitsPerPixel,ucBytesPerPixel,ucOpacity,ucVersion,lColour,eClip:ClipRectangle,wXOffset,wYOffset,eFormat:ColourFormat\nc.ACF:SOFTWARE_BLIT=0x2,VIDEO_BLIT=0x1\nc.BAF:BLEND=0x2,COPY=0x4,DITHER=0x1,FILL=0x1,LINEAR=0x8\nc.BDF:DITHER=0x2,REDRAW=0x1\nc.BMF:ACCELERATED_2D=0x200,ACCELERATED_3D=0x400,ALPHA_CHANNEL=0x800,BLANK_PALETTE=0x1,CLEAR=0x80,COMPRESSED=0x2,FIXED_DEPTH=0x4000,INVERSE_ALPHA=0x20,MASK=0x10,NEVER_SHRINK=0x1000,NO_BLEND=0x8000,NO_DATA=0x4,PREMUL=0x10000,QUERIED=0x40,TRANSPARENT=0x8,USER=0x100,X11_DGA=0x2000\nc.BMP:CHUNKY=0x3,PLANAR=0x2\nc.CEF:DELETE=0x1,EXTEND=0x2\nc.CLIPTYPE:AUDIO=0x2,DATA=0x1,FILE=0x8,IMAGE=0x4,OBJECT=0x10,TEXT=0x20\nc.CPF:DRAG_DROP=0x1,HISTORY_BUFFER=0x4,HOST=0x2\nc.CRF:BUFFER=0x10,LMB=0x1,MMB=0x2,NO_BUTTONS=0x20,RESTRICT=0x8,RMB=0x4\nc.CS:CIE_LAB=0x3,CIE_LCH=0x4,LINEAR_RGB=0x2,SRGB=0x1\nc.CSRF:ALPHA=0x2,CLIP=0x10,DEFAULT_FORMAT=0x8,OFFSET=0x20,TRANSLUCENT=0x4,TRANSPARENT=0x1\nc.CT:AUDIO=0x1,DATA=0x0,END=0x6,FILE=0x3,IMAGE=0x2,OBJECT=0x4,TEXT=0x5\nc.DPMS:DEFAULT=0x0,OFF=0x1,STANDBY=0x3,SUSPEND=0x2\nc.DRAG:ANCHOR=0x1,NONE=0x0,NORMAL=0x2\nc.DSF:NO_DRAW=0x1,NO_EXPOSE=0x2\nc.DT:GLES=0x4,NATIVE=0x1,WINGDI=0x3,X11=0x2\nc.EXF:ABSOLUTE=0x8,ABSOLUTE_COORDS=0x8,CHILDREN=0x1,CURSOR_SPLIT=0x10,REDRAW_VOLATILE=0x2,REDRAW_VOLATILE_OVERLAP=0x4\nc.FLIP:HORIZONTAL=0x1,VERTICAL=0x2\nc.GMF:SAVE=0x1\nc.HOST:STICK_TO_FRONT=0x3,TASKBAR=0x2,TRANSLUCENCE=0x4,TRANSPARENT=0x5,TRAY_ICON=0x1\nc.IRF:FORCE_DRAW=0x10,IGNORE_CHILDREN=0x2,IGNORE_NV_CHILDREN=0x1,REDRAWS_CHILDREN=0x20,RELATIVE=0x8,SINGLE_BITMAP=0x4\nc.LVF:EXPOSE_CHANGES=0x1\nc.MON:AUTO_DETECT=0x1,BIT_6=0x2\nc.PF:ANCHOR=0x4,UNUSED=0x1,VISIBLE=0x2\nc.RNF:AFTER_COPY=0x8000,ASPECT_RATIO=0x1000000,AUTO_QUIT=0x100,COMPOSITE=0x200000,CURSOR=0x4000,DISABLED=0x80,FIXED_BUFFER=0x10000,FIXED_DEPTH=0x80000,FULL_SCREEN=0x400000,GRAB_FOCUS=0x20,HAS_FOCUS=0x40,HOST=0x200,IGNORE_FOCUS=0x800000,INIT_ONLY=0xcb0e81,NO_FOCUS=0x40000,NO_HORIZONTAL=0x1000,NO_PRECOMPOSITE=0x200000,NO_VERTICAL=0x2000,PERVASIVE_COPY=0x20000,POINTER=0x4000,POST_COMPOSITE=0x200000,PRECOPY=0x400,READ_ONLY=0xc040,STICKY=0x10,STICK_TO_BACK=0x2,STICK_TO_FRONT=0x4,TOTAL_REDRAW=0x100000,TRANSPARENT=0x1,VIDEO=0x800,VISIBLE=0x8,VOLATILE=0xc400,WRITE_ONLY=0x800\nc.RT:ROOT=0x1\nc.SCR:ALPHA_BLEND=0x40,AUTO_SAVE=0x2,BIT_6=0x10,BORDERLESS=0x20,BUFFER=0x4,COMPOSITE=0x40,CUSTOM_WINDOW=0x40000000,DPMS_ENABLED=0x8000000,FLIPPABLE=0x20000000,GTF_ENABLED=0x10000000,HOSTED=0x2000000,MAXIMISE=0x80000000,MAXSIZE=0x100000,NO_ACCELERATION=0x8,POWERSAVE=0x4000000,READ_ONLY=0xfe300019,REFRESH=0x200000,VISIBLE=0x1\nc.SWIN:HOST=0x0,ICON_TRAY=0x2,NONE=0x3,TASKBAR=0x1\nc.WH:CLOSE=0x1\n" +#define MOD_IDL "s.SurfaceInfo:pData,lParentID,lBitmapID,lDisplayID,lFlags,lX,lY,lWidth,lHeight,lAbsX,lAbsY,wLevel,cBitsPerPixel,cBytesPerPixel,lLineWidth\ns.SurfaceCoords:lX,lY,lWidth,lHeight,lAbsX,lAbsY\ns.xrMode:lWidth,lHeight,lDepth\ns.PixelFormat:ucRedShift,ucGreenShift,ucBlueShift,ucAlphaShift,ucRedMask,ucGreenMask,ucBlueMask,ucAlphaMask,ucRedPos,ucGreenPos,ucBluePos,ucAlphaPos\ns.DisplayInfo:lDisplay,lFlags,wWidth,wHeight,wBitsPerPixel,wBytesPerPixel,xAccelFlags,lAmtColours,ePixelFormat:PixelFormat,fMinRefresh,fMaxRefresh,fRefreshRate,lIndex,lHDensity,lVDensity\ns.CursorInfo:lWidth,lHeight,lFlags,wBitsPerPixel\ns.BitmapSurface:pData,wWidth,wHeight,lLineWidth,ucBitsPerPixel,ucBytesPerPixel,ucOpacity,ucVersion,lColour,eClip:ClipRectangle,wXOffset,wYOffset,eFormat:ColourFormat\nc.ACF:SOFTWARE_BLIT=0x2,VIDEO_BLIT=0x1\nc.BAF:BLEND=0x2,COPY=0x4,DITHER=0x1,FILL=0x1,LINEAR=0x8\nc.BDF:DITHER=0x2,REDRAW=0x1\nc.BMF:ACCELERATED_2D=0x200,ACCELERATED_3D=0x400,ALPHA_CHANNEL=0x800,BLANK_PALETTE=0x1,CLEAR=0x80,COMPRESSED=0x2,FIXED_DEPTH=0x4000,INVERSE_ALPHA=0x20,MASK=0x10,NEVER_SHRINK=0x1000,NO_BLEND=0x8000,NO_DATA=0x4,PREMUL=0x10000,QUERIED=0x40,TRANSPARENT=0x8,USER=0x100,X11_DGA=0x2000\nc.BMP:CHUNKY=0x3,PLANAR=0x2\nc.CEF:DELETE=0x1,EXTEND=0x2\nc.CLIPTYPE:AUDIO=0x2,DATA=0x1,FILE=0x8,IMAGE=0x4,OBJECT=0x10,TEXT=0x20\nc.CPF:DRAG_DROP=0x1,HISTORY_BUFFER=0x4,HOST=0x2\nc.CRF:BUFFER=0x10,LMB=0x1,MMB=0x2,NO_BUTTONS=0x20,RESTRICT=0x8,RMB=0x4\nc.CS:CIE_LAB=0x3,CIE_LCH=0x4,LINEAR_RGB=0x2,SRGB=0x1\nc.CSRF:ALPHA=0x2,CLIP=0x10,DEFAULT_FORMAT=0x8,OFFSET=0x20,TRANSLUCENT=0x4,TRANSPARENT=0x1\nc.CT:AUDIO=0x1,DATA=0x0,END=0x6,FILE=0x3,IMAGE=0x2,OBJECT=0x4,TEXT=0x5\nc.DPMS:DEFAULT=0x0,OFF=0x1,STANDBY=0x3,SUSPEND=0x2\nc.DRAG:ANCHOR=0x1,NONE=0x0,NORMAL=0x2\nc.DSF:NO_DRAW=0x1,NO_EXPOSE=0x2\nc.DT:GLES=0x4,NATIVE=0x1,WINGDI=0x3,X11=0x2\nc.EXF:ABSOLUTE=0x8,ABSOLUTE_COORDS=0x8,CHILDREN=0x1,CURSOR_SPLIT=0x10,REDRAW_VOLATILE=0x2,REDRAW_VOLATILE_OVERLAP=0x4\nc.FLIP:HORIZONTAL=0x1,VERTICAL=0x2\nc.GMF:SAVE=0x1\nc.HOST:STICK_TO_FRONT=0x3,TASKBAR=0x2,TRANSLUCENCE=0x4,TRANSPARENT=0x5,TRAY_ICON=0x1\nc.IRF:FORCE_DRAW=0x10,IGNORE_CHILDREN=0x2,IGNORE_NV_CHILDREN=0x1,REDRAWS_CHILDREN=0x20,RELATIVE=0x8,SINGLE_BITMAP=0x4\nc.LVF:EXPOSE_CHANGES=0x1\nc.MON:AUTO_DETECT=0x1,BIT_6=0x2\nc.PF:ANCHOR=0x4,UNUSED=0x1,VISIBLE=0x2\nc.RNF:AFTER_COPY=0x8000,ASPECT_RATIO=0x1000000,AUTO_QUIT=0x100,COMPOSITE=0x200000,CURSOR=0x4000,DISABLED=0x80,FIXED_BUFFER=0x10000,FIXED_DEPTH=0x80000,FULL_SCREEN=0x400000,GRAB_FOCUS=0x20,HAS_FOCUS=0x40,HOST=0x200,IGNORE_FOCUS=0x800000,INIT_ONLY=0xcb0e81,NO_FOCUS=0x40000,NO_HORIZONTAL=0x1000,NO_PRECOMPOSITE=0x200000,NO_VERTICAL=0x2000,PERVASIVE_COPY=0x20000,POINTER=0x4000,POST_COMPOSITE=0x200000,PRECOPY=0x400,READ_ONLY=0xc040,STICKY=0x10,STICK_TO_BACK=0x2,STICK_TO_FRONT=0x4,TOTAL_REDRAW=0x100000,TRANSPARENT=0x1,VIDEO=0x800,VISIBLE=0x8,VOLATILE=0xc400,WRITE_ONLY=0x800\nc.RT:ROOT=0x1\nc.SCR:ALPHA_BLEND=0x40,AUTO_SAVE=0x2,BIT_6=0x10,BORDERLESS=0x20,BUFFER=0x4,COMPOSITE=0x40,CUSTOM_WINDOW=0x40000000,DPMS_ENABLED=0x8000000,FLIPPABLE=0x20000000,GRAB_CONTROLLERS=0x80,GTF_ENABLED=0x10000000,HOSTED=0x2000000,MAXIMISE=0x80000000,MAXSIZE=0x100000,NO_ACCELERATION=0x8,POWERSAVE=0x4000000,READ_ONLY=0xfe300019,REFRESH=0x200000,VISIBLE=0x1\nc.SWIN:HOST=0x0,ICON_TRAY=0x2,NONE=0x3,TASKBAR=0x1\nc.WH:CLOSE=0x1\n" diff --git a/src/display/win32/handlers.cpp b/src/display/win32/handlers.cpp index be915c1fb..407ce5ba2 100644 --- a/src/display/win32/handlers.cpp +++ b/src/display/win32/handlers.cpp @@ -159,6 +159,7 @@ void MsgResizedWindow(OBJECTID SurfaceID, LONG WinX, LONG WinY, LONG WinWidth, L if (ScopedObjectLock surface(SurfaceID, 3000); surface.granted()) { display_id = surface->DisplayID; if (ScopedObjectLock display(display_id, 3000); display.granted()) { + if (!display->ResizeFeedback.defined()) return; feedback = display->ResizeFeedback; display->X = WinX; display->Y = WinY; diff --git a/src/display/win32/windows.cpp b/src/display/win32/windows.cpp index e25d16043..934aae88d 100644 --- a/src/display/win32/windows.cpp +++ b/src/display/win32/windows.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include "windows.h" @@ -72,6 +74,7 @@ typedef long long LARGE; #endif extern HINSTANCE glInstance; +extern int glLastPort; void KillMessageHook(void); static HWND glMainScreen = 0; @@ -570,7 +573,7 @@ static void HandleWheel(HWND window, WPARAM wparam, LPARAM lparam) // the main window. if (auto surface_id = winLookupSurfaceID(window)) { - double delta = -((DOUBLE)GET_WHEEL_DELTA_WPARAM(wparam) / (DOUBLE)WHEEL_DELTA) * 3.0; + double delta = -((double)GET_WHEEL_DELTA_WPARAM(wparam) / (double)WHEEL_DELTA) * 3.0; MsgWheelMovement(surface_id, delta); } } @@ -797,17 +800,33 @@ static LRESULT CALLBACK WindowProcedure(HWND window, UINT msgcode, WPARAM wParam return MA_NOACTIVATE; - case WM_ACTIVATEAPP: + case WM_ACTIVATEAPP: { MSG("WM_ACTIVATEAPP: Focus: %d\n", (int)wParam); + auto surface = winLookupSurfaceID(window); if (wParam) { // We have the focus - MsgFocusState(winLookupSurfaceID(window), TRUE); + MsgFocusState(surface, TRUE); + + #if (_WIN32_WINNT < _WIN32_WINNT_WIN10) + // Deprecated from Windows 10 onwards + //XInputEnable(FALSE); + #endif + + glLastPort = 0; + for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) { + XINPUT_CAPABILITIES cap; + if (XInputGetCapabilities(i, XINPUT_FLAG_GAMEPAD, &cap) == ERROR_SUCCESS) { + glLastPort = i; + } + else break; + } } else { // We have lost the focus - MsgFocusState(winLookupSurfaceID(window), FALSE); + MsgFocusState(surface, FALSE); } return 0; + } case WM_MOVE: { int wx, wy, wwidth, wheight, cx, cy, cwidth, cheight; @@ -924,11 +943,11 @@ static LRESULT CALLBACK WindowProcedure(HWND window, UINT msgcode, WPARAM wParam case WM_RBUTTONUP: HandleButtonRelease(window, WIN_RMB); return 0; case WM_MBUTTONUP: HandleButtonRelease(window, WIN_MMB); return 0; - case WM_NCMOUSEMOVE: - HandleMovement(window, wParam, lParam, true); + case WM_NCMOUSEMOVE: + HandleMovement(window, wParam, lParam, true); return DefWindowProc(window, msgcode, wParam, lParam); - - case WM_NCLBUTTONDOWN: + + case WM_NCLBUTTONDOWN: // Click detected on the titlebar or resize area. Quirks in the way that Windows manages // mouse input mean that we need to signal a button press and release consecutively. MsgButtonPress(WIN_LMB|WIN_NONCLIENT, 1); @@ -938,7 +957,7 @@ static LRESULT CALLBACK WindowProcedure(HWND window, UINT msgcode, WPARAM wParam case WM_NCLBUTTONDBLCLK: // Double-click detected on the titlebar MsgButtonPress(WIN_DBL|WIN_LMB|WIN_NONCLIENT, 1); MsgButtonPress(WIN_DBL|WIN_LMB|WIN_NONCLIENT, 0); - return DefWindowProc(window, msgcode, wParam, lParam); + return DefWindowProc(window, msgcode, wParam, lParam); case WM_ICONNOTIFY: if (lParam == WM_LBUTTONDOWN) { @@ -1041,6 +1060,54 @@ void winDisableBatching(void) //******************************************************************************************************************** +ERR winReadController(int Port, double *Values, CON &Buttons) +{ + constexpr double tolerance = 0.08; // At-rest dead zone tolerance for thumb sticks + XINPUT_STATE state; + if (XInputGetState(Port, &state) == ERROR_SUCCESS) { + Values[0] = double(state.Gamepad.bLeftTrigger) * (1.0 / 255.0); + Values[1] = double(state.Gamepad.bRightTrigger) * (1.0 / 255.0); + Values[2] = std::clamp(double(state.Gamepad.sThumbLX) * (1.0 / 32767.0), -1.0, 1.0); + Values[3] = std::clamp(double(state.Gamepad.sThumbLY) * (1.0 / 32767.0), -1.0, 1.0); + Values[4] = std::clamp(double(state.Gamepad.sThumbRX) * (1.0 / 32767.0), -1.0, 1.0); + Values[5] = std::clamp(double(state.Gamepad.sThumbRY) * (1.0 / 32767.0), -1.0, 1.0); + + if ((Values[2] < tolerance) and (Values[2] > -tolerance) and + (Values[3] < tolerance) and (Values[3] > -tolerance)) { + Values[2] = 0; + Values[3] = 0; + } + + if ((Values[4] < tolerance) and (Values[4] > -tolerance) and + (Values[5] < tolerance) and (Values[5] > -tolerance)) { + Values[4] = 0; + Values[5] = 0; + } + + if (state.Gamepad.wButtons) { + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) Buttons |= CON::DPAD_UP; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) Buttons |= CON::DPAD_DOWN; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) Buttons |= CON::DPAD_LEFT; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) Buttons |= CON::DPAD_RIGHT; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START) Buttons |= CON::START; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) Buttons |= CON::SELECT; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) Buttons |= CON::LEFT_THUMB; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) Buttons |= CON::RIGHT_THUMB; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) Buttons |= CON::LEFT_BUMPER_1; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) Buttons |= CON::RIGHT_BUMPER_1; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A) Buttons |= CON::GAMEPAD_S; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B) Buttons |= CON::GAMEPAD_E; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X) Buttons |= CON::GAMEPAD_W; + if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) Buttons |= CON::GAMEPAD_N; + } + else Buttons = CON::NIL; //state.Gamepad.wButtons; + return ERR::Okay; + } + else return ERR::Failed; +} + +//******************************************************************************************************************** + int winGetDesktopSize(int *width, int *height) { *width = 800; diff --git a/src/display/win32/windows.h b/src/display/win32/windows.h index 25c22eea8..e4b58aa85 100644 --- a/src/display/win32/windows.h +++ b/src/display/win32/windows.h @@ -29,6 +29,30 @@ struct WinDT { void *Data; }; +#if !defined(PARASOL_MAIN_H) && defined(__cplusplus) +enum class CON : unsigned int { + NIL = 0, + GAMEPAD_S = 0x00000001, + GAMEPAD_E = 0x00000002, + GAMEPAD_W = 0x00000004, + GAMEPAD_N = 0x00000008, + DPAD_UP = 0x00000010, + DPAD_DOWN = 0x00000020, + DPAD_LEFT = 0x00000040, + DPAD_RIGHT = 0x00000080, + START = 0x00000100, + SELECT = 0x00000200, + LEFT_BUMPER_1 = 0x00000400, + LEFT_BUMPER_2 = 0x00000800, + RIGHT_BUMPER_1 = 0x00001000, + RIGHT_BUMPER_2 = 0x00002000, + LEFT_THUMB = 0x00004000, + RIGHT_THUMB = 0x00008000 +}; + +DEFINE_ENUM_FLAG_OPERATORS(CON) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -82,6 +106,7 @@ extern void MsgMovement(int, double, double, int, int, bool); extern void MsgWheelMovement(int, float); extern void MsgButtonPress(int, int); extern void MsgFocusState(int SurfaceID, int State); +extern void MsgTotalControllerPorts(int, int); extern void MsgResizedWindow(int, int, int, int, int, int, int, int, int); extern void MsgSetFocus(int SurfaceID); extern void MsgSwitchWindowType(HWND, int); @@ -119,6 +144,7 @@ extern void winMinimiseWindow(HWND); extern int winMoveWindow(HWND, int, int); extern void winMoveToBack(HWND); extern void winMoveToFront(HWND); +extern ERR winReadController(int, double *, CON &); extern int winReadKey(char *, char *, unsigned char *, int); extern int winResizeWindow(HWND, int, int, int, int); extern void winSetCursorPos(int X, int Y); diff --git a/src/svg/gradients.cpp b/src/svg/gradients.cpp index 2d7cdf98d..19f350419 100644 --- a/src/svg/gradients.cpp +++ b/src/svg/gradients.cpp @@ -37,7 +37,7 @@ static const std::vector process_gradient_stops(extSVG *Self, cons stop.RGB.Blue = 0; stop.RGB.Alpha = 0; - for (LONG a=1; a < LONG(scan.Attribs.size()); a++) { + for (LONG a=1; a < std::ssize(scan.Attribs); a++) { auto &name = scan.Attribs[a].Name; auto &value = scan.Attribs[a].Value; if (value.empty()) continue; diff --git a/src/svg/save_svg.cpp b/src/svg/save_svg.cpp index cf1b83ba0..11d6fed2a 100644 --- a/src/svg/save_svg.cpp +++ b/src/svg/save_svg.cpp @@ -96,10 +96,10 @@ static ERR save_svg_defs(extSVG *Self, objXML *XML, objVectorScene *Scene, LONG set_dimension(tag, "cy", gradient->CenterY, (gradient->Flags & VGF::SCALED_CY) != VGF::NIL); if ((error IS ERR::Okay) and ((gradient->Flags & (VGF::FIXED_FX|VGF::SCALED_FX)) != VGF::NIL)) - set_dimension(tag, "fx", gradient->FX, (gradient->Flags & VGF::SCALED_FX) != VGF::NIL); + set_dimension(tag, "fx", gradient->FocalX, (gradient->Flags & VGF::SCALED_FX) != VGF::NIL); if ((error IS ERR::Okay) and ((gradient->Flags & (VGF::FIXED_FY|VGF::SCALED_FY)) != VGF::NIL)) - set_dimension(tag, "fy", gradient->FY, (gradient->Flags & VGF::SCALED_FY) != VGF::NIL); + set_dimension(tag, "fy", gradient->FocalY, (gradient->Flags & VGF::SCALED_FY) != VGF::NIL); if ((error IS ERR::Okay) and ((gradient->Flags & (VGF::FIXED_RADIUS|VGF::SCALED_RADIUS)) != VGF::NIL)) set_dimension(tag, "r", gradient->Radius, (gradient->Flags & VGF::SCALED_RADIUS) != VGF::NIL); diff --git a/src/svg/tests/gradients/w3-pservers-grad-01-b.svg b/src/svg/tests/gradients/w3-pservers-grad-01-b.svg new file mode 100644 index 000000000..a34175111 --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-01-b.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + Linear gradient. + + + Referencing gradient below. + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-02-b.svg b/src/svg/tests/gradients/w3-pservers-grad-02-b.svg new file mode 100644 index 000000000..61b88f1bb --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-02-b.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + Radial gradient. + + + Referencing gradient below. + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-07-b.svg b/src/svg/tests/gradients/w3-pservers-grad-07-b.svg new file mode 100644 index 000000000..9cac36753 --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-07-b.svg @@ -0,0 +1,30 @@ +TR/SVG11/pservers.html#Gradients"> + + + + + + + + + + Linear gradient filled rectangle + + + Linear gradient on stroke of rectangle + + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-08-b.svg b/src/svg/tests/gradients/w3-pservers-grad-08-b.svg new file mode 100644 index 000000000..9340494f5 --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-08-b.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + Gradient on fill + + + Gradient on stroke + + + + Linear gradient on filled text + Linear gradient on stroke of text + + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-09-b.svg b/src/svg/tests/gradients/w3-pservers-grad-09-b.svg new file mode 100644 index 000000000..b2c7f31b4 --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-09-b.svg @@ -0,0 +1,39 @@ + + + Testing gradientUnits attribute + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-11-b.svg b/src/svg/tests/gradients/w3-pservers-grad-11-b.svg new file mode 100644 index 000000000..fd5a9ddbe --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-11-b.svg @@ -0,0 +1,42 @@ + + + + + + + + + + Radial gradient on fill of rectangle + + + + + + + + + Radial gradient on stroke of rectangle + + + + + + + + Gradient on text fill + Radial gradient on text, black to yellow + + + + + + + + Gradient on text stroke + Radial gradient on stroke of text, black to red + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-12-b.svg b/src/svg/tests/gradients/w3-pservers-grad-12-b.svg new file mode 100644 index 000000000..a0545f2ba --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-12-b.svg @@ -0,0 +1,39 @@ + + + + Testing gradientUnits attribute + + + + + + + + + Radial gradient with default attributes (from blue to yellow) + Gradient is blue at the object center and lime at the object edges + + + + + + + + + gradientUnits=objectBoundingBox + cx=.2, cy=.2, r=.5, fx=.2 fy=.2 + + + + + + + + + gradientUnits=userSpaceOnUse + Gradient is yellow to blue radial gradient from center to horizontal bounds + + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-15-b.svg b/src/svg/tests/gradients/w3-pservers-grad-15-b.svg new file mode 100644 index 000000000..3a83ca566 --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-15-b.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/svg/tests/gradients/w3-pservers-grad-22-b.svg b/src/svg/tests/gradients/w3-pservers-grad-22-b.svg new file mode 100644 index 000000000..0fa8a118c --- /dev/null +++ b/src/svg/tests/gradients/w3-pservers-grad-22-b.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/svg/tests/test-svg.fluid b/src/svg/tests/test-svg.fluid index 7d3735105..4009de8cd 100644 --- a/src/svg/tests/test-svg.fluid +++ b/src/svg/tests/test-svg.fluid @@ -66,6 +66,16 @@ function testHoneycomb() hashTestSVG('patterns/honeycomb.svg', 0x7b678a function testSnake() hashTestSVG('patterns/snake.svg', 0xbb7d40f0) end function testVStripes() hashTestSVG('patterns/vstripes.svg', 0x2f85dc21) end +function testW3Gradients01() hashTestSVG('gradients/w3-pservers-grad-01-b.svg', 0xe637a6fa) end +function testW3Gradients02() hashTestSVG('gradients/w3-pservers-grad-02-b.svg', 0x69157174) end +function testW3Gradients07() hashTestSVG('gradients/w3-pservers-grad-07-b.svg', 0xfb7be5fe) end +function testW3Gradients08() hashTestSVG('gradients/w3-pservers-grad-08-b.svg', 0x97f7b810) end +function testW3Gradients09() hashTestSVG('gradients/w3-pservers-grad-09-b.svg', 0xfd34d4f1) end +function testW3Gradients11() hashTestSVG('gradients/w3-pservers-grad-11-b.svg', 0x4f4a58f3) end +function testW3Gradients12() hashTestSVG('gradients/w3-pservers-grad-12-b.svg', 0xd59b60ce) end +function testW3Gradients15() hashTestSVG('gradients/w3-pservers-grad-15-b.svg', 0x531aca96) end +function testW3Gradients22() hashTestSVG('gradients/w3-pservers-grad-22-b.svg', 0x5477019b) end + function testCoarsePaper() hashTestSVG('filters/coarse_paper.svg', 0xc4158cf1) end function testComposite() hashTestSVG('filters/composite.svg', 0x66a96a50) end function testConvolve() hashTestSVG('filters/convolve.svg', 0x29d31e69) end @@ -123,10 +133,10 @@ function testContourGradient() hashTestSVG('misc/contour-gradient.svg', 0x4b8 function testBottleTree() hashTestSVG('images/bottletree.svg', 0xd7fb84ff) end function testButton() hashTestSVG('images/button.svg', 0x0e8f5a31) end -function testClock() hashTestSVG('images/clock.svg', 0xe5ad43cb) end -function testIceCube() hashTestSVG('images/icecube.svg', 0x86d23579) end +function testClock() hashTestSVG('images/clock.svg', 0xa2cf50e4) end +function testIceCube() hashTestSVG('images/icecube.svg', 0xc8dc1cd4) end function testTiger() hashTestSVG('images/tiger.svg', 0xa7b2c808) end -function testPod() hashTestSVG('images/pod.svg', 0x9a0fbeda) end +function testPod() hashTestSVG('images/pod.svg', 0xf51113c0) end function testClip() hashTestSVG('masks/clip.svg', 0x209c16aa) end function testClipViewBox() hashTestSVG('masks/clip-viewbox.svg', 0xd66308b7) end @@ -240,6 +250,15 @@ function testW3TextB25() hashTestSVG('text/w3-text-ws-03-t.svg', -1) end --'testW3MasksOpacity', 'testSplitCircles', 'testInheritClip', + 'testW3Gradients01', + 'testW3Gradients02', + 'testW3Gradients07', + 'testW3Gradients08', + 'testW3Gradients09', + 'testW3Gradients11', + 'testW3Gradients12', + 'testW3Gradients15', + 'testW3Gradients22', -- Patterns 'testChevrons', 'testComplex', diff --git a/src/vector/agg/include/agg_span_gradient_contour.h b/src/vector/agg/include/agg_span_gradient_contour.h index 4d4c17414..4c5413706 100644 --- a/src/vector/agg/include/agg_span_gradient_contour.h +++ b/src/vector/agg/include/agg_span_gradient_contour.h @@ -83,14 +83,14 @@ namespace agg static AGG_INLINE int square(int x) { return x * x; } // DT algorithm by: Pedro Felzenszwalb - void dt(float *spanf, float *spang, float *spanr, int *spann, int length) + void dt(double *spanf, double *spang, double *spanr, int *spann, int length) { int k = 0; - float s; + double s; spann[0] = 0; - spang[0] = float(-infinity); - spang[1] = float(+infinity); + spang[0] = double(-infinity); + spang[1] = double(+infinity); for (int q = 1; q <= length - 1; q++) { s = ((spanf[q ] + square(q)) - (spanf[spann[k]] + square(spann[k]))) / (2 * q - 2 * spann[k]); @@ -103,7 +103,7 @@ namespace agg k++; spann[k ] = q; spang[k ] = s; - spang[k + 1 ] = float(+infinity); + spang[k + 1 ] = double(+infinity); } k = 0; @@ -155,25 +155,25 @@ namespace agg // II. Distance Transform // Create Float Buffer + 0 vs infinity (1e20) assignment - float *image = new float[width * height]; + double *image = new double[width * height]; if (image) { for (int y=0, l=0; y < height; y++) { for (int x=0; x < width; x++, l++) { if (buffer[l] == 0) image[l] = 0.0; - else image[l] = float(infinity); + else image[l] = double(infinity); } } // DT of 2d - // SubBuff max width,height + // SubBuff max width,height int length = width; if (height > length) length = height; - float *spanf = new float[length]; - float *spang = new float[length + 1]; - float *spanr = new float[length]; + double *spanf = new double[length]; + double *spang = new double[length + 1]; + double *spanr = new double[length]; int *spann = new int[length]; if ((spanf) and (spang) and (spanr) and (spann)) { diff --git a/src/vector/defs/gradient.cpp b/src/vector/defs/gradient.cpp index f787e1fb1..07c240eb7 100644 --- a/src/vector/defs/gradient.cpp +++ b/src/vector/defs/gradient.cpp @@ -260,50 +260,81 @@ Lookup: VGF Dimension flags that indicate whether field values are fixed or scaled are defined here. -FIELD- -FX: The horizontal focal point for radial gradients. +FocalRadius: The size of the focal radius for radial gradients. -The `(FX, FY)` coordinates define the focal point for radial gradients. If left undefined, the focal point will match the -center of the gradient. +If a radial gradient has a defined focal point (by setting #FocalX and #FocalY) then the FocalRadius can be used to +adjust the size of the focal area. The default of zero ensures that the focal area matches that defined by #Radius, +which is the standard maintained by SVG. + +The FocalRadius value has no effect if the gradient is linear. + +*********************************************************************************************************************/ + +static ERR VECTORGRADIENT_GET_FocalRadius(extVectorGradient *Self, Unit *Value) +{ + Value->set(Self->FocalRadius); + return ERR::Okay; +} + +static ERR VECTORGRADIENT_SET_FocalRadius(extVectorGradient *Self, Unit &Value) +{ + if (Value >= 0) { + if (Value.scaled()) Self->Flags = (Self->Flags | VGF::SCALED_FOCAL_RADIUS) & (~VGF::FIXED_FOCAL_RADIUS); + else Self->Flags = (Self->Flags | VGF::FIXED_FOCAL_RADIUS) & (~VGF::SCALED_FOCAL_RADIUS); + + Self->FocalRadius = Value; + return ERR::Okay; + } + else return ERR::OutOfRange; +} + +/********************************************************************************************************************* + +-FIELD- +FocalX: The horizontal focal point for radial gradients. + +The `(FocalX, FocalY)` coordinates define the focal point for radial gradients. If left undefined, the focal point +will match the center of the gradient. *********************************************************************************************************************/ -static ERR VECTORGRADIENT_GET_FX(extVectorGradient *Self, Unit *Value) +static ERR VECTORGRADIENT_GET_FocalX(extVectorGradient *Self, Unit *Value) { - Value->set(Self->FX); + Value->set(Self->FocalX); return ERR::Okay; } -static ERR VECTORGRADIENT_SET_FX(extVectorGradient *Self, Unit &Value) +static ERR VECTORGRADIENT_SET_FocalX(extVectorGradient *Self, Unit &Value) { if (Value.scaled()) Self->Flags = (Self->Flags | VGF::SCALED_FX) & (~VGF::FIXED_FX); else Self->Flags = (Self->Flags | VGF::FIXED_FX) & (~VGF::SCALED_FX); - Self->FX = Value; + Self->FocalX = Value; return ERR::Okay; } /********************************************************************************************************************* -FIELD- -FY: The vertical focal point for radial gradients. +FocalY: The vertical focal point for radial gradients. -The `(FX, FY)` coordinates define the focal point for radial gradients. If left undefined, the focal point will match the -center of the gradient. +The `(FocalX, FocalY)` coordinates define the focal point for radial gradients. If left undefined, the focal point +will match the center of the gradient. *********************************************************************************************************************/ -static ERR VECTORGRADIENT_GET_FY(extVectorGradient *Self, Unit *Value) +static ERR VECTORGRADIENT_GET_FocalY(extVectorGradient *Self, Unit *Value) { - Value->set(Self->FY); + Value->set(Self->FocalY); return ERR::Okay; } -static ERR VECTORGRADIENT_SET_FY(extVectorGradient *Self, Unit &Value) +static ERR VECTORGRADIENT_SET_FocalY(extVectorGradient *Self, Unit &Value) { if (Value.scaled()) Self->Flags = (Self->Flags | VGF::SCALED_FY) & (~VGF::FIXED_FY); else Self->Flags = (Self->Flags | VGF::FIXED_FY) & (~VGF::SCALED_FY); - Self->FY = Value; + Self->FocalY = Value; return ERR::Okay; } @@ -311,7 +342,7 @@ static ERR VECTORGRADIENT_SET_FY(extVectorGradient *Self, Unit &Value) -FIELD- ID: String identifier for a vector. -The ID field is provided for the purpose of SVG support. Where possible we would recommend that you use the +The ID field is provided for the purpose of SVG support. Where possible, we recommend that you use the existing object name and automatically assigned ID's for identifiers. *********************************************************************************************************************/ @@ -438,7 +469,7 @@ static ERR VECTORGRADIENT_SET_NumericID(extVectorGradient *Self, LONG Value) -FIELD- Radius: The radius of the gradient. -The radius of the gradient can be defined in fixed units or scaled terms to its container. A default radius of +The radius of the gradient can be defined as a fixed unit or scaled relative to its container. A default radius of 50% (0.5) applies if this field is not set. The Radius value has no effect if the gradient is linear. @@ -469,7 +500,7 @@ static ERR VECTORGRADIENT_SET_Radius(extVectorGradient *Self, Unit &Value) SpreadMethod: The behaviour to use when the gradient bounds do not match the vector path. Indicates what happens if the gradient starts or ends inside the bounds of the target vector. The default is -`VSPREAD::PAD`. +`VSPREAD::PAD`. Other valid options for gradients are `REFLECT` and `REPEAT`. -FIELD- Stops: Defines the colours to use for the gradient. @@ -676,17 +707,22 @@ static const FieldArray clGradientFields[] = { { "Y2", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_Y2, VECTORGRADIENT_SET_Y2 }, { "CenterX", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_CenterX, VECTORGRADIENT_SET_CenterX }, { "CenterY", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_CenterY, VECTORGRADIENT_SET_CenterY }, - { "FX", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FX, VECTORGRADIENT_SET_FX }, - { "FY", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FY, VECTORGRADIENT_SET_FY }, + { "FocalX", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FocalX, VECTORGRADIENT_SET_FocalX }, + { "FocalY", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FocalY, VECTORGRADIENT_SET_FocalY }, { "Radius", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_Radius, VECTORGRADIENT_SET_Radius }, + { "FocalRadius", FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FocalRadius, VECTORGRADIENT_SET_FocalRadius }, { "Inherit", FDF_OBJECT|FDF_RW, NULL, VECTORGRADIENT_SET_Inherit }, { "SpreadMethod", FDF_LONG|FDF_LOOKUP|FDF_RW, NULL, NULL, &clVectorGradientSpreadMethod }, { "Units", FDF_LONG|FDF_LOOKUP|FDF_RI, NULL, NULL, &clVectorGradientUnits }, - { "Type", FDF_LONG|FDF_LOOKUP|FDF_RI, NULL, NULL, &clVectorGradientType }, + { "Type", FDF_LONG|FDF_LOOKUP|FDF_RW, NULL, NULL, &clVectorGradientType }, { "Flags", FDF_LONGFLAGS|FDF_RW, NULL, NULL, &clVectorGradientFlags }, { "ColourSpace", FDF_LONG|FDF_RI, NULL, NULL, &clVectorGradientColourSpace }, { "TotalStops", FDF_LONG|FDF_R }, // Virtual fields + { "CX", FDF_VIRTUAL|FDF_SYNONYM|FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_CenterX, VECTORGRADIENT_SET_CenterX }, + { "CY", FDF_VIRTUAL|FDF_SYNONYM|FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_CenterY, VECTORGRADIENT_SET_CenterY }, + { "FX", FDF_VIRTUAL|FDF_SYNONYM|FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FocalX, VECTORGRADIENT_SET_FocalX }, + { "FY", FDF_VIRTUAL|FDF_SYNONYM|FDF_UNIT|FDF_DOUBLE|FDF_SCALED|FDF_RW, VECTORGRADIENT_GET_FocalY, VECTORGRADIENT_SET_FocalY }, { "Matrices", FDF_VIRTUAL|FDF_POINTER|FDF_STRUCT|FDF_RW, VECTORGRADIENT_GET_Matrices, VECTORGRADIENT_SET_Matrices, "VectorMatrix" }, { "NumericID", FDF_VIRTUAL|FDF_LONG|FDF_RW, VECTORGRADIENT_GET_NumericID, VECTORGRADIENT_SET_NumericID }, { "ID", FDF_VIRTUAL|FDF_STRING|FDF_RW, VECTORGRADIENT_GET_ID, VECTORGRADIENT_SET_ID }, diff --git a/src/vector/defs/gradient_def.c b/src/vector/defs/gradient_def.c index d2d2e4a3c..82183f190 100644 --- a/src/vector/defs/gradient_def.c +++ b/src/vector/defs/gradient_def.c @@ -37,15 +37,17 @@ static const struct FieldDef clVectorGradientFlags[] = { { "ScaledFX", 0x00000040 }, { "ScaledFY", 0x00000080 }, { "ScaledRadius", 0x00000100 }, - { "FixedX1", 0x00000200 }, - { "FixedY1", 0x00000400 }, - { "FixedX2", 0x00000800 }, - { "FixedY2", 0x00001000 }, - { "FixedCX", 0x00002000 }, - { "FixedCY", 0x00004000 }, - { "FixedFX", 0x00008000 }, - { "FixedFY", 0x00010000 }, - { "FixedRadius", 0x00020000 }, + { "ScaledFocalRadius", 0x00000200 }, + { "FixedX1", 0x00000400 }, + { "FixedY1", 0x00000800 }, + { "FixedX2", 0x00001000 }, + { "FixedY2", 0x00002000 }, + { "FixedCX", 0x00004000 }, + { "FixedCY", 0x00008000 }, + { "FixedFX", 0x00010000 }, + { "FixedFY", 0x00020000 }, + { "FixedRadius", 0x00040000 }, + { "FixedFocalRadius", 0x00080000 }, { NULL, 0 } }; diff --git a/src/vector/idl.h b/src/vector/idl.h index cb51c0287..05dd835dd 100644 --- a/src/vector/idl.h +++ b/src/vector/idl.h @@ -1,2 +1,2 @@ #undef MOD_IDL -#define MOD_IDL "s.GradientStop:dOffset,eRGB:FRGB\ns.Transition:dOffset,sTransform\ns.VectorPoint:dX,dY,ucBit,ucBit\ns.VectorPainter:oPattern,oImage,oGradient,eColour:FRGB\ns.PathCommand:lType,ucLargeArc,ucSweep,ucPad1,dX,dY,dAbsX,dAbsY,dX2,dY2,dX3,dY3,dAngle\ns.VectorMatrix:pNext:VectorMatrix,oVector,dScaleX,dShearY,dShearX,dScaleY,dTranslateX,dTranslateY,lTag\ns.FontMetrics:lHeight,lLineSpacing,lAscent,lDescent\ns.MergeSource:lSourceType,oEffect\nc.ARC:LARGE=0x1,SWEEP=0x2\nc.ARF:MEET=0x40,NONE=0x100,SLICE=0x80,X_MAX=0x4,X_MID=0x2,X_MIN=0x1,Y_MAX=0x20,Y_MID=0x10,Y_MIN=0x8\nc.CM:BRIGHTNESS=0x6,COLOURISE=0x9,CONTRAST=0x5,DESATURATE=0x8,HUE=0x7,HUE_ROTATE=0x3,LUMINANCE_ALPHA=0x4,MATRIX=0x1,NONE=0x0,SATURATE=0x2\nc.CMP:ALL=0xffffffff,ALPHA=0x3,BLUE=0x2,GREEN=0x1,RED=0x0\nc.EM:DUPLICATE=0x1,NONE=0x3,WRAP=0x2\nc.FM:CHILD_HAS_FOCUS=0x4,HAS_FOCUS=0x2,LOST_FOCUS=0x8,PATH_CHANGED=0x1\nc.LS:DISTANT=0x0,POINT=0x2,SPOT=0x1\nc.LT:DIFFUSE=0x0,SPECULAR=0x1\nc.MOP:DILATE=0x1,ERODE=0x0\nc.OP:ARITHMETIC=0x5,ATOP=0x3,BURN=0xe,CONTRAST=0xc,DARKEN=0x9,DIFFERENCE=0x11,DODGE=0xd,EXCLUSION=0x12,HARD_LIGHT=0xf,IN=0x1,INVERT=0xb,INVERT_RGB=0xa,LIGHTEN=0x8,MINUS=0x14,MULTIPLY=0x7,OUT=0x2,OVER=0x0,OVERLAY=0x15,PLUS=0x13,SCREEN=0x6,SOFT_LIGHT=0x10,SUBTRACT=0x14,XOR=0x4\nc.PE:Arc=0x11,ArcRel=0x12,ClosePath=0x13,Curve=0x9,CurveRel=0xa,HLine=0x5,HLineRel=0x6,Line=0x3,LineRel=0x4,Move=0x1,MoveRel=0x2,QuadCurve=0xd,QuadCurveRel=0xe,QuadSmooth=0xf,QuadSmoothRel=0x10,Smooth=0xb,SmoothRel=0xc,VLine=0x7,VLineRel=0x8\nc.RC:ALL=0x7,BASE_PATH=0x2,FINAL_PATH=0x1,TRANSFORM=0x4\nc.RQ:AUTO=0x0,BEST=0x4,CRISP=0x2,FAST=0x1,PRECISE=0x3\nc.TB:NOISE=0x1,TURBULENCE=0x0\nc.VBF:INCLUSIVE=0x1,NO_TRANSFORM=0x2\nc.VCLF:APPLY_FILLS=0x1,APPLY_STROKES=0x2\nc.VCS:INHERIT=0x0,LINEAR_RGB=0x2,SRGB=0x1\nc.VF:DISABLED=0x1,HAS_FOCUS=0x2,JOIN_PATHS=0x4\nc.VFA:MEET=0x0,NONE=0x1\nc.VFR:END=0x4,EVEN_ODD=0x2,INHERIT=0x3,NON_ZERO=0x1\nc.VGF:FIXED_CX=0x2000,FIXED_CY=0x4000,FIXED_FX=0x8000,FIXED_FY=0x10000,FIXED_RADIUS=0x20000,FIXED_X1=0x200,FIXED_X2=0x800,FIXED_Y1=0x400,FIXED_Y2=0x1000,SCALED_CX=0x10,SCALED_CY=0x20,SCALED_FX=0x40,SCALED_FY=0x80,SCALED_RADIUS=0x100,SCALED_X1=0x1,SCALED_X2=0x4,SCALED_Y1=0x2,SCALED_Y2=0x8\nc.VGT:CONIC=0x2,CONTOUR=0x4,DIAMOND=0x3,LINEAR=0x0,RADIAL=0x1\nc.VIJ:BEVEL=0x1,INHERIT=0x5,JAG=0x3,MITER=0x2,ROUND=0x4\nc.VIS:COLLAPSE=0x2,HIDDEN=0x0,INHERIT=0x3,VISIBLE=0x1\nc.VLC:BUTT=0x1,INHERIT=0x4,ROUND=0x3,SQUARE=0x2\nc.VLJ:BEVEL=0x3,INHERIT=0x5,MITER=0x0,MITER_REVERT=0x1,MITER_ROUND=0x4,ROUND=0x2\nc.VMF:AUTO_SPACING=0x2,STRETCH=0x1,X_MAX=0x10,X_MID=0x8,X_MIN=0x4,Y_MAX=0x80,Y_MID=0x40,Y_MIN=0x20\nc.VOF:HIDDEN=0x1,INHERIT=0x3,SCROLL=0x2,VISIBLE=0x0\nc.VPF:BITMAP_SIZED=0x1,OUTLINE_VIEWPORTS=0x8,RENDER_TIME=0x2,RESIZE=0x4\nc.VSM:AUTO=0x0,BESSEL=0x8,BICUBIC=0x3,BILINEAR=0x2,BLACKMAN3=0xc,BLACKMAN8=0xf,GAUSSIAN=0x7,KAISER=0x5,LANCZOS3=0xb,LANCZOS8=0xe,MITCHELL=0x9,NEIGHBOUR=0x1,QUADRIC=0x6,SINC3=0xa,SINC8=0xd,SPLINE16=0x4\nc.VSPREAD:CLIP=0x6,END=0x7,PAD=0x1,REFLECT=0x2,REFLECT_X=0x4,REFLECT_Y=0x5,REPEAT=0x3,UNDEFINED=0x0\nc.VTS:CONDENSED=0x6,EXPANDED=0x8,EXTRA_CONDENSED=0x5,EXTRA_EXPANDED=0xb,INHERIT=0x0,NARROWER=0x3,NORMAL=0x1,SEMI_CONDENSED=0x7,SEMI_EXPANDED=0x9,ULTRA_CONDENSED=0x4,ULTRA_EXPANDED=0xa,WIDER=0x2\nc.VTXF:AREA_SELECTED=0x20,BLINK=0x8,EDIT=0x10,EDITABLE=0x10,LINE_THROUGH=0x4,NO_SYS_KEYS=0x40,OVERLINE=0x2,OVERWRITE=0x80,RASTER=0x200,SECRET=0x100,UNDERLINE=0x1\nc.VUNIT:BOUNDING_BOX=0x1,END=0x3,UNDEFINED=0x0,USERSPACE=0x2\nc.WVC:BOTTOM=0x3,NONE=0x1,TOP=0x2\nc.WVS:ANGLED=0x2,CURVED=0x1,SAWTOOTH=0x3\n" +#define MOD_IDL "s.GradientStop:dOffset,eRGB:FRGB\ns.Transition:dOffset,sTransform\ns.VectorPoint:dX,dY,ucBit,ucBit\ns.VectorPainter:oPattern,oImage,oGradient,eColour:FRGB\ns.PathCommand:lType,ucLargeArc,ucSweep,ucPad1,dX,dY,dAbsX,dAbsY,dX2,dY2,dX3,dY3,dAngle\ns.VectorMatrix:pNext:VectorMatrix,oVector,dScaleX,dShearY,dShearX,dScaleY,dTranslateX,dTranslateY,lTag\ns.FontMetrics:lHeight,lLineSpacing,lAscent,lDescent\ns.MergeSource:lSourceType,oEffect\nc.ARC:LARGE=0x1,SWEEP=0x2\nc.ARF:MEET=0x40,NONE=0x100,SLICE=0x80,X_MAX=0x4,X_MID=0x2,X_MIN=0x1,Y_MAX=0x20,Y_MID=0x10,Y_MIN=0x8\nc.CM:BRIGHTNESS=0x6,COLOURISE=0x9,CONTRAST=0x5,DESATURATE=0x8,HUE=0x7,HUE_ROTATE=0x3,LUMINANCE_ALPHA=0x4,MATRIX=0x1,NONE=0x0,SATURATE=0x2\nc.CMP:ALL=0xffffffff,ALPHA=0x3,BLUE=0x2,GREEN=0x1,RED=0x0\nc.EM:DUPLICATE=0x1,NONE=0x3,WRAP=0x2\nc.FM:CHILD_HAS_FOCUS=0x4,HAS_FOCUS=0x2,LOST_FOCUS=0x8,PATH_CHANGED=0x1\nc.LS:DISTANT=0x0,POINT=0x2,SPOT=0x1\nc.LT:DIFFUSE=0x0,SPECULAR=0x1\nc.MOP:DILATE=0x1,ERODE=0x0\nc.OP:ARITHMETIC=0x5,ATOP=0x3,BURN=0xe,CONTRAST=0xc,DARKEN=0x9,DIFFERENCE=0x11,DODGE=0xd,EXCLUSION=0x12,HARD_LIGHT=0xf,IN=0x1,INVERT=0xb,INVERT_RGB=0xa,LIGHTEN=0x8,MINUS=0x14,MULTIPLY=0x7,OUT=0x2,OVER=0x0,OVERLAY=0x15,PLUS=0x13,SCREEN=0x6,SOFT_LIGHT=0x10,SUBTRACT=0x14,XOR=0x4\nc.PE:Arc=0x11,ArcRel=0x12,ClosePath=0x13,Curve=0x9,CurveRel=0xa,HLine=0x5,HLineRel=0x6,Line=0x3,LineRel=0x4,Move=0x1,MoveRel=0x2,QuadCurve=0xd,QuadCurveRel=0xe,QuadSmooth=0xf,QuadSmoothRel=0x10,Smooth=0xb,SmoothRel=0xc,VLine=0x7,VLineRel=0x8\nc.RC:ALL=0x7,BASE_PATH=0x2,FINAL_PATH=0x1,TRANSFORM=0x4\nc.RQ:AUTO=0x0,BEST=0x4,CRISP=0x2,FAST=0x1,PRECISE=0x3\nc.TB:NOISE=0x1,TURBULENCE=0x0\nc.VBF:INCLUSIVE=0x1,NO_TRANSFORM=0x2\nc.VCLF:APPLY_FILLS=0x1,APPLY_STROKES=0x2\nc.VCS:INHERIT=0x0,LINEAR_RGB=0x2,SRGB=0x1\nc.VF:DISABLED=0x1,HAS_FOCUS=0x2,JOIN_PATHS=0x4\nc.VFA:MEET=0x0,NONE=0x1\nc.VFR:END=0x4,EVEN_ODD=0x2,INHERIT=0x3,NON_ZERO=0x1\nc.VGF:FIXED_CX=0x4000,FIXED_CY=0x8000,FIXED_FOCAL_RADIUS=0x80000,FIXED_FX=0x10000,FIXED_FY=0x20000,FIXED_RADIUS=0x40000,FIXED_X1=0x400,FIXED_X2=0x1000,FIXED_Y1=0x800,FIXED_Y2=0x2000,SCALED_CX=0x10,SCALED_CY=0x20,SCALED_FOCAL_RADIUS=0x200,SCALED_FX=0x40,SCALED_FY=0x80,SCALED_RADIUS=0x100,SCALED_X1=0x1,SCALED_X2=0x4,SCALED_Y1=0x2,SCALED_Y2=0x8\nc.VGT:CONIC=0x2,CONTOUR=0x4,DIAMOND=0x3,LINEAR=0x0,RADIAL=0x1\nc.VIJ:BEVEL=0x1,INHERIT=0x5,JAG=0x3,MITER=0x2,ROUND=0x4\nc.VIS:COLLAPSE=0x2,HIDDEN=0x0,INHERIT=0x3,VISIBLE=0x1\nc.VLC:BUTT=0x1,INHERIT=0x4,ROUND=0x3,SQUARE=0x2\nc.VLJ:BEVEL=0x3,INHERIT=0x5,MITER=0x0,MITER_REVERT=0x1,MITER_ROUND=0x4,ROUND=0x2\nc.VMF:AUTO_SPACING=0x2,STRETCH=0x1,X_MAX=0x10,X_MID=0x8,X_MIN=0x4,Y_MAX=0x80,Y_MID=0x40,Y_MIN=0x20\nc.VOF:HIDDEN=0x1,INHERIT=0x3,SCROLL=0x2,VISIBLE=0x0\nc.VPF:BITMAP_SIZED=0x1,OUTLINE_VIEWPORTS=0x8,RENDER_TIME=0x2,RESIZE=0x4\nc.VSM:AUTO=0x0,BESSEL=0x8,BICUBIC=0x3,BILINEAR=0x2,BLACKMAN3=0xc,BLACKMAN8=0xf,GAUSSIAN=0x7,KAISER=0x5,LANCZOS3=0xb,LANCZOS8=0xe,MITCHELL=0x9,NEIGHBOUR=0x1,QUADRIC=0x6,SINC3=0xa,SINC8=0xd,SPLINE16=0x4\nc.VSPREAD:CLIP=0x6,END=0x7,PAD=0x1,REFLECT=0x2,REFLECT_X=0x4,REFLECT_Y=0x5,REPEAT=0x3,UNDEFINED=0x0\nc.VTS:CONDENSED=0x6,EXPANDED=0x8,EXTRA_CONDENSED=0x5,EXTRA_EXPANDED=0xb,INHERIT=0x0,NARROWER=0x3,NORMAL=0x1,SEMI_CONDENSED=0x7,SEMI_EXPANDED=0x9,ULTRA_CONDENSED=0x4,ULTRA_EXPANDED=0xa,WIDER=0x2\nc.VTXF:AREA_SELECTED=0x20,BLINK=0x8,EDIT=0x10,EDITABLE=0x10,LINE_THROUGH=0x4,NO_SYS_KEYS=0x40,OVERLINE=0x2,OVERWRITE=0x80,RASTER=0x200,SECRET=0x100,UNDERLINE=0x1\nc.VUNIT:BOUNDING_BOX=0x1,END=0x3,UNDEFINED=0x0,USERSPACE=0x2\nc.WVC:BOTTOM=0x3,NONE=0x1,TOP=0x2\nc.WVS:ANGLED=0x2,CURVED=0x1,SAWTOOTH=0x3\n" diff --git a/src/vector/scene/scene_fill.cpp b/src/vector/scene/scene_fill.cpp index 3dddaa358..684ba518e 100644 --- a/src/vector/scene/scene_fill.cpp +++ b/src/vector/scene/scene_fill.cpp @@ -74,7 +74,7 @@ static void fill_image(VectorState &State, const TClipRectangle &Bounds, Path.approximation_scale(Transform.scale()); DOUBLE x_scale, y_scale, x_offset, y_offset; - calc_aspectratio("fill_image", Image.AspectRatio, c_width, c_height, + calc_aspectratio("fill_image", Image.AspectRatio, c_width, c_height, Image.Bitmap->Width, Image.Bitmap->Height, &x_offset, &y_offset, &x_scale, &y_scale); agg::trans_affine transform; @@ -121,6 +121,24 @@ static void fill_gradient(VectorState &State, const TClipRectangle &Boun Path->approximation_scale(Transform.scale()); + auto render_gradient = [&](S SpreadMethod, DOUBLE Span) { + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + span_gradient_type span_gradient(span_interpolator, SpreadMethod, *Table, 0, Span); + renderer_gradient_type solidrender_gradient(RenderBase, span_allocator, span_gradient); + + if (State.mClipStack->empty()) { + agg::scanline_u8 scanline; + agg::render_scanlines(Raster, scanline, solidrender_gradient); + } + else { // Masked gradient + agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); + agg::scanline_u8_am masked_scanline(alpha_mask); + agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); + } + }; + if (Gradient.Type IS VGT::LINEAR) { TClipRectangle area; @@ -173,123 +191,117 @@ static void fill_gradient(VectorState &State, const TClipRectangle &Boun if ((Gradient.Flags & VGF::SCALED_CY) != VGF::NIL) c.y = y_offset + (c_height * Gradient.CenterY); else c.y = y_offset + Gradient.CenterY; - if ((Gradient.Flags & VGF::SCALED_FX) != VGF::NIL) f.x = x_offset + (c_width * Gradient.FX); - else if ((Gradient.Flags & VGF::FIXED_FX) != VGF::NIL) f.x = x_offset + Gradient.FX; - else f.x = x_offset + c.x; + if ((Gradient.Flags & VGF::SCALED_FX) != VGF::NIL) f.x = x_offset + (c_width * Gradient.FocalX); + else if ((Gradient.Flags & VGF::FIXED_FX) != VGF::NIL) f.x = x_offset + Gradient.FocalX; + else f.x = c.x; - if ((Gradient.Flags & VGF::SCALED_FY) != VGF::NIL) f.y = y_offset + (c_height * Gradient.FY); - else if ((Gradient.Flags & VGF::FIXED_FY) != VGF::NIL) f.y = y_offset + Gradient.FY; - else f.y = y_offset + c.y; + if ((Gradient.Flags & VGF::SCALED_FY) != VGF::NIL) f.y = y_offset + (c_height * Gradient.FocalY); + else if ((Gradient.Flags & VGF::FIXED_FY) != VGF::NIL) f.y = y_offset + Gradient.FocalY; + else f.y = c.y; if ((c.x IS f.x) and (c.y IS f.y)) { // Standard radial gradient, where the focal point is the same as the gradient center - DOUBLE length = Gradient.Radius; + DOUBLE radial_col_span = Gradient.Radius; if (Gradient.Units IS VUNIT::USERSPACE) { // Coordinates are relative to the viewport if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { // Gradient is a ratio of the viewport's dimensions - length = (ViewWidth + ViewHeight) * Gradient.Radius * 0.5; + radial_col_span = (ViewWidth + ViewHeight) * Gradient.Radius * 0.5; } } else { // Coordinates are scaled to the bounding box if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - // In AGG, an unscaled gradient will cover the entire bounding box according to the diagonal. - // In SVG a radius of 50% must result in the edge of the radius meeting the edge of the bounding box. - - DOUBLE scale_x = Gradient.Radius * (1.0 / 0.707106781); //(width * Gradient.Radius) / (sqrt((width * width) + (width * width)) * 0.5); - DOUBLE scale_y = Gradient.Radius * (1.0 / 0.707106781); //(height * Gradient.Radius) / (sqrt((height * height) + (height * height)) * 0.5); - if (c_height > c_width) scale_y *= c_height / c_width; - else if (c_width > c_height) scale_x *= c_width / c_height; - scale_x *= 100.0 / length; // Adjust the scale according to the gradient length. - scale_y *= 100.0 / length; - transform.scale(scale_x, scale_y); + // Set radial_col_span to the wider of the width/height + if (c_height > c_width) { + radial_col_span = c_height * Gradient.Radius; + transform.scaleX(c_width / c_height); + } + else { + radial_col_span = c_width * Gradient.Radius; + transform.scaleY(c_height / c_width); + } } else { - //transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01 / length); + //transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01 / radial_col_span); } } - if (length < 255) { // Blending works best if the gradient span is at least 255 colours wide, so adjust it here. - transform.scale(length * (1.0 / 255.0)); - length = 255; + constexpr double MIN_SPAN = 32; + if (radial_col_span < MIN_SPAN) { // Blending looks best if it meets a minimum span (radius) value. + transform.scale(radial_col_span * (1.0 / MIN_SPAN)); + radial_col_span = MIN_SPAN; } - agg::gradient_radial gradient_func; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - span_gradient_type span_gradient(span_interpolator, gradient_func, *Table, 0, length); - renderer_gradient_type solidrender_gradient(RenderBase, span_allocator, span_gradient); - - transform.translate(c.x, c.y); + transform.translate(c); apply_transforms(Gradient, transform); transform *= Transform; transform.invert(); - if (State.mClipStack->empty()) { - agg::scanline_u8 scanline; - agg::render_scanlines(Raster, scanline, solidrender_gradient); - } - else { // Masked gradient - agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); - agg::scanline_u8_am masked_scanline(alpha_mask); + agg::gradient_radial gradient_func; - agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); + if (Gradient.SpreadMethod IS VSPREAD::REFLECT) { + agg::gradient_reflect_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); + } + else if (Gradient.SpreadMethod IS VSPREAD::REPEAT) { + agg::gradient_repeat_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); } + else render_gradient(gradient_func, radial_col_span); } else { // Radial gradient with a displaced focal point (uses agg::gradient_radial_focus). NB: In early versions of - // the SVG standard, the focal point had to be within the radius. Later specifications allowed it to - // be placed outside of the radius. + // the SVG standard, the focal point had to be within the base radius. Later specifications allowed it to + // be placed outside of that radius. - DOUBLE fix_radius = Gradient.Radius; - if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - fix_radius *= (c_width + c_height) * 0.5; // Use the average radius of the ellipse. - } - DOUBLE length = fix_radius; + DOUBLE radial_col_span = Gradient.Radius; + DOUBLE focal_radius = Gradient.FocalRadius; + if (focal_radius <= 0) focal_radius = Gradient.Radius; - if (Gradient.Units IS VUNIT::USERSPACE) { - if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - const DOUBLE scale = length * Gradient.Radius; - transform *= agg::trans_affine_scaling(sqrt((ViewWidth * ViewWidth) + (ViewHeight * ViewHeight)) / scale); + if (Gradient.Units IS VUNIT::USERSPACE) { // Coordinates are relative to the viewport + if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { // Gradient is a ratio of the viewport's dimensions + radial_col_span = (ViewWidth + ViewHeight) * radial_col_span * 0.5; + focal_radius = (ViewWidth + ViewHeight) * focal_radius * 0.5; } - else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } - else { // Bounding box + else { // Coordinates are scaled to the bounding box if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - // In AGG, an unscaled gradient will cover the entire bounding box according to the diagonal. - // In SVG a radius of 50% must result in the edge of the radius meeting the edge of the bounding box. - - auto scale = agg::point_d(Gradient.Radius * (1.0 / 0.707106781), Gradient.Radius * (1.0 / 0.707106781)); - if (c_height > c_width) scale.y *= c_height / c_width; - else if (c_width > c_height) scale.x *= c_width / c_height; - scale.x *= 100.0 / length; // Adjust the scale according to the gradient length. - scale.y *= 100.0 / length; - transform.scale(scale); + // Set radial_col_span to the wider of the width/height + if (c_height > c_width) { + radial_col_span = c_height * radial_col_span; + focal_radius = c_height * focal_radius; + transform.scaleX(c_width / c_height); + } + else { + radial_col_span = c_width * radial_col_span; + focal_radius = c_width * focal_radius; + transform.scaleY(c_height / c_width); + } + } + else { + //transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01 / radial_col_span); } - else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } - agg::gradient_radial_focus gradient_func(fix_radius, f.x - c.x, f.y - c.y); + // Changing the focal radius allows the client to increase or decrease the border to which the focal + // calculations are being made. If not supported by the underlying implementation (e.g. SVG) then + // it must match the base radius. - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - span_gradient_type span_gradient(span_interpolator, gradient_func, *Table, 0, fix_radius); - renderer_gradient_type solidrender_gradient(RenderBase, span_allocator, span_gradient); + agg::gradient_radial_focus gradient_func(focal_radius, f.x - c.x, f.y - c.y); transform.translate(c); apply_transforms(Gradient, transform); transform *= Transform; transform.invert(); - if (State.mClipStack->empty()) { - agg::scanline_u8 scanline; - agg::render_scanlines(Raster, scanline, solidrender_gradient); + if (Gradient.SpreadMethod IS VSPREAD::REFLECT) { + agg::gradient_reflect_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); } - else { // Masked gradient - agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); - agg::scanline_u8_am masked_scanline(alpha_mask); - - agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); + else if (Gradient.SpreadMethod IS VSPREAD::REPEAT) { + agg::gradient_repeat_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); } + else render_gradient(gradient_func, radial_col_span); } } else if (Gradient.Type IS VGT::DIAMOND) { @@ -303,50 +315,44 @@ static void fill_gradient(VectorState &State, const TClipRectangle &Boun // Standard diamond gradient, where the focal point is the same as the gradient center - const DOUBLE length = 255; + DOUBLE radial_col_span = Gradient.Radius; if (Gradient.Units IS VUNIT::USERSPACE) { if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - const DOUBLE scale = length * Gradient.Radius; - transform *= agg::trans_affine_scaling(sqrt((c_width * c_width) + (c_height * c_height)) / scale); + radial_col_span = (ViewWidth + ViewHeight) * Gradient.Radius * 0.5; } else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } else { // Align to vector's bounding box if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - // In AGG, an unscaled gradient will cover the entire bounding box according to the diagonal. - // In SVG a radius of 50% must result in the edge of the radius meeting the edge of the bounding box. - - auto scale = agg::point_d(Gradient.Radius * (1.0 / 0.707106781), Gradient.Radius * (1.0 / 0.707106781)); - if (c_height > c_width) scale.y *= c_height / c_width; - else if (c_width > c_height) scale.x *= c_width / c_height; - scale.x *= 100.0 / length; // Adjust the scale according to the gradient length. - scale.y *= 100.0 / length; - transform.scale(scale.x, scale.y); + // Set radial_col_span to the wider of the width/height + if (c_height > c_width) { + radial_col_span = c_height * Gradient.Radius; + transform.scaleX(c_width / c_height); + } + else { + radial_col_span = c_width * Gradient.Radius; + transform.scaleY(c_height / c_width); + } } else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } agg::gradient_diamond gradient_func; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - span_gradient_type span_gradient(span_interpolator, gradient_func, *Table, 0, length); - renderer_gradient_type solidrender_gradient(RenderBase, span_allocator, span_gradient); transform.translate(c); apply_transforms(Gradient, transform); transform *= Transform; transform.invert(); - if (State.mClipStack->empty()) { - agg::scanline_u8 scanline; - agg::render_scanlines(Raster, scanline, solidrender_gradient); + if (Gradient.SpreadMethod IS VSPREAD::REFLECT) { + agg::gradient_reflect_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); } - else { // Masked gradient - agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); - agg::scanline_u8_am masked_scanline(alpha_mask); - - agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); + else if (Gradient.SpreadMethod IS VSPREAD::REPEAT) { + agg::gradient_repeat_adaptor spread_method(gradient_func); + render_gradient(spread_method, radial_col_span); } + else render_gradient(gradient_func, radial_col_span); } else if (Gradient.Type IS VGT::CONIC) { agg::point_d c; @@ -359,50 +365,35 @@ static void fill_gradient(VectorState &State, const TClipRectangle &Boun // Standard conic gradient, where the focal point is the same as the gradient center - const DOUBLE length = 255; + DOUBLE radial_col_span = Gradient.Radius; if (Gradient.Units IS VUNIT::USERSPACE) { if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - const DOUBLE scale = length * Gradient.Radius; - transform *= agg::trans_affine_scaling(sqrt((c_width * c_width) + (c_height * c_height)) / scale); + radial_col_span = (ViewWidth + ViewHeight) * Gradient.Radius * 0.5; } else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } else { // Bounding box if ((Gradient.Flags & VGF::SCALED_RADIUS) != VGF::NIL) { - // In AGG, an unscaled gradient will cover the entire bounding box according to the diagonal. - // In SVG a radius of 50% must result in the edge of the radius meeting the edge of the bounding box. - - agg::point_d scale(Gradient.Radius * (1.0 / 0.707106781), Gradient.Radius * (1.0 / 0.707106781)); - if (c_height > c_width) scale.y *= c_height / c_width; - else if (c_width > c_height) scale.x *= c_width / c_height; - scale.x *= 100.0 / length; // Adjust the scale according to the gradient length. - scale.y *= 100.0 / length; - transform.scale(scale); + // Set radial_col_span to the wider of the width/height + if (c_height > c_width) { + radial_col_span = c_height * Gradient.Radius; + transform.scaleX(c_width / c_height); + } + else { + radial_col_span = c_width * Gradient.Radius; + transform.scaleY(c_height / c_width); + } } else transform *= agg::trans_affine_scaling(Gradient.Radius * 0.01); } agg::gradient_conic gradient_func; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - span_gradient_type span_gradient(span_interpolator, gradient_func, *Table, 0, length); - renderer_gradient_type solidrender_gradient(RenderBase, span_allocator, span_gradient); - transform.translate(c); apply_transforms(Gradient, transform); transform *= Transform; transform.invert(); - if (State.mClipStack->empty()) { - agg::scanline_u8 scanline; - agg::render_scanlines(Raster, scanline, solidrender_gradient); - } - else { // Masked gradient - agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); - agg::scanline_u8_am masked_scanline(alpha_mask); - - agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); - } + render_gradient(gradient_func, radial_col_span); } else if (Gradient.Type IS VGT::CONTOUR) { // NOTE: Contouring requires a bounding box and is thus incompatible with UserSpaceOnUse if (Gradient.Units != VUNIT::BOUNDING_BOX) return; @@ -433,7 +424,6 @@ static void fill_gradient(VectorState &State, const TClipRectangle &Boun else { // Masked gradient agg::alpha_mask_gray8 alpha_mask(State.mClipStack->top().m_renderer); agg::scanline_u8_am masked_scanline(alpha_mask); - agg::render_scanlines(Raster, masked_scanline, solidrender_gradient); } } diff --git a/src/vector/vector.fdl b/src/vector/vector.fdl index bad3aa3c5..71651bd9b 100644 --- a/src/vector/vector.fdl +++ b/src/vector/vector.fdl @@ -226,6 +226,7 @@ module({ name="Vector", copyright="Paul Manias © 2010-2024", version=1.0, times "SCALED_FX: FX is scaled", "SCALED_FY: FY is scaled", "SCALED_RADIUS: Radius is scaled", + "SCALED_FOCAL_RADIUS: Focal radius is scaled", "FIXED_X1: X1 is fixed", "FIXED_Y1: Y1 is fixed", "FIXED_X2: X2 is fixed", @@ -234,7 +235,8 @@ module({ name="Vector", copyright="Paul Manias © 2010-2024", version=1.0, times "FIXED_CY: CY is fixed", "FIXED_FX: FX is fixed", "FIXED_FY: FY is fixed", - "FIXED_RADIUS: is fixed") + "FIXED_RADIUS: Radius is fixed", + "FIXED_FOCAL_RADIUS: Focal radius is fixed") flags("VPF", { comment="Optional flags for the VectorScene object." }, "BITMAP_SIZED: Automatically adjust the @VectorScene.PageWidth and @VectorScene.PageHeight to match the target @Bitmap.Width and @Bitmap.Height.", @@ -444,9 +446,10 @@ module({ name="Vector", copyright="Paul Manias © 2010-2024", version=1.0, times double Y2 # Ending Y of the gradient 'line' double CenterX # Center X coordinate of radial gradient shapes. double CenterY # Center Y coordinate of radial gradient shapes. - double FX # Focal X coordinate for radial gradient shapes. - double FY # Focal Y coordinate for radial gradient shapes. - double Radius # The size of a radial gradient radius. + double FocalX # Focal X coordinate for radial gradient shapes. + double FocalY # Focal Y coordinate for radial gradient shapes. + double Radius # The radius size for radial gradients. + double FocalRadius # The size of the focal radius for radial gradients. obj(VectorGradient) Inherit # Reference to another gradient from which to inherit attributes. int(VSPREAD) SpreadMethod # Defines the spread method to use for gradient fills. int(VUNIT) Units # Defines the coordinate system for `(X1, Y1), (X2, Y2)` diff --git a/scripts/dev/flute.fluid b/tools/flute.fluid similarity index 100% rename from scripts/dev/flute.fluid rename to tools/flute.fluid diff --git a/scripts/dev/hash.fluid b/tools/hash.fluid similarity index 100% rename from scripts/dev/hash.fluid rename to tools/hash.fluid diff --git a/scripts/dev/idl/common-graphics.fdl b/tools/idl/common-graphics.fdl similarity index 100% rename from scripts/dev/idl/common-graphics.fdl rename to tools/idl/common-graphics.fdl diff --git a/scripts/dev/idl/common.fdl b/tools/idl/common.fdl similarity index 92% rename from scripts/dev/idl/common.fdl rename to tools/idl/common.fdl index 7191acadd..be09b0680 100644 --- a/scripts/dev/idl/common.fdl +++ b/tools/idl/common.fdl @@ -192,30 +192,36 @@ flags("JTYPE", { comment="JTYPE flags are used to categorise input types.", modu "REPEATED: Input is a repeated entry (i.e. user is holding down a button and a repetition timer is being triggered)", "DRAG_ITEM: This special flag is set by the input system if the pointer is click-dragging an object at the time of the event.") +flags("CON", { comment="Gamepad controller buttons.", module="core" }, + "GAMEPAD_S: South button (A)", + "GAMEPAD_E: East button (B)", + "GAMEPAD_W: West button (X)", + "GAMEPAD_N: North button (Y)", + "DPAD_UP: Directional pad up.", + "DPAD_DOWN: Directional pad down.", + "DPAD_LEFT: Directional pad left.", + "DPAD_RIGHT: Directional pad right.", + "START: Gamepad start button.", + "SELECT: Gamepad select or back button.", + "LEFT_BUMPER_1: Gamepad left-hand bumper 1 (top, primary).", + "LEFT_BUMPER_2: Gamepad left-hand bumper 2 (lower).", + "RIGHT_BUMPER_1: Gamepad right-hand bumper 1 (top, primary).", + "RIGHT_BUMPER_2: Gamepad right-hand bumper 2 (lower).", + "LEFT_THUMB: Left thumb stick depressed.", + "RIGHT_THUMB: Right thumb stick depressed." + ) + enum("JET", { type="int", start=1, comment="JET constants are documented in GetInputEvent()", module="Core" }, - "DIGITAL_XY: Digital movement from a relative location. Value is +/- n, where n is the number of units moved horizontally. Mouse movement will normally exceed a value of 1, whereas gamepad movement is limited to a value of +/- 1 except in the case of successive presses.", - "BUTTON_1|LMB: Left mouse button, XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed).", - "BUTTON_2|RMB: Right mouse button, XBox X button, PS cross button.", - "BUTTON_3|MMB: Middle mouse button, XBox Y button, PS triangle.", - "BUTTON_4: XBox B button, PS circle.", - "BUTTON_5: Left analog stick depressed.", - "BUTTON_6: Right analog stick depressed.", + "BUTTON_1|LMB: Left mouse button; XBox A button, PS square button. Value is pressure sensitive, ranging between 0 - 1.0 (0 is released, 1.0 is fully depressed).", + "BUTTON_2|RMB: Right mouse button; XBox X button, PS cross button.", + "BUTTON_3|MMB: Middle mouse button; XBox Y button, PS triangle.", + "BUTTON_4: Alt. mouse button 1; XBox B button, PS circle.", + "BUTTON_5: Alt. mouse button 2.", + "BUTTON_6: Non-specific button assignment.", "BUTTON_7: Non-specific button assignment.", "BUTTON_8: Non-specific button assignment.", "BUTTON_9: Non-specific button assignment.", "BUTTON_10: Non-specific button assignment.", - "TRIGGER_LEFT: Gamepad left-hand trigger - value is between 0 - 1.0 (0 is released, 1.0 is fully depressed).", - "TRIGGER_RIGHT: Gamepad right-hand trigger.", - "BUTTON_START: Gamepad start button - value is 0 or 1.", - "BUTTON_SELECT: Gamepad select button - value is 0 or 1.", - "LEFT_BUMPER_1: Gamepad left-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0.", - "LEFT_BUMPER_2: Gamepad left-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0.", - "RIGHT_BUMPER_1: Gamepad right-hand bumper 1 (top) - pressure sensitive value from 0 - 1.0.", - "RIGHT_BUMPER_2: Gamepad right-hand bumper 2 (lower) - pressure sensitive value from 0 - 1.0.", - "ANALOG_XY: Position for the default analog control (on gamepads this is the left analog control). Analog values range between -1.0 and 1.0. A value of zero indicates that the control is at rest.", - "ANALOG_Z: 3D or yoke position for the default analog control. A negative value indicates that the control has been pulled out and a positive value indicates that it has been pushed in.", - "ANALOG2_XY: As for `ANALOG_XY`, this type covers a second analog stick if present.", - "ANALOG2_Z: As for `ANALOG_Z`, this type covers a second analog stick if present.", "WHEEL: Mouse wheel rotation - the value generally reflects the number of 'clicks' rotated on the wheel.", "WHEEL_TILT: Some mouse wheels can be tilted to the left or right. Ranges from -1.0 to +1.0", "PEN_TILT_XY: For pen-based input, this type indicates the vertical tilt of the pen device. A value of 0 indicates that the pen is laid flat with nib at the bottom, 0.5 is 90 degrees, 1.0 is laid flat with nib at the top.", diff --git a/scripts/dev/idl/idl-c.fluid b/tools/idl/idl-c.fluid similarity index 99% rename from scripts/dev/idl/idl-c.fluid rename to tools/idl/idl-c.fluid index 860049cde..424bb74aa 100644 --- a/scripts/dev/idl/idl-c.fluid +++ b/tools/idl/idl-c.fluid @@ -1,7 +1,7 @@ -- This program produces C++ headers, auto-generated values and documentation from Parasol FDL files. -- --- Usage: parasol sdk:scripts/dev/idl/idl-c.fluid src=source.fdl --- Example: parasol sdk:scripts/dev/idl/idl-c.fluid src=sdk:core/modules/core/core.fdl +-- Usage: parasol sdk:tools/idl/idl-c.fluid src=source.fdl +-- Example: parasol sdk:tools/idl/idl-c.fluid src=sdk:core/modules/core/core.fdl include 'core' include 'xml' diff --git a/scripts/dev/idl/idl-compile.fluid b/tools/idl/idl-compile.fluid similarity index 100% rename from scripts/dev/idl/idl-compile.fluid rename to tools/idl/idl-compile.fluid diff --git a/scripts/dev/idl/idl-doc.fluid b/tools/idl/idl-doc.fluid similarity index 100% rename from scripts/dev/idl/idl-doc.fluid rename to tools/idl/idl-doc.fluid diff --git a/scripts/dev/idl/idl-types.fluid b/tools/idl/idl-types.fluid similarity index 100% rename from scripts/dev/idl/idl-types.fluid rename to tools/idl/idl-types.fluid diff --git a/scripts/dev/parka.fluid b/tools/parka.fluid similarity index 100% rename from scripts/dev/parka.fluid rename to tools/parka.fluid diff --git a/scripts/dev/rsakey.fluid b/tools/rsakey.fluid similarity index 100% rename from scripts/dev/rsakey.fluid rename to tools/rsakey.fluid