text:
// DOM-IGNORE-BEGIN

//DOM-IGNORE-END

/******************************************************************************
Change History:
  Rev         Description
  ----------  ----------------------------------------------------------
  2.6 - 2.6a  No change

  2.7         Changed the interface to _SetCurrentPosition to be able to
              take in the printer number as a parameter.
*******************************************************************************/
//DOM-IGNORE-END

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>

#include "usb.h"
#include "usb_host_printer.h"
#include "usb_host_printer_postscript.h"

//#define DEBUG_MODE
#ifdef DEBUG_MODE
    #include "uart2.h"
#endif

#ifdef USB_PRINTER_LANGUAGE_POSTSCRIPT

// *****************************************************************************
// *****************************************************************************
// Section: Configuration
// *****************************************************************************
// *****************************************************************************

#if !defined(USB_ENABLE_TRANSFER_EVENT)
    #error The USB Host Printer Client Driver requires transfer events.
#endif

// *****************************************************************************
// *****************************************************************************
// Section: Constants
// *****************************************************************************
// *****************************************************************************

#define ESCAPE                              "\033"

#define COMMAND_EJECT_PAGE                  "showpage "

#define COMMAND_GRAPHICS_COLOR_BLACK        "0 setgray "
#define COMMAND_GRAPHICS_COLOR_WHITE        "1 setgray "
#define COMMAND_GRAPHICS_LINE_TYPE_DASHED   "[3] 0 setdash "
#define COMMAND_GRAPHICS_LINE_TYPE_DOTTED   "[1 5] 0 setdash"
#define COMMAND_GRAPHICS_LINE_TYPE_SOLID    "[] 0 setdash "
#define COMMAND_GRAPHICS_LINE_WIDTH_NORMAL  "1 setlinewidth "
#define COMMAND_GRAPHICS_LINE_WIDTH_THICK   "3 setlinewidth "
#define COMMAND_GRAPHICS_LINE_END_BUTT      "0 setlinecap "
#define COMMAND_GRAPHICS_LINE_END_ROUND     "1 setlinecap "
#define COMMAND_GRAPHICS_LINE_END_SQUARE    "2 setlinecap "
#define COMMAND_GRAPHICS_LINE_JOIN_BEVEL    "2 setlinejoin "
#define COMMAND_GRAPHICS_LINE_JOIN_MITER    "0 setlinejoin "
#define COMMAND_GRAPHICS_LINE_JOIN_ROUND    "1 setlinejoin "
#define COMMAND_GRAPHICS_MOVE_TO            "%d %d moveto "
#define COMMAND_GRAPHICS_MOVE_RELATIVE      "%d %d rmoveto "
#define COMMAND_GRAPHICS_LINE_TO            "%d %d lineto "
#define COMMAND_GRAPHICS_LINE_TO_RELATIVE   "%d %d rlineto "
#define COMMAND_GRAPHICS_ARC                "%d %d %d %d %d arc "
#define COMMAND_GRAPHICS_ARC_TO             "%d %d %d %d %d arcto clear "
#define COMMAND_GRAPHICS_CIRCLE             "%d %d %d 0 360 arc "
#define COMMAND_GRAPHICS_CLOSEPATH          "closepath "

#define COMMAND_IMAGE_STOP                  ">} image grestore "
#define COMMAND_JOB_START                   ESCAPE "%-12345X"
#define COMMAND_LANDSCAPE                   "612 0 translate 90 rotate "
#define COMMAND_JOB_STOP                    "showpage " ESCAPE "%-12345X"
#define COMMAND_SET_POSITION                "%d %d moveto "
#define COMMAND_TEXT_START                  "("
#define COMMAND_TEXT_STOP                   ") show "
#define COMMAND_FILL                        "fill "
#define COMMAND_STROKE                      "stroke "

#define X_COORDINATE_IN_RANGE(x)            ((0 <= (x)) && ((x) <= printerListPostScript[printer].currentWidth))
#define Y_COORDINATE_IN_RANGE(y)            ((0 <= (y)) && ((y) <= printerListPostScript[printer].currentHeight))

// *****************************************************************************
// *****************************************************************************
// Section: Data Structures
// *****************************************************************************
// *****************************************************************************

//-----------------------------------------------------------------------------
/* Printer Status Structure

This structure holds the information about an attached printer.  One instance
of this structure is needed for each attached printer.
*/

typedef struct _PRINTER_STATUS_POSTSCRIPT
{
    USB_PRINTER_FUNCTION_SUPPORT    support;    // The functions supported by this printer.

    uint16_t    currentHeight;  // The current height of the page in points.
    uint16_t    currentWidth;   // The current width of the page in points.

    uint16_t    currentX;       // Current X-axis position.
    uint16_t    currentY;       // Current Y-axis position.

    uint8_t    deviceAddress;  // Address of the attached printer
    uint8_t    fontName;       // Currently selected font
    uint8_t    fontSize;       // Size of the current font

    union
    {
        uint8_t    value;

        struct
        {
            uint8_t    isLandscape     : 1;    // Landscape(1) or portrait(0)
            uint8_t    isBold          : 1;    // If the font is bold
            uint8_t    isItalic        : 1;    // If the font is italic
            uint8_t    penIsWhite      : 1;    // Current selected pen is white.
        };
    } printerFlags;

} PRINTER_STATUS_POSTSCRIPT;

// *****************************************************************************
// *****************************************************************************
// Section: Global Variables
// *****************************************************************************
// *****************************************************************************

