# Raster API

Header | cups/raster.h
--- | ---
Library | -lcupsimage
See Also | Programming: Introduction to CUPS Programming Programming: CUPS API Programming: PPD API References: CUPS PPD Specification

## Contents

- Overview
- Functions by Task
  - Opening and Closing Raster Streams
  - Reading Raster Streams
  - Writing Raster Streams
- Functions
  - cupsRasterClose
  - cupsRasterInterpretPPD
  - cupsRasterOpen
  - cupsRasterReadHeader
  - cupsRasterReadHeader2
  - cupsRasterReadPixels
  - cupsRasterWriteHeader
  - cupsRasterWriteHeader2
  - cupsRasterWritePixels
- Data Types
  - cups_adv_t
  - cups_bool_t
  - cups_cspace_t
  - cups_cut_t
  - cups_edge_t
  - cups_interpret_cb_t
  - cups_jog_t
  - cups_mode_t
  - cups_order_t
  - cups_orient_t
  - cups_page_header2_t
  - cups_page_header_t
  - cups_raster_t
- Structures
  - cups_page_header2_s
  - cups_page_header_s
- Constants
  - cups_adv_e
  - cups_bool_e
  - cups_cspace_e
  - cups_cut_e
  - cups_edge_e
  - cups_jog_e
  - cups_mode_e
  - cups_order_e
  - cups_orient_e

## Overview

The CUPS raster API provides a standard interface for reading and writing CUPS raster streams which are used for printing to raster printers. Because the raster format is updated from time to time, it is important to use this API to avoid incompatibilities with newer versions of CUPS.

Two kinds of CUPS filters use the CUPS raster API - raster image processor (RIP) filters such as `pstoraster` and `cgpdftoraster` (Mac OS X) that produce CUPS raster files and printer driver filters that convert CUPS raster files into a format usable by the printer. Printer driver filters are by far the most common.

CUPS raster files (`application/vnd.cups-raster`) consists of a stream of raster page descriptions produced by one of the RIP filters such as pstoraster, imagetoraster, or cgpdftoraster. CUPS raster files are referred to using the `cups_raster_t` type and are opened using the `cupsRasterOpen` function. For example, to read raster data from the standard input, open file descriptor 0:

    #include <cups/raster.h>>

    cups_raster_t *ras = cupsRasterOpen(0, CUPS_RASTER_READ);

Each page of data begins with a page dictionary structure called `cups_page_header2_t`. This structure contains the colorspace, bits per color, media size, media type, hardware resolution, and so forth used for the page.

> Note:

> Do not confuse the colorspace in the page header with the PPD `ColorModel` keyword. `ColorModel` refers to the general type of color used for a device (Gray, RGB, CMYK, DeviceN) and is often used to select a particular colorspace for the page header along with the associate color profile. The page header colorspace (`cupsColorSpace`) describes both the type and organization of the color data, for example KCMY (black first) instead of CMYK and RGBA (RGB + alpha) instead of RGB.

You read the page header using the `cupsRasterReadHeader2` function:

    #include <cups/raster.h>>

    cups_raster_t *ras = cupsRasterOpen(0, CUPS_RASTER_READ);
    cups_page_header2_t header;

    while (cupsRasterReadHeader2(ras, &header))
    {
      /* setup this page */

      /* read raster data */

      /* finish this page */
    }

After the page dictionary comes the page data which is a full-resolution, possibly compressed bitmap representing the page in the printer's output colorspace. You read uncompressed raster data using the `cupsRasterReadPixels` function. A `for` loop is normally used to read the page one line at a time:

    #include <cups/raster.h>>

    cups_raster_t *ras = cupsRasterOpen(0, CUPS_RASTER_READ);
    cups_page_header2_t header;
    int page = 0;
    int y;
    char *buffer;

    while (cupsRasterReadHeader2(ras, &header))
    {
      /* setup this page */
      page ++;
      fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies);

      /* allocate memory for 1 line */
      buffer = malloc(header.cupsBytesPerLine);

      /* read raster data */
      for (y = 0; y < header.cupsHeight; y ++)
      {
        if (cupsRasterReadPixels(ras, buffer, header.cupsBytesPerLine) == 0)
          break;

        /* write raster data to printer on stdout */
      }

      /* finish this page */
    }

When you are done reading the raster data, call the `cupsRasterClose` function to free the memory used to read the raster file:

    cups_raster_t *ras;

    cupsRasterClose(ras);

## Functions by Task

### Opening and Closing Raster Streams

- cupsRasterClose
- cupsRasterOpen

### Reading Raster Streams

- cupsRasterReadHeader Deprecated in CUPS 1.2/Mac OS X 10.5
- cupsRasterReadHeader2
- cupsRasterReadPixels

### Writing Raster Streams

- cupsRasterInterpretPPD
- cupsRasterWriteHeader Deprecated in CUPS 1.2/Mac OS X 10.5
- cupsRasterWriteHeader2
- cupsRasterWritePixels

## Functions

### cupsRasterClose

Close a raster stream.

void cupsRasterClose (
cups_raster_t *r
);

#### Parameters

r
  Stream to close

#### Discussion

The file descriptor associated with the raster stream must be closed separately as needed.

### CUPS 1.2/Mac OS X 10.5 cupsRasterInterpretPPD

Interpret PPD commands to create a page header.

int cupsRasterInterpretPPD (
cups_page_header2_t *h,
ppd_file_t *ppd,
int num_options,
cups_option_t *options,
cups_interpret_cb_t func
);

#### Parameters

h
  Page header to create
ppd
  PPD file
num_options
  Number of options
options
  Options
func
  Optional page header callback (`NULL` for none)

#### Return Value

0 on success, -1 on failure

#### Discussion

This function is used by raster image processing (RIP) filters like cgpdftoraster and imagetoraster when writing CUPS raster data for a page. It is not used by raster printer driver filters which only read CUPS raster data.
`cupsRasterInterpretPPD` does not mark the options in the PPD using the "num_options" and "options" arguments. Instead, mark the options with `cupsMarkOptions` and `ppdMarkOption` prior to calling it - this allows for per-page options without manipulating the options array.
The "func" argument specifies an optional callback function that is called prior to the computation of the final raster data. The function can make changes to the `cups_page_header2_t` data as needed to use a supported raster format and then returns 0 on success and -1 if the requested attributes cannot be supported.
`cupsRasterInterpretPPD` supports a subset of the PostScript language. Currently only the `[`, `]`, `<<`, `>>`, `{`, `}`, `cleartomark`, `copy`, `dup`, `index`, `pop`, `roll`, `setpagedevice`, and `stopped` operators are supported.

### cupsRasterOpen

Open a raster stream.

cups_raster_t *cupsRasterOpen (
int fd,
cups_mode_t mode
);

#### Parameters

fd
  File descriptor
mode
  Mode - `CUPS_RASTER_READ`, `CUPS_RASTER_WRITE`, or `CUPS_RASTER_WRITE_COMPRESSED`

#### Return Value

New stream

#### Discussion

This function associates a raster stream with the given file descriptor. For most printer driver filters, "fd" will be 0 (stdin). For most raster image processor (RIP) filters that generate raster data, "fd" will be 1 (stdout).
When writing raster data, the `CUPS_RASTER_WRITE` or `CUPS_RASTER_WRITE_COMPRESS` mode can be used - compressed output is generally 25-50% smaller but adds a 100-300% execution time overhead.

### DEPRECATED cupsRasterReadHeader

Read a raster page header and store it in a version 1 page header structure.

unsigned cupsRasterReadHeader (
cups_raster_t *r,
cups_page_header_t *h
);

#### Parameters

r
  Raster stream
h
  Pointer to header data

#### Return Value

1 on success, 0 on failure/end-of-file

#### Discussion

This function is deprecated. Use `cupsRasterReadHeader2` instead.
Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset of the version 2 page header data. This function handles reading version 2 page headers and copying only the version 1 data into the provided buffer.

### CUPS 1.2/Mac OS X 10.5 cupsRasterReadHeader2

Read a raster page header and store it in a version 2 page header structure.

unsigned cupsRasterReadHeader2 (
cups_raster_t *r,
cups_page_header2_t *h
);