const unsigned char         _psCharacterArray[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
const char                  _psFontNames[USB_PRINTER_FONT_MAX_FONT][4][30] = {
    { "AvantGarde-Book", "AvantGarde-Demi", "AvantGarde-Oblique", "AvantGarde-DemiOblique" },
    { "Bookman-Light", "Bookman-Demi", "Bookman-LightOblique", "Bookman-DemiOblique" },
    { "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique" },
    { "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique" },
    { "Helvetica-Narrow", "Helvetica-Narrow-Bold", "Helvetica-Narrow-Oblique", "Helvetica-Narrow-BoldOblique" },
    { "NewCenturySchlbk-Roman", "NewCenturySchlbk-Bold", "NewCenturySchlbk-Italic", "NewCenturySchlbk-BoldItalic" },
    { "Palatino-Roman", "Palatino-Bold", "Palatino-Italic", "Palatino-BoldItalic" },
    { "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic" } };

PRINTER_STATUS_POSTSCRIPT   printerListPostScript[USB_MAX_PRINTER_DEVICES];

// *****************************************************************************
// *****************************************************************************
// Section: Macros
// *****************************************************************************
// *****************************************************************************

#define PAGE_IS_LANDSCAPE(x)    ((x & 0x01) == 0x01)
#define PAGE_IS_PORTRAIT(x)     ((x & 0x01) == 0x00)
#define FONT_IS_BOLD(x)         ((x & 0x02) == 0x02)
#define FONT_IS_ITALIC(x)       ((x & 0x04) == 0x04)

#define _SetCurrentPosition(p,x,y)                      \
    {                                                   \
        printerListPostScript[(p)].currentX = (x);      \
        printerListPostScript[(p)].currentY = (y);      \
    }

#ifndef USB_MALLOC
    #define USB_MALLOC(size) malloc(size)
#endif

#ifndef USB_FREE
    #define USB_FREE(ptr) free(ptr)
#endif

#define USB_FREE_AND_CLEAR(ptr) {USB_FREE(ptr); ptr = NULL;}

// *****************************************************************************
// *****************************************************************************
// Section: Local Prototypes
// *****************************************************************************
// *****************************************************************************

static uint8_t _PrintFontCommand( uint8_t printer, uint8_t transferFlags );
static uint8_t _PrintStaticCommand( uint8_t address, char *command, uint8_t transferFlags );
static void _SetFontString( uint8_t font, uint8_t printerFlags, char *ptr );

// *****************************************************************************
// *****************************************************************************
// Section: Interface Functions
// *****************************************************************************
// *****************************************************************************

/****************************************************************************
  Function:
    uint8_t USBHostPrinterLanguagePostScript( uint8_t address,
        USB_PRINTER_COMMAND command, USB_DATA_POINTER data, uint32_t size, uint8_t transferFlags )

  Summary:
    This function executes printer commands for a PostScript printer.

  Description:
    This function executes printer commands for a PostScript printer.  When
    the application issues a printer command, the printer client driver
    determines what language to use to communicate with the printer, and
    transfers the command to that language support routine.  As much as
    possible, commands are designed to produce the same output regardless
    of what printer language is used.

    Not all printer commands support data from both RAM and ROM.  Unless
    otherwise noted, the data pointer is assumed to point to RAM, regardless of
    the value of transferFlags.  Refer to the specific command to see if ROM
    data is supported.

  Preconditions:
    None

  Parameters:
    uint8_t address                - Device's address on the bus
    USB_PRINTER_COMMAND command - Command to execute.  See the enumeration
                                    USB_PRINTER_COMMAND for the list of
                                    valid commands and their requirements.
    USB_DATA_POINTER data    - Pointer to the required data.  Note that
                                    the caller must set transferFlags
                                    appropriately to indicate if the pointer is
                                    a RAM pointer or a ROM pointer.
    uint32_t size                  - Size of the data.  For some commands, this
                                    parameter is used to hold the data itself.
    uint8_t transferFlags          - Flags that indicate details about the
                                    transfer operation.  Refer to these flags
                                    * USB_PRINTER_TRANSFER_COPY_DATA
                                    * USB_PRINTER_TRANSFER_STATIC_DATA
                                    * USB_PRINTER_TRANSFER_NOTIFY
                                    * USB_PRINTER_TRANSFER_FROM_ROM
                                    * USB_PRINTER_TRANSFER_FROM_RAM

  Return Values:
    USB_PRINTER_SUCCESS             - The command was executed successfully.
    USB_PRINTER_UNKNOWN_DEVICE      - A printer with the indicated address is not
                                        attached
    USB_PRINTER_TOO_MANY_DEVICES    - The printer status array does not have
                                        space for another printer.
    USB_PRINTER_OUT_OF_MEMORY       - Not enough available heap space to
                                        execute the command.
    other                           - See possible return codes from the
                                        function USBHostPrinterWrite().

  Remarks:
    When developing new commands, keep in mind that the function
    USBHostPrinterCommandReady() will be used before calling this function to
    see if there is space available in the output transfer queue.
    USBHostPrinterCommandReady() will routine true if a single space is
    available in the output queue.  Therefore, each command can generate only
    one output transfer.

    Multiple printer languages may be used in a single application.  The USB
    Embedded Host Printer Client Driver will call the routine required for the
    attached device.
  ***************************************************************************/

uint8_t USBHostPrinterLanguagePostScript( uint8_t address,
        USB_PRINTER_COMMAND command, USB_DATA_POINTER data, uint32_t size, uint8_t transferFlags )
{
    char    *buffer;
    uint8_t    printer = 0;

    if (command != USB_PRINTER_ATTACHED)
    {
        // Try to find the current printer.  If we can't find the printer in the list,
        // put it in the list at the first available location.
        for (printer=0; (printer<USB_MAX_PRINTER_DEVICES) && (printerListPostScript[printer].deviceAddress != address); printer++ );
        if (printer == USB_MAX_PRINTER_DEVICES)
        {
            return USB_PRINTER_UNKNOWN_DEVICE;
        }
    }

    switch( command )
    {
        //---------------------------------------------------------------------
        case USB_PRINTER_ATTACHED:
            for (printer=0; (printer<USB_MAX_PRINTER_DEVICES) && (printerListPostScript[printer].deviceAddress != 0); printer++ );
            if (printer != USB_MAX_PRINTER_DEVICES)
            {
                printerListPostScript[printer].deviceAddress = address;
                printerListPostScript[printer].support       = *((USB_PRINTER_FUNCTION_SUPPORT *)(data.pointerRAM));
                return USB_PRINTER_SUCCESS;
            }
            return USB_PRINTER_TOO_MANY_DEVICES;
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_DETACHED:
            for (printer=0; (printer<USB_MAX_PRINTER_DEVICES) && (printerListPostScript[printer].deviceAddress != address); printer++ );
            if (printer != USB_MAX_PRINTER_DEVICES)
            {
                printerListPostScript[printer].deviceAddress = 0;
            }
            return USB_PRINTER_SUCCESS;
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_JOB_START:
            // Initialize page information.
            printerListPostScript[printer].fontName                 = USB_PRINTER_FONT_HELVETICA;
            printerListPostScript[printer].fontSize                 = 12;
            printerListPostScript[printer].printerFlags.value       = 0;
            printerListPostScript[printer].currentHeight            = PRINTER_PAGE_PORTRAIT_HEIGHT;
            printerListPostScript[printer].currentWidth             = PRINTER_PAGE_PORTRAIT_WIDTH;
            _SetCurrentPosition( printer, 0, 0 );
            return _PrintStaticCommand( address, COMMAND_JOB_START, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_JOB_STOP:
            return _PrintStaticCommand( address, COMMAND_JOB_STOP, transferFlags | USB_PRINTER_TRANSFER_NOTIFY );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_ORIENTATION_PORTRAIT:
            // PostScript resets all settings at the beginning of a page.  Portrait
            // is the default orientation, so we don't have to do anything.  This
            // command should be the first command sent after USB_PRINTER_JOB_START
            // or USB_PRINTER_EJECT_PAGE.
            printerListPostScript[printer].printerFlags.isLandscape = 0;
            printerListPostScript[printer].currentHeight            = PRINTER_PAGE_PORTRAIT_HEIGHT;
            printerListPostScript[printer].currentWidth             = PRINTER_PAGE_PORTRAIT_WIDTH;
            return USB_PRINTER_SUCCESS;
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_ORIENTATION_LANDSCAPE:
            // PostScript resets all settings at the beginning of a page.  This
            // command should be the first command sent after USB_PRINTER_JOB_START
            // or USB_PRINTER_EJECT_PAGE.  It must be called only once, or the
            // paper will be rotated again.
            printerListPostScript[printer].printerFlags.isLandscape = 1;
            printerListPostScript[printer].currentHeight            = PRINTER_PAGE_LANDSCAPE_HEIGHT;
            printerListPostScript[printer].currentWidth             = PRINTER_PAGE_LANDSCAPE_WIDTH;
            return _PrintStaticCommand( address, COMMAND_LANDSCAPE, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_NAME:
            // Font name is passed in the size parameter.
            printerListPostScript[printer].fontName = (uint8_t)size;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_SIZE:
            // Font size is passed in the size parameter.
            printerListPostScript[printer].fontSize = (uint8_t)size;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_ITALIC:
            printerListPostScript[printer].printerFlags.isItalic = 1;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_UPRIGHT:
            printerListPostScript[printer].printerFlags.isItalic = 0;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_BOLD:
            printerListPostScript[printer].printerFlags.isBold = 1;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_FONT_MEDIUM:
            printerListPostScript[printer].printerFlags.isBold = 0;
            return _PrintFontCommand( printer, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_EJECT_PAGE:
            // When we eject a page, all of our settings are cleared.
            return _PrintStaticCommand( address, COMMAND_EJECT_PAGE, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_TEXT_START:
            return _PrintStaticCommand( address, COMMAND_TEXT_START, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_TEXT:
        case USB_PRINTER_TRANSPARENT:
            // If the user's data is in ROM, we have to copy it to RAM first,
            // so the USB Host routines can read it.
            if (transferFlags & USB_PRINTER_TRANSFER_FROM_ROM)
            {
                USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            }
            if (transferFlags & USB_PRINTER_TRANSFER_COPY_DATA)
            {
                buffer = (char *)USB_MALLOC( size );
                if (buffer == NULL)
                {
                    return USB_PRINTER_OUT_OF_MEMORY;
                }

                if (transferFlags & USB_PRINTER_TRANSFER_FROM_ROM)
                {
                    #if defined( __C30__ ) || defined __XC16__
                        char __prog__   *ptr;
                    #elif defined( __PIC32MX__ )
                        const char      *ptr;
                    #endif
                    uint32_t   i;

                    ptr = ((USB_DATA_POINTER)data).pointerROM;
                    for (i=0; i<size; i++)
                    {
                        buffer[i] = *ptr++;
                    }
                }
                else
                {
                    char    *ptr;
                    uint32_t   i;

                    ptr = ((USB_DATA_POINTER)data).pointerRAM;
                    for (i=0; i<size; i++)
                    {
                        buffer[i] = *ptr++;
                    }
                }
            }
            else
            {
                buffer = ((USB_DATA_POINTER)data).pointerRAM;
            }

            return USBHostPrinterWrite( address, buffer, size, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_TEXT_STOP:
            return _PrintStaticCommand( address, COMMAND_TEXT_STOP, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_MOVE_TO:
            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE((uint16_t)(size >> 16)) || !Y_COORDINATE_IN_RANGE((uint16_t)size ))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif
        case USB_PRINTER_SET_POSITION:
            // This command sets the cursor to the specified position.  Note
            // that we must convert the specification to use PostScript's
            // orientation of the Y-axis.
            buffer = (char *)USB_MALLOC( 16 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            sprintf( buffer, COMMAND_SET_POSITION, (uint16_t)(size >> 16), printerListPostScript[printer].currentHeight - (uint16_t)size );
            _SetCurrentPosition( printer, (uint16_t)(size >> 16), (uint16_t)size );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_IMAGE_START:
            buffer = (char *)USB_MALLOC( 146 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            {
                USB_PRINTER_IMAGE_INFO  *info;

                info = (USB_PRINTER_IMAGE_INFO *)(data.pointerRAM);

                sprintf( buffer, "gsave %d %d %d %7.2f mul sub translate %d %7.2f mul %d %7.2f mul scale %d %d 1 [%d 0 0 -%d 0 %d] {<",
                    info->positionX, printerListPostScript[printer].currentHeight - info->positionY, info->height, (double)info->scale,
                    info->width, (double)info->scale, info->height, (double)info->scale,
                    info->width, info->height,
                    info->width, info->height, info->height );
                #ifdef DEBUG_MODE
                    UART2PrintString( buffer );
                    UART2PrintString( "\r\n" );
                #endif
            }
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_IMAGE_DATA_HEADER:
            return USB_PRINTER_SUCCESS;
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_IMAGE_DATA:
            // We have to translate the data here from binary to an ASCII representation
            // of the binary.  For each four bits, we need one uint8_t for the ASCII, plus one
            // for a NULL at the end.  We cannot do this in terms of uint8_ts - PostScript will
            // ignore extra bits at the end of a single character only, not at the end of
            // a uint8_t.

            // Determine the number of data nibbles.  We might have a size that is
            // not an even multiple of 4 bits.  To account for this, add 3 to the
            // size, and then divide by 4.
            size += 3;
            size /= 4;

            buffer = (char *)USB_MALLOC( size + 1 ); // Add one for possible truncation error.
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }
            else
            {
                uint16_t    i;
                uint8_t    printVar;
                char    *tempNew;

                // If the data is being read from ROM, then we have to
                // use a different pointer type to get the data.
                if (transferFlags & USB_PRINTER_TRANSFER_FROM_ROM)
                {
                    #if defined( __C30__ ) || defined __XC16__
                        uint8_t __prog__   *tempOld;
                    #elif defined( __PIC32MX__ )
                        const uint8_t      *tempOld;
                    #endif

                    tempNew = (char *)buffer;
                    tempOld = ((USB_DATA_POINTER)data).pointerROM;

                    // PostScript will ignore extra bits at the end of a nibble, but
                    // not at the end of a uint8_t.  Therefore, we have to print one
                    // nibble at a time.
                    for (i=0; i<size; i++)
                    {
                        if (!(i & 0x01))
                        {
                            // Most significant nibble.  Don't advance the uint8_t pointer.
                            printVar = (*tempOld>>4) & 0x0F;
                        }
                        else
                        {
                            // Least significant nibble.  Advance the uint8_t pointer.
                            printVar = *tempOld++ & 0x0F;
                        }
                        *tempNew++ = _psCharacterArray[printVar];
                    }
                }
                else
                {
                    uint8_t    *tempOld;

                    tempNew = (char *)buffer;
                    tempOld = ((USB_DATA_POINTER)data).pointerRAM;

                    // PostScript will ignore extra bits at the end of a nibble, but
                    // not at the end of a uint8_t.  Therefore, we have to print one
                    // nibble at a time.
                    for (i=0; i<size; i++)
                    {
                        if (!(i & 0x01))
                        {
                            // Most significant nibble.  Don't advance the uint8_t pointer.
                            printVar = (*tempOld>>4) & 0x0F;
                        }
                        else
                        {
                            // Least significant nibble.  Advance the uint8_t pointer.
                            printVar = *tempOld++ & 0x0F;
                        }
                        *tempNew++ = _psCharacterArray[printVar];
                    }
                }

                USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
                return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, size, transferFlags );
            }
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_IMAGE_STOP:
            return _PrintStaticCommand( address, COMMAND_IMAGE_STOP, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_TYPE:
            if (size == PRINTER_LINE_TYPE_SOLID)
            {
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_TYPE_SOLID, transferFlags );
            }
            else if (size == PRINTER_LINE_TYPE_DASHED)
            {
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_TYPE_DASHED, transferFlags );
            }
            else // PRINTER_LINE_TYPE_DOTTED
            {
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_TYPE_DOTTED, transferFlags );
            }
            break;

            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_WIDTH:
            if (size == PRINTER_LINE_WIDTH_NORMAL)
            {
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_WIDTH_NORMAL, transferFlags );
            }
            else //PRINTER_LINE_WIDTH_THICK
            {
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_WIDTH_THICK, transferFlags );
            }
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_END:
            if (size == PRINTER_LINE_END_BUTT)
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_END_BUTT, transferFlags );
            else if (size == PRINTER_LINE_END_ROUND)
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_END_ROUND, transferFlags );
            else //PRINTER_LINE_END_SQUARE
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_END_SQUARE, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_JOIN:
            if (size == PRINTER_LINE_JOIN_BEVEL)
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_JOIN_BEVEL, transferFlags );
            if (size == PRINTER_LINE_JOIN_MITER)
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_JOIN_MITER, transferFlags );
            else // PRINTER_LINE_JOIN_ROUND
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_LINE_JOIN_ROUND, transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_FILL_TYPE:
            // This command is not supported yet.  It's a bit complicated.
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_COLOR:
            if (size == PRINTER_COLOR_BLACK)
            {
                printerListPostScript[printer].printerFlags.penIsWhite = 0;
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_COLOR_BLACK, transferFlags );
            }
            else //PRINTER_COLOR_WHITE
            {
                printerListPostScript[printer].printerFlags.penIsWhite = 1;
                return _PrintStaticCommand( address, COMMAND_GRAPHICS_COLOR_WHITE, transferFlags );
            }
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_MOVE_RELATIVE:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.
            {
                int x;
                int y;

                x = printerListPostScript[printer].currentX + (int)(size >> 16);
                y = printerListPostScript[printer].currentY + (int)(size & 0xFFFF);

                #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                    if (!X_COORDINATE_IN_RANGE( x ) || !Y_COORDINATE_IN_RANGE( y ))
                    {
                        return USB_PRINTER_BAD_PARAMETER;
                    }
                #endif

                buffer = (char *)USB_MALLOC( 16 );
                if (buffer == NULL)
                {
                    return USB_PRINTER_OUT_OF_MEMORY;
                }

                sprintf( buffer, COMMAND_GRAPHICS_MOVE_TO, x, printerListPostScript[printer].currentHeight - y ) ;
                _SetCurrentPosition( printer,  x, y );
                USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
                return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            }
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.x1) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.y1) ||
                    !X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.x2) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.y2))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 73 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            sprintf( buffer, COMMAND_SET_POSITION COMMAND_GRAPHICS_LINE_TO COMMAND_STROKE,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.x1, printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.y1),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.x2, printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.y2) );
            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.x2, ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sLine.y2 );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_TO:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE( (int)(size >> 16) ) || !Y_COORDINATE_IN_RANGE( (int)(size & 0xFFFF) ))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 46 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            sprintf( buffer, COMMAND_GRAPHICS_MOVE_TO COMMAND_GRAPHICS_LINE_TO COMMAND_STROKE,
                printerListPostScript[printer].currentX, printerListPostScript[printer].currentHeight - printerListPostScript[printer].currentY,
                (int)(size >> 16), printerListPostScript[printer].currentHeight - (int)(size & 0xFFFF) );
            _SetCurrentPosition( printer,  (int)(size >> 16), (int)(size & 0xFFFF) );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_LINE_TO_RELATIVE:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE( printerListPostScript[printer].currentX + (int)(size >> 16) ) || !Y_COORDINATE_IN_RANGE( printerListPostScript[printer].currentY + (int)(size & 0xFFFF) ))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 46 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            sprintf( buffer, COMMAND_GRAPHICS_MOVE_TO COMMAND_GRAPHICS_LINE_TO_RELATIVE COMMAND_STROKE,
                printerListPostScript[printer].currentX, printerListPostScript[printer].currentHeight - printerListPostScript[printer].currentY,
                (int)(size >> 16), (int)(size & 0xFFFF) * -1 ) ;
            _SetCurrentPosition( printer,  printerListPostScript[printer].currentX + (int)(size >> 16), printerListPostScript[printer].currentY + (int)(size & 0xFFFF) );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_ARC:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.  Also, the coordinate parameters do
            // not match the command parameters (x,y).
            // x y ro a1 a2 arc fill 1 setgray x y ri a1 a2 arc fill 0 setgray

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.xL) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.yT) ||
                    !X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.xR) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.yB))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 15 + (56 + 11)* 2 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            {
                int     a1;
                int     a2;
                int     x;
                int     y;
                uint8_t    mask;
                uint8_t    maskPrevious;

                // Find the angles that define the arc.

                if (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.octant == 0)
                {
                    a1 = 0;
                    a2 = 0;
                }
                else if (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.octant == 0xFF)
                {
                    a1 = 0;
                    a2 = 360;
                }
                else
                {
                    // Look for the first edge of the arc.
                    a1 = 0;
                    mask = 0x02;
                    maskPrevious = 0x04;
                    while (!((mask & ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.octant) && !(maskPrevious & ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.octant)))
                    {
                        a1 += 45;
                        maskPrevious = mask;
                        mask >>= 1;
                        if (mask == 0)
                        {
                            mask = 0x80;
                        }
                    }

                    // Look for the second edge of the arc
                    a2 = a1;
                    while (mask & ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.octant)
                    {
                        a2 += 45;
                        mask >>= 1;
                        if (mask == 0)
                        {
                            mask = 0x80;
                        }
                    }
                }

                // Draw the outer circle of the arc.

                x = (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.xR + ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.xL) / 2;
                y = (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.yT + ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.yB) / 2;

                sprintf( buffer, COMMAND_GRAPHICS_MOVE_TO COMMAND_GRAPHICS_ARC COMMAND_FILL,
                    x, printerListPostScript[printer].currentHeight - y,
                    x, printerListPostScript[printer].currentHeight - y,
                    ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.r2, a1, a2 );

                if (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.r1 != 0)
                {
                    // Change pens

                    if (printerListPostScript[printer].printerFlags.penIsWhite)
                    {
                        strcat( buffer, COMMAND_GRAPHICS_COLOR_BLACK );
                    }
                    else
                    {
                        strcat( buffer, COMMAND_GRAPHICS_COLOR_WHITE );
                    }

                    // Draw the inner circle to erase the interior.

                    sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_ARC COMMAND_FILL,
                        x, printerListPostScript[printer].currentHeight - y,
                        ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.r1, a1, a2 );

                    // Put the original pen back.

                    if (printerListPostScript[printer].printerFlags.penIsWhite)
                    {
                        strcat( buffer, COMMAND_GRAPHICS_COLOR_WHITE );
                    }
                    else
                    {
                        strcat( buffer, COMMAND_GRAPHICS_COLOR_BLACK );
                    }
                }
            }
            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.xL, ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sArc.yT );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_CIRCLE:
        case USB_PRINTER_GRAPHICS_CIRCLE_FILLED:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.x + ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.r) ||
                    !X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.x - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.r) ||
                    !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.y + ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.r) ||
                    !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.y - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.r))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 50 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            sprintf( buffer, COMMAND_GRAPHICS_CIRCLE,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.x,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.y),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.r );

            if (command == USB_PRINTER_GRAPHICS_CIRCLE)
            {
                strcat( buffer, COMMAND_STROKE );
            }
            else // USB_PRINTER_GRAPHICS_CIRCLE_FILLED
            {
                strcat( buffer, COMMAND_FILL );
            }

            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.x, ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sCircle.y );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_BEVEL:
        case USB_PRINTER_GRAPHICS_BEVEL_FILLED:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.
            // xL yB-r moveto xL yT xR yT r arcto clear xR yT xR yB r arcto clear xR yB xL yT r arcto clear xL yB xL yT r arcto clear stroke

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yT) ||
                    !X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xR) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 155 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            // xL yB+r moveto
            sprintf( buffer, COMMAND_SET_POSITION,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.r ));

            // xL yT xR yT r arcto clear
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_ARC_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yT),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xR,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yT),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.r );

            // xR yT xR yB r arcto clear
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_ARC_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xR,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yT),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xR,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.r );

            // xR yB xL yB r arcto clear
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_ARC_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xR,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.r );

            // xL yB xL yT r arcto clear
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_ARC_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL,
                printerListPostScript[printer].currentHeight - (((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yT),
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.r );

            if (command == USB_PRINTER_GRAPHICS_BEVEL)
            {
                strcat( buffer, COMMAND_STROKE );
            }
            else // USB_PRINTER_GRAPHICS_BEVEL_FILLED
            {
                strcat( buffer, COMMAND_FILL );
            }

            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.xL, ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sBevel.yB );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_RECTANGLE:
        case USB_PRINTER_GRAPHICS_RECTANGLE_FILLED:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.
            // xL yB moveto xL yT lineto xR yT lineto xR yB lineto closepath stroke

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
                if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xL) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yT) ||
                    !X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xR) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yB))
                {
                    return USB_PRINTER_BAD_PARAMETER;
                }
            #endif

            buffer = (char *)USB_MALLOC( 80 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            // xL yB moveto
            sprintf( buffer, COMMAND_SET_POSITION,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xL,
                printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yB );

            // xL yT lineto
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_LINE_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xL,
                printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yT );

            // xR yT lineto
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_LINE_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xR,
                printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yT );

            // xR yB lineto
            sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_LINE_TO,
                ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xR,
                printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yB );

            strcat( buffer, COMMAND_GRAPHICS_CLOSEPATH );
            if (command == USB_PRINTER_GRAPHICS_RECTANGLE)
            {
                strcat( buffer, COMMAND_STROKE );
            }
            else // USB_PRINTER_GRAPHICS_RECTANGLE_FILLED
            {
                strcat( buffer, COMMAND_FILL );
            }

            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.xL, ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sRectangle.yB );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        case USB_PRINTER_GRAPHICS_POLYGON:
            // Note that we must convert the specification to use PostScript's
            // orientation of the Y-axis.

            #ifdef PRINTER_GRAPHICS_COORDINATE_CHECKING
            {
                uint16_t    i;

                for (i = 0; i < ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.numPoints * 2; i+=2)
                {
                    if (!X_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i]) || !Y_COORDINATE_IN_RANGE(((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i+1]))
                    {
                        return USB_PRINTER_BAD_PARAMETER;
                    }
                }
            }
            #endif

            buffer = (char *)USB_MALLOC( 15 + ( 15 * ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.numPoints) + 18 );
            if (buffer == NULL)
            {
                return USB_PRINTER_OUT_OF_MEMORY;
            }

            {
                uint16_t    i = 0;

                // x0 y0 moveto
                sprintf( buffer, COMMAND_SET_POSITION,
                    ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i],
                    printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i+1] );
                i += 2;

                // xn yn lineto
                while (i < ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.numPoints * 2)
                {
                    sprintf( &(buffer[strlen(buffer)]), COMMAND_GRAPHICS_LINE_TO,
                        ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i],
                        printerListPostScript[printer].currentHeight - ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[i+1] );
                    i += 2;
                }

                strcat( buffer, COMMAND_GRAPHICS_CLOSEPATH COMMAND_STROKE );
            }

            _SetCurrentPosition( printer,  ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[0], ((USB_PRINTER_GRAPHICS_PARAMETERS *)(data.pointerRAM))->sPolygon.points[1] );
            USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );
            return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
            break;

        //---------------------------------------------------------------------
        default:
            return USB_PRINTER_UNKNOWN_COMMAND;
            break;
    }
    return USB_PRINTER_UNKNOWN_COMMAND;
}