#### Parameters

r
  Raster stream
h
  Pointer to header data

#### Return Value

1 on success, 0 on failure/end-of-file

### cupsRasterReadPixels

Read raster pixels.

unsigned cupsRasterReadPixels (
cups_raster_t *r,
unsigned char *p,
unsigned len
);

#### Parameters

r
  Raster stream
p
  Pointer to pixel buffer
len
  Number of bytes to read

#### Return Value

Number of bytes read

#### Discussion

For best performance, filters should read one or more whole lines. The "cupsBytesPerLine" value from the page header can be used to allocate the line buffer and as the number of bytes to read.

### DEPRECATED cupsRasterWriteHeader

Write a raster page header from a version 1 page header structure.

unsigned cupsRasterWriteHeader (
cups_raster_t *r,
cups_page_header_t *h
);

#### Parameters

r
  Raster stream
h
  Raster page header

#### Return Value

1 on success, 0 on failure

#### Discussion

This function is deprecated. Use `cupsRasterWriteHeader2` instead.

### CUPS 1.2/Mac OS X 10.5 cupsRasterWriteHeader2

Write a raster page header from a version 2 page header structure.

unsigned cupsRasterWriteHeader2 (
cups_raster_t *r,
cups_page_header2_t *h
);

#### Parameters

r
  Raster stream
h
  Raster page header

#### Return Value

1 on success, 0 on failure

#### Discussion

The page header can be initialized using `cupsRasterInterpretPPD`.

### cupsRasterWritePixels

Write raster pixels.

unsigned cupsRasterWritePixels (
cups_raster_t *r,
unsigned char *p,
unsigned len
);

#### Parameters

r
  Raster stream
p
  Bytes to write
len
  Number of bytes to write

#### Return Value

Number of bytes written

#### Discussion

For best performance, filters should write one or more whole lines. The "cupsBytesPerLine" value from the page header can be used to allocate the line buffer and as the number of bytes to write.

## Data Types

### cups_adv_t

AdvanceMedia attribute values

typedef enum cups_adv_e cups_adv_t;

### cups_bool_t

Boolean type

typedef enum cups_bool_e cups_bool_t;

### cups_cspace_t

cupsColorSpace attribute values

typedef enum cups_cspace_e cups_cspace_t;

### cups_cut_t

CutMedia attribute values

typedef enum cups_cut_e cups_cut_t;

### cups_edge_t

LeadingEdge attribute values

typedef enum cups_edge_e cups_edge_t;

### cups_interpret_cb_t

cupsRasterInterpretPPD callback function

typedef int (*cups_interpret_cb_t)(cups_page_header2_t *header, int preferred_bits);

### cups_jog_t

Jog attribute values

typedef enum cups_jog_e cups_jog_t;

### cups_mode_t

cupsRasterOpen modes

typedef enum cups_mode_e cups_mode_t;

### cups_order_t

cupsColorOrder attribute values

typedef enum cups_order_e cups_order_t;

### cups_orient_t

Orientation attribute values

typedef enum cups_orient_e cups_orient_t;

### CUPS 1.2/Mac OS X 10.5 cups_page_header2_t

Version 2 page header

typedef struct cups_page_header2_s cups_page_header2_t;

### DEPRECATED cups_page_header_t

Version 1 page header

typedef struct cups_page_header_s cups_page_header_t;

### cups_raster_t

Raster stream data

typedef struct _cups_raster_s cups_raster_t;

## Structures

### CUPS 1.2/Mac OS X 10.5 cups_page_header2_s

Version 2 page header

struct cups_page_header2_s {
unsigned AdvanceDistance;
cups_adv_t AdvanceMedia;
cups_bool_t Collate;
cups_cut_t CutMedia;
cups_bool_t Duplex;
unsigned HWResolution[2];
unsigned ImagingBoundingBox[4];
cups_bool_t InsertSheet;
cups_jog_t Jog;
cups_edge_t LeadingEdge;
cups_bool_t ManualFeed;
unsigned Margins[2];
char MediaClass[64];
char MediaColor[64];
unsigned MediaPosition;
char MediaType[64];
unsigned MediaWeight;
cups_bool_t MirrorPrint;
cups_bool_t NegativePrint;
unsigned NumCopies;
cups_orient_t Orientation;
cups_bool_t OutputFaceUp;
char OutputType[64];
unsigned PageSize[2];
cups_bool_t Separations;
cups_bool_t TraySwitch;
cups_bool_t Tumble;
unsigned cupsBitsPerColor;
unsigned cupsBitsPerPixel;
float cupsBorderlessScalingFactor;
unsigned cupsBytesPerLine;
cups_order_t cupsColorOrder;
cups_cspace_t cupsColorSpace;
unsigned cupsCompression;
unsigned cupsHeight;
float cupsImagingBBox[4];
unsigned cupsInteger[16];
char cupsMarkerType[64];
unsigned cupsMediaType;
unsigned cupsNumColors;
char cupsPageSizeName[64];
float cupsPageSize[2];
float cupsReal[16];
char cupsRenderingIntent[64];
unsigned cupsRowCount;
unsigned cupsRowFeed;
unsigned cupsRowStep;
char cupsString[16][64];
unsigned cupsWidth;
};

#### Members

AdvanceDistance
  AdvanceDistance value in points
AdvanceMedia
  AdvanceMedia value (`cups_adv_t`)
Collate
  Collated copies value
CutMedia
  CutMedia value (`cups_cut_t`)
Duplex
  Duplexed (double-sided) value
HWResolution[2]
  Resolution in dots-per-inch
ImagingBoundingBox[4]
  Pixel region that is painted (points, left, bottom, right, top)
InsertSheet
  InsertSheet value
Jog
  Jog value (`cups_jog_t`)
LeadingEdge
  LeadingEdge value (`cups_edge_t`)
ManualFeed
  ManualFeed value
Margins[2]
  Lower-lefthand margins in points
MediaClass[64]
  MediaClass string
MediaColor[64]
  MediaColor string
MediaPosition
  MediaPosition value
MediaType[64]
  MediaType string
MediaWeight
  MediaWeight value in grams/m^2
MirrorPrint
  MirrorPrint value
NegativePrint
  NegativePrint value
NumCopies
  Number of copies to produce
Orientation
  Orientation value (`cups_orient_t`)
OutputFaceUp
  OutputFaceUp value
OutputType[64]
  OutputType string
PageSize[2]
  Width and length of page in points
Separations
  Separations value
TraySwitch
  TraySwitch value
Tumble
  Tumble value
cupsBitsPerColor
  Number of bits for each color
cupsBitsPerPixel
  Number of bits for each pixel
cupsBorderlessScalingFactor CUPS 1.2/Mac OS X 10.5
  Scaling that was applied to page data
cupsBytesPerLine
  Number of bytes per line
cupsColorOrder
  Order of colors
cupsColorSpace
  True colorspace
cupsCompression
  Device compression to use
cupsHeight
  Height of page image in pixels
cupsImagingBBox[4] CUPS 1.2/Mac OS X 10.5
  Floating point ImagingBoundingBox (scaling factor not applied, left, bottom, right, top)
cupsInteger[16] CUPS 1.2/Mac OS X 10.5
  User-defined integer values
cupsMarkerType[64] CUPS 1.2/Mac OS X 10.5
  Ink/toner type
cupsMediaType
  Media type code
cupsNumColors CUPS 1.2/Mac OS X 10.5
  Number of color compoents
cupsPageSizeName[64] CUPS 1.2/Mac OS X 10.5
  PageSize name
cupsPageSize[2] CUPS 1.2/Mac OS X 10.5
  Floating point PageSize (scaling * factor not applied)
cupsReal[16] CUPS 1.2/Mac OS X 10.5
  User-defined floating-point values
cupsRenderingIntent[64] CUPS 1.2/Mac OS X 10.5
  Color rendering intent
cupsRowCount
  Rows per band
cupsRowFeed
  Feed between bands
cupsRowStep
  Spacing between lines
cupsString[16][64] CUPS 1.2/Mac OS X 10.5
  User-defined string values
cupsWidth
  Width of page image in pixels