/****************************************************************************
  Function:
    bool USBHostPrinterLanguagePostScriptIsSupported( char *deviceID,
                USB_PRINTER_FUNCTION_SUPPORT *support )

  Description:
    This function determines if the printer with the given device ID string
    supports the PostScript printer language.

  Preconditions:
    None

  Parameters:
    char *deviceID  - Pointer to the "COMMAND SET:" portion of the device ID
                        string of the attached printer.
    USB_PRINTER_FUNCTION_SUPPORT *support   - Pointer to returned information
                        about what types of functions this printer supports.

  Return Values:
    true    - The printer supports PostScript.
    false   - The printer does not support PostScript.

  Remarks:
    The caller must first locate the "COMMAND SET:" section of the device ID
    string.  To ensure that only the "COMMAND SET:" section of the device ID
    string is checked, the ";" at the end of the section should be temporarily
    replaced with a NULL.  Otherwise, this function may find the printer
    language string in the comments or other section, and incorrectly indicate
    that the printer supports the language.

    Device ID strings are case sensitive.
  ***************************************************************************/

bool USBHostPrinterLanguagePostScriptIsSupported( char *deviceID,
                USB_PRINTER_FUNCTION_SUPPORT *support )
{
    if (strstr( deviceID, LANGUAGE_ID_STRING_POSTSCRIPT ))
    {
        support->val = LANGUAGE_SUPPORT_FLAGS_POSTSCRIPT;
        return true;
    }
    return false;
}