### DEPRECATED cups_page_header_s

Version 1 page header

struct cups_page_header_s {
unsigned AdvanceDistance;
cups_adv_t AdvanceMedia;
cups_bool_t Collate;
cups_cut_t CutMedia;
cups_bool_t Duplex;
unsigned HWResolution[2];
unsigned ImagingBoundingBox[4];
cups_bool_t InsertSheet;
cups_jog_t Jog;
cups_edge_t LeadingEdge;
cups_bool_t ManualFeed;
unsigned Margins[2];
char MediaClass[64];
char MediaColor[64];
unsigned MediaPosition;
char MediaType[64];
unsigned MediaWeight;
cups_bool_t MirrorPrint;
cups_bool_t NegativePrint;
unsigned NumCopies;
cups_orient_t Orientation;
cups_bool_t OutputFaceUp;
char OutputType[64];
unsigned PageSize[2];
cups_bool_t Separations;
cups_bool_t TraySwitch;
cups_bool_t Tumble;
unsigned cupsBitsPerColor;
unsigned cupsBitsPerPixel;
unsigned cupsBytesPerLine;
cups_order_t cupsColorOrder;
cups_cspace_t cupsColorSpace;
unsigned cupsCompression;
unsigned cupsHeight;
unsigned cupsMediaType;
unsigned cupsRowCount;
unsigned cupsRowFeed;
unsigned cupsRowStep;
unsigned cupsWidth;
};

#### Members

AdvanceDistance
  AdvanceDistance value in points
AdvanceMedia
  AdvanceMedia value (`cups_adv_t`)
Collate
  Collated copies value
CutMedia
  CutMedia value (`cups_cut_t`)
Duplex
  Duplexed (double-sided) value
HWResolution[2]
  Resolution in dots-per-inch
ImagingBoundingBox[4]
  Pixel region that is painted (points, left, bottom, right, top)
InsertSheet
  InsertSheet value
Jog
  Jog value (`cups_jog_t`)
LeadingEdge
  LeadingEdge value (`cups_edge_t`)
ManualFeed
  ManualFeed value
Margins[2]
  Lower-lefthand margins in points
MediaClass[64]
  MediaClass string
MediaColor[64]
  MediaColor string
MediaPosition
  MediaPosition value
MediaType[64]
  MediaType string
MediaWeight
  MediaWeight value in grams/m^2
MirrorPrint
  MirrorPrint value
NegativePrint
  NegativePrint value
NumCopies
  Number of copies to produce
Orientation
  Orientation value (`cups_orient_t`)
OutputFaceUp
  OutputFaceUp value
OutputType[64]
  OutputType string
PageSize[2]
  Width and length of page in points
Separations
  Separations value
TraySwitch
  TraySwitch value
Tumble
  Tumble value
cupsBitsPerColor
  Number of bits for each color
cupsBitsPerPixel
  Number of bits for each pixel
cupsBytesPerLine
  Number of bytes per line
cupsColorOrder
  Order of colors
cupsColorSpace
  True colorspace
cupsCompression
  Device compression to use
cupsHeight
  Height of page image in pixels
cupsMediaType
  Media type code
cupsRowCount
  Rows per band
cupsRowFeed
  Feed between bands
cupsRowStep
  Spacing between lines
cupsWidth
  Width of page image in pixels

## Constants

### cups_adv_e

AdvanceMedia attribute values

#### Constants

CUPS_ADVANCE_FILE
  Advance the roll after this file
CUPS_ADVANCE_JOB
  Advance the roll after this job
CUPS_ADVANCE_NONE
  Never advance the roll
CUPS_ADVANCE_PAGE
  Advance the roll after this page
CUPS_ADVANCE_SET
  Advance the roll after this set

### cups_bool_e

Boolean type

#### Constants

CUPS_FALSE
  Logical false
CUPS_TRUE
  Logical true

### cups_cspace_e

cupsColorSpace attribute values

#### Constants

CUPS_CSPACE_CIELab CUPS 1.1.19/Mac OS X 10.3
  CIE Lab
CUPS_CSPACE_CIEXYZ CUPS 1.1.19/Mac OS X 10.3
  CIE XYZ