// *****************************************************************************
// *****************************************************************************
// Section: Local Functions
// *****************************************************************************
// *****************************************************************************

/****************************************************************************
  Function:
    static uint8_t _PrintFontCommand( uint8_t printer, uint8_t transferFlags )

  Description:
    This function generates the command needed to select the desired font
    and sends it to the printer.  The font specification includes typeface,
    size, and bold and italic indications.

  Preconditions:
    None

  Parameters:
    uint8_t printer        - Index of the desired printer in the printer support array.
    uint8_t transferFlags  - Transfer control flags.

  Return Values:
    USB_PRINTER_SUCCESS         - Command completed successfully.
    USB_PRINTER_OUT_OF_MEMORY   - Not enough dynamic memory to perform the
                                    command.
    others                      - See the return values for the function
                                    USBHostPrinterWrite().

  Remarks:
    None
  ***************************************************************************/

static uint8_t _PrintFontCommand( uint8_t printer, uint8_t transferFlags )
{
    char    *buffer;
//    char    temp[6];

    buffer = (char *)USB_MALLOC( 1 + 30 + 10 + 5 + 20 );
    if (buffer == NULL)
    {
        return USB_PRINTER_OUT_OF_MEMORY;
    }

    buffer[0] = '/';
    _SetFontString( printerListPostScript[printer].fontName, printerListPostScript[printer].printerFlags.value, &(buffer[1]) );
    sprintf( &(buffer[strlen(buffer)]), " findfont %d scalefont setfont ", printerListPostScript[printer].fontSize );
//    strcat( buffer, " findfont " );
//    sprintf( temp, "%d", printerListPostScript[printer].fontSize );
//    strcat( buffer, temp );
//    strcat( buffer, " scalefont setfont " );

    USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );

    return USBHostPrinterWrite( printerListPostScript[printer].deviceAddress, buffer, strlen(buffer), transferFlags );
}

/****************************************************************************
  Function:
    static uint8_t _PrintStaticCommand( uint8_t address, char *command, uint8_t transferFlags )

  Description:
    This function sends a hard-coded command to the printer.  Many printer
    commands are constant text strings that require no parameters.  This
    routine allocates dynamic memory for a copy of the command, copies the
    command into the string, and sends the command to the printer.

  Preconditions:
    None

  Parameters:
    uint8_t address        - Address of the attached printer.
    char *command       - Printer command string.
    uint8_t transferFlags  - Transfer control string.

  Return Values:
    USB_PRINTER_SUCCESS         - Command completed successfully.
    USB_PRINTER_OUT_OF_MEMORY   - Not enough dynamic memory to perform the
                                    command.
    others                      - See the return values for the function
                                    USBHostPrinterWrite().

  Remarks:
    None
  ***************************************************************************/

static uint8_t _PrintStaticCommand( uint8_t address, char *command, uint8_t transferFlags )
{
    char    *buffer;

    USBHOSTPRINTER_SETFLAG_COPY_DATA( transferFlags );

    buffer = (char *)USB_MALLOC( strlen(command) + 1 );
    if (buffer == NULL)
    {
        return USB_PRINTER_OUT_OF_MEMORY;
    }
    strcpy( buffer, command );
    return USBHostPrinterWrite( address, buffer, strlen(buffer), transferFlags );
}

/****************************************************************************
  Function:
    static void _SetFontString( uint8_t font, uint8_t printerFlags, char *ptr )

  Description:
    This function puts the string that designates the selected font into
    the indicated character buffer.

  Preconditions:
    None

  Parameters:
    uint8_t font           - Font indication.  See the enumeration
                            USB_PRINTER_FONTS for the list of valid values.
    uint8_t printerFlags   - Flags that indicate the bold and italic condition
                            of the font.  These must match the structure of
                            printerFlags in the PRINTER_STATUS_POSTSCRIPT
                            structure
    char *ptr           -   Buffer to store the font string.

  Returns:
    None

  Remarks:
    None
  ***************************************************************************/

static void _SetFontString( uint8_t font, uint8_t printerFlags, char *ptr )
{
    uint8_t    i;

    if (font > USB_PRINTER_FONT_MAX_FONT)
    {
        font = USB_PRINTER_FONT_COURIER;
    }

    i = 0;
    if (FONT_IS_BOLD( printerFlags ))   i |= 0x01;
    if (FONT_IS_ITALIC( printerFlags))  i |= 0x02;

    strcpy( ptr, &(_psFontNames[font][i][0]) );
}

#endif


text:
@implementation DefaultHttpExecutor

-(id)init
{
    if (self = [super init])
    {
		method=GET;
    }

    return self;

}

-(void)setUrl:(NSURL*)_url
{
    url=_url;
}

-(void)setMethod:(RequestMethod) _method
{
    method=_method;
}