CUPS_CSPACE_CMY
  Cyan, magenta, yellow
CUPS_CSPACE_CMYK
  Cyan, magenta, yellow, black
CUPS_CSPACE_GMCK
  Gold, magenta, yellow, black
CUPS_CSPACE_GMCS
  Gold, magenta, yellow, silver
CUPS_CSPACE_GOLD
  Gold foil
CUPS_CSPACE_ICC1 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 1 color
CUPS_CSPACE_ICC2 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 2 colors
CUPS_CSPACE_ICC3 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 3 colors
CUPS_CSPACE_ICC4 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 4 colors
CUPS_CSPACE_ICC5 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 5 colors
CUPS_CSPACE_ICC6 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 6 colors
CUPS_CSPACE_ICC7 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 7 colors
CUPS_CSPACE_ICC8 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 8 colors
CUPS_CSPACE_ICC9 CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 9 colors
CUPS_CSPACE_ICCA CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 10 colors
CUPS_CSPACE_ICCB CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 11 colors
CUPS_CSPACE_ICCC CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 12 colors
CUPS_CSPACE_ICCD CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 13 colors
CUPS_CSPACE_ICCE CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 14 colors
CUPS_CSPACE_ICCF CUPS 1.1.19/Mac OS X 10.3
  ICC-based, 15 colors
CUPS_CSPACE_K
  Black
CUPS_CSPACE_KCMY
  Black, cyan, magenta, yellow
CUPS_CSPACE_KCMYcm
  Black, cyan, magenta, yellow, * light-cyan, light-magenta
CUPS_CSPACE_RGB
  Red, green, blue
CUPS_CSPACE_RGBA
  Red, green, blue, alpha
CUPS_CSPACE_RGBW CUPS 1.2/Mac OS X 10.5
  Red, green, blue, white
CUPS_CSPACE_SILVER
  Silver foil
CUPS_CSPACE_W
  Luminance
CUPS_CSPACE_WHITE
  White ink (as black)
CUPS_CSPACE_YMC
  Yellow, magenta, cyan
CUPS_CSPACE_YMCK
  Yellow, magenta, cyan, black

### cups_cut_e

CutMedia attribute values

#### Constants

CUPS_CUT_FILE
  Cut the roll after this file
CUPS_CUT_JOB
  Cut the roll after this job
CUPS_CUT_NONE
  Never cut the roll
CUPS_CUT_PAGE
  Cut the roll after this page
CUPS_CUT_SET
  Cut the roll after this set

### cups_edge_e

LeadingEdge attribute values

#### Constants

CUPS_EDGE_BOTTOM
  Leading edge is the bottom of the page
CUPS_EDGE_LEFT
  Leading edge is the left of the page
CUPS_EDGE_RIGHT
  Leading edge is the right of the page
CUPS_EDGE_TOP
  Leading edge is the top of the page

### cups_jog_e

Jog attribute values

#### Constants

CUPS_JOG_FILE
  Move pages after this file
CUPS_JOG_JOB
  Move pages after this job
CUPS_JOG_NONE
  Never move pages
CUPS_JOG_SET
  Move pages after this set

### cups_mode_e

cupsRasterOpen modes

#### Constants

CUPS_RASTER_READ
  Open stream for reading
CUPS_RASTER_WRITE
  Open stream for writing
CUPS_RASTER_WRITE_COMPRESSED CUPS 1.3/Mac OS X 10.5
  Open stream for compressed writing

### cups_order_e

cupsColorOrder attribute values

#### Constants

CUPS_ORDER_BANDED
  CCC MMM YYY KKK ...
CUPS_ORDER_CHUNKED
  CMYK CMYK CMYK ...
CUPS_ORDER_PLANAR
  CCC ... MMM ... YYY ... KKK ...

### cups_orient_e

Orientation attribute values

#### Constants

CUPS_ORIENT_0
  Don't rotate the page
CUPS_ORIENT_180
  Turn the page upside down
CUPS_ORIENT_270
  Rotate the page clockwise
CUPS_ORIENT_90
  Rotate the page counter-clockwise