-(NSString*)execute:(ParsedApiData*)data withError:(NSError*)error
{

    NSMutableURLRequest * req = [NSMutableURLRequest requestWithURL:url];

    [req setHTTPMethod:REQUEST_METHOD_VALUE(method)];

    NSMutableData* body = [NSMutableData data];

    NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    int len = 64;
    //Creates a random boundary
    NSMutableString *boundary = [NSMutableString stringWithCapacity: len];

    for (int i=0; i<len; i++) {
        [boundary appendFormat: @"%C", [letters characterAtIndex: arc4random() % [letters length]]];
    }

    [req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];

    NSData *boundaryData = [[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding];
    [body appendData:boundaryData];

    int i = 0;

    NSArray* keys=[data.fields allKeys];
    NSString *key;

    for (i=0;i<[keys count];i++)

    {
        key=[keys objectAtIndex:i];

        // Property upload
        [body appendData: [[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", key,[data.fields objectForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]];

        if (i!=[keys count]-1 || [data.files count]!=0)
        {
            [body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        }
    }

    keys=[data.files allKeys];

    for (i=0;i<[keys count];i++)
    {
        key=[keys objectAtIndex:i];

        // File upload
        [body appendData: [[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n\r\n", key,key] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData: [data.files objectForKey:key]];

        if (i != [keys count]-1)
        {
            [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        }else
        {
            [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
        }

    }

    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    [req setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[body length]] forHTTPHeaderField:@"Content-Length"];

    if([data.files count]!=0 || [data.fields count]!=0)
    {
        [req setHTTPBody:body];
    }

    NSData *returnData = [NSURLConnection sendSynchronousRequest:req returningResponse:nil error: &error];

    NSString* returnString=nil;

    if(error!=nil)
    {
    	TRANSLOADIT_LOG_ERROR(self.class, error);
    }else
    {
        returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

        TRANSLOADIT_LOG_INFO(self.class,@"%@",returnString);
    }

    return returnString;

}

@end

redpajama_set_name: RedPajamaGithub


text:
package componente;

import model.Usuario;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.SessionScoped;

@Component
@SessionScoped
public class UsuarioWeb {

	private Usuario usuario;

	public UsuarioWeb() {
		// TODO Auto-generated constructor stub
	}

	public void login(Usuario usuario){
		this.usuario = usuario;
	}

	public void logout(){
		this.usuario = null;
	}

	public boolean logado(){
		if (this.usuario == null){
			return false;
		}else {
			return true;
		}
	}

	public Usuario getUsuario() {
		return usuario;
	}

	public void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

}


text:
require 'shipitron'

module Shipitron
  class PostBuild < Hashie::Dash
    property :ecs_task
    property :container_name
    property :command

    # String is of the format:
    # 'ecs_task:task,container_name:name,command:command
    def self.parse(str)
      PostBuild.new.tap do |post_build|
        str.split(',').each do |part|
          part.match(/([^:]+):(.+)/) do |m|
            prop = m[1].to_sym
            if property?(prop)
              post_build[prop] = m[2]
            end
          end
        end

        properties.each do |prop|
          raise "post build argument missing '#{prop}'" if post_build[prop].nil?
        end
      end
    end

    def to_s
      "ecs_task:#{ecs_task},container_name:#{container_name},command:#{command}"
    end

    def command_ary
      command.split(' ')
    end
  end
end


text:
layout: post
title: Recommendation System
excerpt: "Implement recommendation system by python."
modified:
categories: articles
tags: [Python]
comments: true
share: true
---

In this small article, I want to keep a record for my study experience in recommendation system. There are several parameters can evaluate a recommendation system, which are **precision**, **recall** and **F-measure**. Collaborative filtering (CF) is the most successful recommendation technique to date. There are three main categories of CF techniques: memory-based, model-based and hybrid CF algorithms (that combine CF with other recommendation techniques).

Overview of collaborative filtering techniques.

Today, I will mainly focus on Item-based and User-based CF techniques. The basic idea of item-based CF algorithms is to calculate the similarity between different items based on the user-item rating data and then to compute the prediction score for a given item based on the calculated similarity score, while the core of user-based CF algorithms is to provide item recommendation or prediction based on the common opinion of other like-minded users.

### Evaluation indicators for a recommendation system

| Notation | Meaning |
|:--------|:-------:|
| P  | is the fraction of retrieved instances that are relevant. |
| R   | is the fraction of relevant instances that are retrieved.  |
| F   | F = (2PR/(P+R)). in fact, F-measure is a measure of test's accuracy by coordinate Precision with Recall.  |
{: .table}

### Datasets

Here I want to evaluate running time of two algorithms using [MovieLens](http://grouplens.org/datasets/movielens/) datasets.

[u1.base](https://dn-shanguangyu.qbox.me/u1.base)
「Total 943 person, Total 1650 movies」

[u1.test](https://dn-shanguangyu.qbox.me/u1.test)
「Total 459 person, Total 1410 movies」

### User-based CF & Item-based CF

{% highlight python %}
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# Author: <work#shanguangyu.com>

from __future__ import division
from math import sqrt
import time

class UserBasedCF:

    def __init__(self, train_file, test_file):
        self.train_file = train_file
        self.test_file = test_file
        self.readData()
        self.userSimilarity()

    def readData(self):
        self.train, self.test = {}, {}
        for line in open(self.train_file):
            user, item, score, _ = line.strip().split("\t")
            self.train.setdefault(user, {})
            self.train[user][item] = int(score)
        for line in open(self.test_file):
            user, item, score, _ = line.strip().split("\t")
            self.test.setdefault(user, {})
            self.test[user][item] = int(score)

    def userSimilarity(self):
        # Build invese table for item_users
        self.item_users = {}
        for u, items in self.train.iteritems():
            for i in items.keys():
                if i not in self.item_users:
                    self.item_users[i] = set()
                self.item_users[i].add(u)

        C, N = {}, {}
        for i, users in self.item_users.iteritems():
            for u in users:
                N.setdefault(u, 0)
                N[u] += 1
                C.setdefault(u, {})
                for v in users:
                    if u == v:
                        continue
                    C[u].setdefault(v, 0)
                    C[u][v] += 1

        self.W = {}
        # Calculate finial similarity matrix W
        for u, related_users in C.iteritems():
            self.W.setdefault(u, {})
            for v, cuv in related_users.iteritems():
                self.W[u][v] = cuv / sqrt(N[u] * N[v])

    def recommend(self, user, K=3, N=10):
        rank = {}
        interacted_items = self.train[user]
        for v, wuv in sorted(self.W[user].items(),
                             key=lambda x: x[1], reverse=True)[0:K]:
            for i, rvi in self.train[v].items():
                if i in interacted_items:
                    # filter items user interacted before
                    continue
                rank.setdefault(i, 0)
                rank[i] += wuv * rvi

        return dict(sorted(rank.items(),
                           key=lambda x: x[1], reverse=True)[0:N])

    def evaluate(self, train=None, test=None, K=3, N=10):
        train = self.train
        test = self.test
        hit, recall, precision = 0, 0, 0
        for user in train.keys():
            tu = test.get(user, {})
            rank = self.recommend(user, K=K, N=N)
            for i, _ in rank.items():
                if i in tu:
                    hit += 1
            recall += len(tu)
            precision += N
        recall = hit / recall
        precision = hit / precision
        f = 2 * recall * precision / (precision + recall)
        return (recall, precision, f)

class ItemBasedCF:

    def __init__(self, train_file, test_file):
        self.train_file = train_file
        self.test_file = test_file
        self.readData()
        self.itemSimilarity()

    def readData(self):
        self.train, self.test = {}, {}
        for line in open(self.train_file):
            user, item, score, _ = line.strip().split("\t")
            self.train.setdefault(user, {})
            self.train[user][item] = int(score)
        for line in open(self.test_file):
            user, item, score, _ = line.strip().split("\t")
            self.test.setdefault(user, {})
            self.test[user][item] = int(score)

    def itemSimilarity(self):
        C = dict()
        N = dict()
        for user, items in self.train.items():
            for i in items.keys():
                N.setdefault(i, 0)
                N[i] += 1
                C.setdefault(i, {})
                for j in items.keys():
                    if i == j:
                        continue
                    C[i].setdefault(j, 0)
                    C[i][j] += 1
        self.W = {}
        for i, related_items in C.items():
            self.W.setdefault(i, {})
            for j, cij in related_items.items():
                self.W[i][j] = cij / (sqrt(N[i] * N[j]))
        return self.W

    def recommend(self, user, K=3, N=10):
        rank = dict()
        interacted_items = self.train[user]
        for item, score in interacted_items.iteritems():
            for j, wj in sorted(self.W[item].iteritems(),
                                key=lambda x: x[1], reverse=True)[0:K]:
                if j in interacted_items.keys():
                    continue
                rank.setdefault(j, 0)
                rank[j] += score * wj
        return dict(sorted(rank.items(),
                           key=lambda x: x[1], reverse=True)[0:N])

    def evaluate(self, train=None, test=None, K=3, N=10):
        train = self.train
        test = self.test
        hit, recall, precision = 0, 0, 0
        for user in train.keys():
            tu = test.get(user, {})
            rank = self.recommend(user, K=K, N=N)
            for i, _ in rank.items():
                if i in tu:
                    hit += 1
            recall += len(tu)
            precision += N
        recall = hit / recall
        precision = hit / precision
        f = 2 * recall * precision / (precision + recall)
        return (recall, precision, f)

if __name__ == '__main__':
    start_time = time.time()

    # choose which method to use
    # model = UserBasedCF('u1.base', 'u1.test')
    model = ItemBasedCF('u1.base', 'u1.test')

    # The performance of model under various K
    klst = [5, 10, 15, 20, 25]
    print("recall", "precision", "f1")
    for k in klst:
        print model.evaluate(train='u1.base', test='u1.test', K=k)
    print("--- %s seconds ---" % (time.time() - start_time))

{% endhighlight %}

### Results
{% highlight text %}
User-based CF:
('recall', 'precision', 'f1')
(0.09855, 0.20901378579003183, 0.13394495412844035)
(0.1054, 0.22354188759278898, 0.14325518178729188)
(0.10725, 0.22746553552492046, 0.14576962283384304)
(0.10875, 0.23064687168610817, 0.14780835881753313)
(0.1087, 0.2305408271474019, 0.14774040095141014)
--- 13.2764439583 seconds ---

Item-based CF:
('recall', 'precision', 'f1')
(0.0974, 0.20657476139978792, 0.13238192320761127)
(0.09955, 0.21113467656415694, 0.13530411145090046)
(0.0997, 0.2114528101802757, 0.13550798504926945)
(0.09905, 0.21007423117709437, 0.1346245327896704)
(0.0981, 0.2080593849416755, 0.13333333333333336)
--- 387.862884045 seconds ---
{% endhighlight %}

### Conclusion

In short, user-based CF is appropriate for a situation that items increase fast with real-time demand, such as news recommendation. While in e-commerce, movie recommendation, items usually don't change very much, so this often can be computed off line by item-based CF.

### References

1. [A Programmer's Guide to Data Mining](https://raw.githubusercontent.com/zacharski/pg2dm-python/master/ch2/recommender.py)
2. [Item-based Collaborative Filtering Recommendation Algorithms](glaros.dtc.umn.edu/gkhome/fetch/papers/www10_sarwar.pdf)
3. [推荐系统实践 (Practice in Recommendation system)](https://book.douban.com/subject/10769749/)
4. [协同过滤实现 (Implementation of Collaborative Filtering)](http://wuchong.me/blog/2014/04/19/recsys-cf-study/)

---
Published under (CC) BY-NC-SA


text:
using System;
using System.Collections.Generic;
using JetBrains.Annotations;

namespace ObservableData.Structures
{
    public interface IListOperation<out T>
    {
        TResult Match<TResult>(
            [NotNull] Func<IListInsertOperation<T>, TResult> onInsert,
            [NotNull] Func<IListRemoveOperation<T>, TResult> onRemove,
            [NotNull] Func<IListReplaceOperation<T>, TResult> onReplace,
            [NotNull] Func<IListMoveOperation<T>, TResult> onMove,
            [NotNull] Func<IListResetOperation<T>, TResult> onReset);

        void Match(
            Action<IListInsertOperation<T>> onInsert,
            Action<IListRemoveOperation<T>> onRemove,
            Action<IListReplaceOperation<T>> onReplace,
            Action<IListMoveOperation<T>> onMove,
            Action<IListResetOperation<T>> onReset);
    }

    public interface IListInsertOperation<out T> : IListOperation<T>
    {
        int Index { get; }

        [NotNull]
        IReadOnlyCollection<T> Items { get; }
    }

    public interface IListRemoveOperation<out T> : IListOperation<T>
    {
        int Index { get; }

        T Item { get; }
    }

    public interface IListReplaceOperation<out T> : IListOperation<T>
    {
        int Index { get; }

        T Item { get; }

        T ReplacedItem { get; }
    }

    public interface IListMoveOperation<out T> : IListOperation<T>
    {
        T Item { get; }

        int From { get; }

        int To { get; }
    }

    public interface IListResetOperation<out T> : IListOperation<T>
    {
        [CanBeNull]
        IReadOnlyCollection<T> Items { get; }
    }
}


text:
package io.cdap.google.plugins;

import com.google.cloud.language.v1.AnalyzeSentimentResponse;
import com.google.protobuf.MessageOrBuilder;
import io.cdap.cdap.api.annotation.Description;
import io.cdap.cdap.api.annotation.Name;
import io.cdap.cdap.api.annotation.Plugin;
import io.cdap.cdap.api.data.format.StructuredRecord;
import io.cdap.cdap.api.data.schema.Schema;
import io.cdap.cdap.etl.api.Transform;
import io.cdap.google.common.NLPMethod;

/**
 * Provides the prevailing emotional opinion within a provided text. The API returns two values: The score describes
 * the emotional leaning of the text from -1 (negative) to +1 (positive), with 0 being neutral.
 *
 * The magnitude measures the strength of the emotion.
 *
 * The json returned by API:
 * {
 *   "documentSentiment": {
 *     "magnitude": 0.8,
 *     "score": 0.8
 *   },
 *   "language": "en",
 *   "sentences": [
 *     {
 *       "text": {
 *         "content": "Enjoy your vacation!",
 *         "beginOffset": 0
 *       },
 *       "sentiment": {
 *         "magnitude": 0.8,
 *         "score": 0.8
 *       }
 *     }
 *   ]
 * }
 *
 * is translated into:
 *
 * { # record
 *   "magnitude": 0.8,
 *   "score": 0.8
 *   "language": "en",
 *   "sentences": [ # array
 *     { # record
 *       "content": "Enjoy your vacation!",
 *       "beginOffset": 0
 *       "magnitude": 0.8,
 *       "score": 0.8
 *     }
 *   ]
 * }
 */
@Plugin(type = Transform.PLUGIN_TYPE)
@Name("NLPAnalyzeSentiment")
@Description("Provides the prevailing emotional opinion within a provided text. The API returns two values: The " +
  "\"score\" describes the emotional leaning of the text from -1 (negative) to +1 (positive), with 0 being neutral.\n" +
  "The \"magnitude\" measures the strength of the emotion.")
public class AnalyzeSentimentTransform extends NLPTransform {
  private static final Schema SCHEMA =
    Schema.recordOf(AnalyzeSentimentTransform.class.getSimpleName(),
                    Schema.Field.of("language", Schema.of(Schema.Type.STRING)),
                    Schema.Field.of("score", Schema.nullableOf(Schema.of(Schema.Type.DOUBLE))),
                    Schema.Field.of("magnitude", Schema.nullableOf(Schema.of(Schema.Type.DOUBLE))),
                    Schema.Field.of("sentences", Schema.arrayOf(SENTENCE_SCORED)));

  public AnalyzeSentimentTransform(NLPConfig config) {
    super(config);
  }

  @Override
  protected StructuredRecord getRecordFromResponse(MessageOrBuilder message) {
    AnalyzeSentimentResponse response = (AnalyzeSentimentResponse) message;

    StructuredRecord.Builder builder = StructuredRecord.builder(SCHEMA);
    builder.set("language", response.getLanguage());

    builder.set("score", response.getDocumentSentiment().getScore());
    builder.set("magnitude", response.getDocumentSentiment().getMagnitude());

    builder.set("sentences", getSentences(response.getSentencesList(), SENTENCE_SCORED));

    return builder.build();
  }

  protected NLPMethod getMethod() {
    return NLPMethod.ANALYZE_SENTIMENT;
  }
}


text:
package com.google.api.ads.adwords.jaxws.v201506.cm;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 *             Represents a feed item's value for a particular feed attribute. A feed item's value is
 *             composed of a collection of these attribute values.
 *
 *
 *
Java class for FeedItemAttributeValue complex type.
 *
 *
The following schema fragment specifies the expected content contained within this class.
 *
 *

 * <complexType name="FeedItemAttributeValue">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="feedAttributeId" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
 *         <element name="integerValue" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
 *         <element name="doubleValue" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
 *         <element name="booleanValue" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
 *         <element name="stringValue" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         <element name="integerValues" type="{http://www.w3.org/2001/XMLSchema}long" maxOccurs="unbounded" minOccurs="0"/>
 *         <element name="doubleValues" type="{http://www.w3.org/2001/XMLSchema}double" maxOccurs="unbounded" minOccurs="0"/>
 *         <element name="booleanValues" type="{http://www.w3.org/2001/XMLSchema}boolean" maxOccurs="unbounded" minOccurs="0"/>
 *         <element name="stringValues" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
 *       </sequence>
 *     </restriction>
 *   </complexContent>
 * </complexType>
 *

 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "FeedItemAttributeValue", propOrder = {
    "feedAttributeId",
    "integerValue",
    "doubleValue",
    "booleanValue",
    "stringValue",
    "integerValues",
    "doubleValues",
    "booleanValues",
    "stringValues"
})
public class FeedItemAttributeValue {

    protected Long feedAttributeId;
    protected Long integerValue;
    protected Double doubleValue;
    protected Boolean booleanValue;
    protected String stringValue;
    @XmlElement(type = Long.class)
    protected List<Long> integerValues;
    @XmlElement(type = Double.class)
    protected List<Double> doubleValues;
    @XmlElement(type = Boolean.class)
    protected List<Boolean> booleanValues;
    protected List<String> stringValues;

    /**
     * Gets the value of the feedAttributeId property.
     *
     * @return
     *     possible object is
     *     {@link Long }
     *
     */
    public Long getFeedAttributeId() {
        return feedAttributeId;
    }

    /**
     * Sets the value of the feedAttributeId property.
     *
     * @param value
     *     allowed object is
     *     {@link Long }
     *
     */
    public void setFeedAttributeId(Long value) {
        this.feedAttributeId = value;
    }

    /**
     * Gets the value of the integerValue property.
     *
     * @return
     *     possible object is
     *     {@link Long }
     *
     */
    public Long getIntegerValue() {
        return integerValue;
    }

    /**
     * Sets the value of the integerValue property.
     *
     * @param value
     *     allowed object is
     *     {@link Long }
     *
     */
    public void setIntegerValue(Long value) {
        this.integerValue = value;
    }

    /**
     * Gets the value of the doubleValue property.
     *
     * @return
     *     possible object is
     *     {@link Double }
     *
     */
    public Double getDoubleValue() {
        return doubleValue;
    }

    /**
     * Sets the value of the doubleValue property.
     *
     * @param value
     *     allowed object is
     *     {@link Double }
     *
     */
    public void setDoubleValue(Double value) {
        this.doubleValue = value;
    }

    /**
     * Gets the value of the booleanValue property.
     *
     * @return
     *     possible object is
     *     {@link Boolean }
     *
     */
    public Boolean isBooleanValue() {
        return booleanValue;
    }

    /**
     * Sets the value of the booleanValue property.
     *
     * @param value
     *     allowed object is
     *     {@link Boolean }
     *
     */
    public void setBooleanValue(Boolean value) {
        this.booleanValue = value;
    }

    /**
     * Gets the value of the stringValue property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *
     */
    public String getStringValue() {
        return stringValue;
    }

    /**
     * Sets the value of the stringValue property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *
     */
    public void setStringValue(String value) {
        this.stringValue = value;
    }

    /**
     * Gets the value of the integerValues property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the integerValues property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getIntegerValues().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link Long }
     *
     *
     */
    public List<Long> getIntegerValues() {
        if (integerValues == null) {
            integerValues = new ArrayList<Long>();
        }
        return this.integerValues;
    }

    /**
     * Gets the value of the doubleValues property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the doubleValues property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getDoubleValues().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link Double }
     *
     *
     */
    public List<Double> getDoubleValues() {
        if (doubleValues == null) {
            doubleValues = new ArrayList<Double>();
        }
        return this.doubleValues;
    }

    /**
     * Gets the value of the booleanValues property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the booleanValues property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getBooleanValues().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link Boolean }
     *
     *
     */
    public List<Boolean> getBooleanValues() {
        if (booleanValues == null) {
            booleanValues = new ArrayList<Boolean>();
        }
        return this.booleanValues;
    }

    /**
     * Gets the value of the stringValues property.
     *
     *

     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a set method for the stringValues property.
     *
     *

     * For example, to add a new item, do as follows:
     *

     *    getStringValues().add(newItem);
     *

     *
     *
     *

     * Objects of the following type(s) are allowed in the list
     * {@link String }
     *
     *
     */
    public List<String> getStringValues() {
        if (stringValues == null) {
            stringValues = new ArrayList<String>();
        }
        return this.stringValues;
    }

}


text: module.exports.phantomjs = '/src/lib/phantom/bin/phantomjs';


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>org.codehaus.groovy.reflection.stdclasses (Groovy 2.4.4)</title>
<meta name="date" content="2015-07-09">
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">

org.codehaus.groovy.reflection.stdclasses

Classes

ArrayCachedClass

BigDecimalCachedClass

BigIntegerCachedClass

BooleanCachedClass

ByteCachedClass

CachedClosureClass

CachedSAMClass

CharacterCachedClass

DoubleCachedClass

FloatCachedClass

IntegerCachedClass

LongCachedClass

NumberCachedClass

ObjectCachedClass

ShortCachedClass

StringCachedClass


text:
#pragma once

typedef const char* string_t;

string_t shs_cat_(string_t first,...);
#define shs_cat(...) shs_cat_(__VA_ARGS__,(void*)0)
string_t shs_dup(string_t str);
string_t shs_decode(string_t *str,char* buf);

void sh_system(string_t cmd);

void sh_docmd(int argc,const string_t *argv);

void sh_prompt_update();
string_t sh_prompt();


text:
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __NS_SVGGRADIENTELEMENT_H__
#define __NS_SVGGRADIENTELEMENT_H__

#include "nsSVGAnimatedTransformList.h"
#include "nsSVGElement.h"
#include "nsSVGLength2.h"
#include "nsSVGEnum.h"
#include "nsSVGString.h"

static const unsigned short SVG_SPREADMETHOD_UNKNOWN = 0;
static const unsigned short SVG_SPREADMETHOD_PAD     = 1;
static const unsigned short SVG_SPREADMETHOD_REFLECT = 2;
static const unsigned short SVG_SPREADMETHOD_REPEAT  = 3;

class nsSVGGradientFrame;
class nsSVGLinearGradientFrame;
class nsSVGRadialGradientFrame;

nsresult
NS_NewSVGLinearGradientElement(nsIContent** aResult,
                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
nsresult
NS_NewSVGRadialGradientElement(nsIContent** aResult,
                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);

namespace mozilla {
namespace dom {

class SVGAnimatedTransformList;

//--------------------- Gradients------------------------

typedef nsSVGElement SVGGradientElementBase;

class SVGGradientElement : public SVGGradientElementBase
{
  friend class ::nsSVGGradientFrame;

protected:
  explicit SVGGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
  virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override = 0;

public:
  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;

  // nsIContent
  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;

  virtual nsSVGAnimatedTransformList*
    GetAnimatedTransformList(uint32_t aFlags = 0) override;
  virtual nsIAtom* GetTransformListAttrName() const override {
    return nsGkAtoms::gradientTransform;
  }

  // WebIDL
  already_AddRefed<SVGAnimatedEnumeration> GradientUnits();
  already_AddRefed<SVGAnimatedTransformList> GradientTransform();
  already_AddRefed<SVGAnimatedEnumeration> SpreadMethod();
  already_AddRefed<SVGAnimatedString> Href();

protected:
  virtual EnumAttributesInfo GetEnumInfo() override;
  virtual StringAttributesInfo GetStringInfo() override;

  enum { GRADIENTUNITS, SPREADMETHOD };
  nsSVGEnum mEnumAttributes[2];
  static nsSVGEnumMapping sSpreadMethodMap[];
  static EnumInfo sEnumInfo[2];

  enum { HREF };
  nsSVGString mStringAttributes[1];
  static StringInfo sStringInfo[1];

  // SVGGradientElement values
  nsAutoPtr<nsSVGAnimatedTransformList> mGradientTransform;
};

//---------------------Linear Gradients------------------------

typedef SVGGradientElement SVGLinearGradientElementBase;

class SVGLinearGradientElement : public SVGLinearGradientElementBase
{
  friend class ::nsSVGLinearGradientFrame;
  friend nsresult
    (::NS_NewSVGLinearGradientElement(nsIContent** aResult,
                                      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));

protected:
  explicit SVGLinearGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
  virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

public:
  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;

  // WebIDL
  already_AddRefed<SVGAnimatedLength> X1();
  already_AddRefed<SVGAnimatedLength> Y1();
  already_AddRefed<SVGAnimatedLength> X2();
  already_AddRefed<SVGAnimatedLength> Y2();

protected:

  virtual LengthAttributesInfo GetLengthInfo() override;

  enum { ATTR_X1, ATTR_Y1, ATTR_X2, ATTR_Y2 };
  nsSVGLength2 mLengthAttributes[4];
  static LengthInfo sLengthInfo[4];
};

//-------------------------- Radial Gradients ----------------------------

typedef SVGGradientElement SVGRadialGradientElementBase;

class SVGRadialGradientElement : public SVGRadialGradientElementBase
{
  friend class ::nsSVGRadialGradientFrame;
  friend nsresult
    (::NS_NewSVGRadialGradientElement(nsIContent** aResult,
                                      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));

protected:
  explicit SVGRadialGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
  virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

public:
  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;

  // WebIDL
  already_AddRefed<SVGAnimatedLength> Cx();
  already_AddRefed<SVGAnimatedLength> Cy();
  already_AddRefed<SVGAnimatedLength> R();
  already_AddRefed<SVGAnimatedLength> Fx();
  already_AddRefed<SVGAnimatedLength> Fy();
protected:

  virtual LengthAttributesInfo GetLengthInfo() override;

  enum { ATTR_CX, ATTR_CY, ATTR_R, ATTR_FX, ATTR_FY };
  nsSVGLength2 mLengthAttributes[5];
  static LengthInfo sLengthInfo[5];
};

} // namespace dom
} // namespace mozilla

#endif


text:
package info.haxahaxa.compiler;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

public class SimpleMessageBuilder implements IMessageBuilder {
	private Map<JavaFileObject, List<String>> codes = new HashMap<JavaFileObject, List<String>>();

	@Override
	public String getCompleteMessage(ICompileResult result) {
		// TODO Auto-generated method stub
		return "Complete";
	}

	@Override
	public String getErrorMessage(
			Diagnostic<? extends JavaFileObject> diagnostic) throws Exception {
		// TODO Auto-generated method stub
		return diagnostic.getMessage(null) + getLine(diagnostic);
	}

	protected String getLine(Diagnostic<? extends JavaFileObject> diagnostic) {
		String ret = System.getProperty("line.separator", "\n");
		StringBuilder sb = new StringBuilder();
		List<String> code = getSourceCode(diagnostic.getSource());
		if (code == null) {
			return null;
		}
		sb.append(ret);
		sb.append(code.get((int) diagnostic.getLineNumber() - 1));
		sb.append(ret);
		sb.append(String.format("%" + diagnostic.getColumnNumber() + "s", "^"));

		return sb.toString();
	}

	protected List<String> getSourceCode(JavaFileObject javaFile) {
		if (javaFile == null) {
			return null;
		}
		List<String> code = codes.get(javaFile);
		if (code != null) {
			return code;
		}
		code = new ArrayList<String>();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					javaFile.openInputStream()));
			String line = null;
			while ((line = br.readLine()) != null) {
				code.add(line);
			}
			codes.put(javaFile, code);
			br.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return code;
	}
}


text:
package kafka;

import java.util.Properties;
import java.util.Random;

import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;

public class SentenceProducer {

  public static final String TOPIC = "sentences";

  public static final String[] SENTENCES = new String[] { "That was the worst movie I have ever seen",
      "I love you and you are a good person", "Hadoop is the coolest program ever",
      "You did a nice job singing in the choir yesterday!", "not a good day.", "good are things are happening. lol", "I am so mad",
      "I am so rich", "I hate brownies. They are too rich", "I love brownies. They are so rich", "Rainbows make me want to cry",
      "I love to watch rainbows - they make me happy", "I hate coffee", "I love coffee", "You make me frown", "You make me smile" };

  public static final String[] CATEGORIES = new String[] { "Politics", "Sports", "Home", "Work" };

  public static void main(String... args) throws InterruptedException {
    long events = 10000;
    if (args.length > 0) {
      events = Long.parseLong(args[0]);
    }
    Random rnd = new Random();

    Properties props = new Properties();
    props.put("metadata.broker.list", "node1:9092,node2:9092,node3:9092,node4:9092");
    props.put("serializer.class", "kafka.serializer.StringEncoder");
    props.put("request.required.acks", "1");

    ProducerConfig config = new ProducerConfig(props);
    Producer<String, String> producer = new Producer<String, String>(config);

    try {
      for (long nEvents = 0; nEvents < events; nEvents++) {
        String sentence = SENTENCES[rnd.nextInt(SENTENCES.length)];
        String category = CATEGORIES[rnd.nextInt(CATEGORIES.length)];
        KeyedMessage<String, String> data = new KeyedMessage<String, String>("sentences", category, sentence);
        producer.send(data);
      }
    }
    finally {
      producer.close();
    }
  }
}