Пример #1
0
/* Returns an XImage structure containing the string rendered in the font.
   This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
   extra byte set to 0xFF.

   Foreground and background are GL-style color specifiers: 4 floats from
   0.0-1.0.
 */
XImage *
text_to_ximage (Screen *screen, Visual *visual,
                const char *font,
                const char *text_lines,
                GLfloat *texture_fg,
                GLfloat *texture_bg)
{
  Display *dpy = DisplayOfScreen (screen);
  int width, height;
  XFontStruct *f;
  Pixmap bitmap;

  f = XLoadQueryFont(dpy, font);
  if (!f)
    {
      f = XLoadQueryFont(dpy, "fixed");
      if (f)
        fprintf (stderr, "%s: unable to load font \"%s\"; using \"fixed\".\n",
                 progname, font);
      else
        {
          fprintf (stderr, "%s: unable to load fonts \"%s\" or \"fixed\"!\n",
                   progname, font);
          exit (1);
        }
    }

  /* Parse the text, and render it to `bitmap'
   */
  {
    char *text, *text2, *line, *token;
    int lines;
    XCharStruct overall;
    XGCValues gcv;
    GC gc;

    int margin = 2;
    int fg = 1;
    int bg = 0;
    int xoff, yoff;

    text  = strdup (text_lines);
    while (*text &&
           (text[strlen(text)-1] == '\r' ||
            text[strlen(text)-1] == '\n'))
      text[strlen(text)-1] = 0;

    text2 = strdup (text);

    memset(&overall, 0, sizeof(overall));
    token = text;
    lines = 0;
    while ((line = strtok (token, "\r\n")))
      {
        XCharStruct o2;
        int ascent, descent, direction;
        token = 0;
        XTextExtents (f, line, strlen(line),
                      &direction, &ascent, &descent, &o2);
        overall.lbearing = MAX(overall.lbearing, o2.lbearing);
        overall.rbearing = MAX(overall.rbearing, o2.rbearing);
        lines++;
      }
    free (text);
    text = 0;

    width = overall.lbearing + overall.rbearing + margin + margin + 1;
    height = ((f->ascent + f->descent) * lines) + margin + margin;

    /* GL texture sizes must be powers of two. */
    {
      int w2 = to_pow2(width);
      int h2 = to_pow2(height);
      xoff = (w2 - width)  / 2;
      yoff = (h2 - height) / 2;
      width  = w2;
      height = h2;
    }

    bitmap = XCreatePixmap(dpy, RootWindowOfScreen (screen), width, height, 1);

    gcv.font = f->fid;
    gcv.foreground = bg;
    gc = XCreateGC (dpy, bitmap, (GCFont | GCForeground), &gcv);
    XFillRectangle(dpy, bitmap, gc, 0, 0, width, height);
    XSetForeground(dpy, gc, fg);

    token = text2;
    lines = 0;
    while ((line = strtok(token, "\r\n")))
      {
        XCharStruct o2;
        int ascent, descent, direction;
        token = 0;

        XTextExtents(f, line, strlen(line),
                     &direction, &ascent, &descent, &o2);
        XDrawString(dpy, bitmap, gc,
                    overall.lbearing + margin + xoff,
                    ((f->ascent * (lines + 1)) +
                     (f->descent * lines) +
                     margin +
                     yoff),
                    line, strlen(line));
        lines++;
      }
    free(text2);

    XUnloadFont(dpy, f->fid);
    XFree((XPointer) f);
    XFreeGC(dpy, gc);
  }

  /* Convert the server-side Pixmap to a client-side GL-ordered XImage.
   */
  {
    XImage *ximage1, *ximage2;
    unsigned long fg, bg;
    int x, y;

    ximage1 = XGetImage (dpy, bitmap, 0, 0, width, height, ~0L, ZPixmap);
    XFreePixmap(dpy, bitmap);
    ximage2 = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0,
                            width, height, 32, 0);

    ximage2->data = (char *) malloc (height * ximage2->bytes_per_line);

    /* Translate the 1-bit image to a deep image:
       first figure out what the colors are.
     */
    {
      int rpos, gpos, bpos, apos;  /* bitfield positions */

      /* Note that unlike X, which is endianness-agnostic (since any XImage
         can have its own specific bit ordering, with the server reversing
         things as necessary) OpenGL pretends everything is client-side, so
         we need to pack things in the right order for the client machine.
       */
#if 0
    /* #### Cherub says that the little-endian case must be taken on MacOSX,
            or else the colors/alpha are the wrong way around.  How can
            that be the case?
     */
      if (bigendian())
        rpos = 24, gpos = 16, bpos =  8, apos =  0;
      else
#endif
        rpos =  0, gpos =  8, bpos = 16, apos = 24;

      fg = (((unsigned long) (texture_fg[0] * 255.0) << rpos) |
            ((unsigned long) (texture_fg[1] * 255.0) << gpos) |
            ((unsigned long) (texture_fg[2] * 255.0) << bpos) |
            ((unsigned long) (texture_fg[3] * 255.0) << apos));
      bg = (((unsigned long) (texture_bg[0] * 255.0) << rpos) |
            ((unsigned long) (texture_bg[1] * 255.0) << gpos) |
            ((unsigned long) (texture_bg[2] * 255.0) << bpos) |
            ((unsigned long) (texture_bg[3] * 255.0) << apos));
    }

    for (y = 0; y < height; y++)
      {
	int y2 = (height-1-y); /* Texture maps are upside down. */
	for (x = 0; x < width; x++)
          XPutPixel (ximage2, x, y, 
                     XGetPixel (ximage1, x, y2) ? fg : bg);
      }

    XDestroyImage (ximage1);

#if 0
    for (y = 0; y < height; y++)
      {
	int y2 = (height-1-y); /* Texture maps are upside down. */
	for (x = 0; x < width; x++)
          fputc ((XGetPixel (ximage2, x, y2) == fg ? '#' : ' '), stdout);
        fputc ('\n', stdout);
      }
    fputc ('\n', stdout);
#endif /* 0 */

    return ximage2;
  }
}
Пример #2
0
static void
pinit(ModeInfo *mi)
{
  /* int status; */
	glClearDepth(1.0);
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT0, GL_POSITION, position0);
	glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, position1);
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
	glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHT1);
	glEnable(GL_NORMALIZE);
	glCullFace(GL_BACK);

	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
	glShadeModel(GL_FLAT);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_CULL_FACE);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

#if 0
    clear_gl_error();
    status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
                               WoodTextureWidth, WoodTextureHeight,
                               GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
    if (status)
      {
        const char *s = (char *) gluErrorString (status);
        fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
                 progname, WoodTextureWidth, WoodTextureHeight,
                 (s ? s : "(unknown)"));
        exit (1);
      }
    check_gl_error("mipmapping");
#else
    {
      XImage *img = xpm_to_ximage (mi->dpy,
                                   mi->xgwa.visual,
                                   mi->xgwa.colormap,
                                   wood_texture);
	  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
                    img->width, img->height, 0,
                    GL_RGBA,
                    /* GL_UNSIGNED_BYTE, */
                    GL_UNSIGNED_INT_8_8_8_8_REV,
                    img->data);
      check_gl_error("texture");
      XDestroyImage (img);
    }
#endif

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
}
Пример #3
0
XBR_IMAGE *XbrGfxGIF(Display *display, unsigned char *data, int size, int html,
                     XColor *backcol, char **errmsg)
{
    register unsigned char  ch, ch1;
    register unsigned char *ptr, *ptr1;
    register int   i;
    unsigned char *raster,	/* The raster data stream, unblocked */
                  *image;	/* The image data */
    int BitOffset = 0,		/* Bit Offset of next code */
    Prefix[4096],               /* Prefix table used for decoding */
    Suffix[4096],               /* Suffix table used for decoding */
    OutCode[1025],              /* Hash table used by the decompressor */
    OutCount = 0,		/* Decompressor output 'stack count' */
    RWidth, RHeight,		/* screen dimensions */
    LeftOfs, TopOfs,		/* image offset */
    BitsPerPixel,		/* Bits per pixel, read from GIF header */
    ColorMapSize,		/* number of colors */
    Background,			/* background color */
    Transparent = 0,		/* Transparent background? */
    TransparentColour,		/* The colour that is transparent. */
    CodeSize,			/* Code size, read from GIF header */
    InitCodeSize,		/* Starting code size, used during Clear */
    Code,			/* Value returned by XbrGfxReadCode */
    MaxCode,			/* limiting value for current code size */
    ClearCode,			/* GIF clear code */
    EOFCode,			/* GIF end-of-information code */
    CurCode, OldCode, InCode,	/* Decompressor variables */
    FirstFree,			/* First free code, generated per GIF spec */
    FreeCode,			/* Decompressor, next free slot in hash table */
    FinChar,			/* Decompressor variable */
    BitMask,			/* AND mask for data size */
    ReadMask,			/* Code AND mask for current code size */
    DispCells,			/* Number of display cells */
    screen;                     /* Default screen of display */
    Colormap colormap;          /* The colour map the get colours from */
    XImage *theImage;		/* The image to build up */
    Visual *theVisual;          /* Screen visual type */
    XBR_IMAGE *retval;
    GC gc;

    DispCells = DisplayCells(display, DefaultScreen(display));
    colormap = DefaultColormap(display, DefaultScreen(display));
    theVisual = DefaultVisual(display, DefaultScreen(display));
    screen = DefaultScreen(display);

    XC = 0, YC = 0; Pass = 0; alloc = 0;

    /* Allocate memory for raster data */
    if((raster = (unsigned char *) malloc(size)) == NULL) {
        if(errmsg) *errmsg = "Out of memory!";
        return(NULL);
    }

    ptr = data;

    if(strncmp((char *)ptr, "GIF87a", 6) && strncmp((char *)ptr, "GIF89a", 6)) {
        if(errmsg) *errmsg = "Not a GIF image!";
        return(NULL);
    }
    ptr += 6;

    /* Get variables from the GIF screen descriptor */
    ch = NEXTBYTE;
    RWidth = ch + 0x100 * NEXTBYTE;
    ch = NEXTBYTE;
    RHeight = ch + 0x100 * NEXTBYTE;

    ch = NEXTBYTE;
    HasColormap = ((ch & COLORMAPMASK) ? True : False);

    BitsPerPixel = (ch & 7) + 1;
    numcols = ColorMapSize = 1 << BitsPerPixel;
    BitMask = ColorMapSize - 1;

    Background = NEXTBYTE;

    /* Supposed to be NULL */
    if(NEXTBYTE) {
        if(errmsg) *errmsg = "GIF image corrupt!";
        return(NULL);
    }

    /* Read in global colormap. */
    if(HasColormap) {
	for (i = 0; i < ColorMapSize; i++) {
	    Red[i] = NEXTBYTE;
	    Green[i] = NEXTBYTE;
	    Blue[i] = NEXTBYTE;
            used[i] = 0;
	}
        numused = 0;
    }
    else {
        if(!numcols) numcols=256;
        for (i=0; i<numcols; i++)
            cols[i] = (unsigned long) i;
    }

    /* Chomp extensions. */
    while((ch = NEXTBYTE) == GIF_EXTENSION) {
        if(NEXTBYTE == GIF_GFXBLOCK) {
	    ch = NEXTBYTE;	/* Block size */
	    Transparent = ((NEXTBYTE & GIF_TRANSMASK) ? True : False);
	    ptr += 2;
	    TransparentColour = NEXTBYTE;
	    ch = NEXTBYTE;
	} else {
	    ch = NEXTBYTE;
	    ptr += ch;
	    while((ch = NEXTBYTE) != GIF_BLOCKEND)
		ptr += ch;
	}
    }
    
    /* Check for image seperator */
    if (ch != IMAGESEP) {
        if(errmsg) *errmsg = "Corrupt GIF file: *no image separator*";
        return(NULL);
    }

    /* Now read in values from the image descriptor */
    ch = NEXTBYTE;
    LeftOfs = ch + 0x100 * NEXTBYTE;
    ch = NEXTBYTE;
    TopOfs = ch + 0x100 * NEXTBYTE;
    ch = NEXTBYTE;
    Width = ch + 0x100 * NEXTBYTE;
    ch = NEXTBYTE;
    Height = ch + 0x100 * NEXTBYTE;
    Interlace = ((NEXTBYTE & INTERLACEMASK) ? True : False);

/*
    xbrimage_resize(Width, Height);
    xbrimage_dimensions(Width, Height);
*/

    /* Note that I ignore the possible existence of a local color map.
     * I'm told there aren't many files around that use them, and the spec
     * says it's defined for future use.  This could lead to an error
     * reading some files. 
     */

    /* Start reading the raster data. First we get the intial code size
     * and compute decompressor constant values, based on this code size.
     */
    CodeSize = NEXTBYTE;
    ClearCode = (1 << CodeSize);
    EOFCode = ClearCode + 1;
    FreeCode = FirstFree = ClearCode + 2;

    /* The GIF spec has it that the code size is the code size used to
     * compute the above values is the code size given in the file, but the
     * code size used in compression/decompression is the code size given in
     * the file plus one. (thus the ++).
     */
    CodeSize++;
    InitCodeSize = CodeSize;
    MaxCode = (1 << CodeSize);
    ReadMask = MaxCode - 1;

    /* Read the raster data.  Here we just transpose it from the GIF array
     * to the raster array, turning it from a series of blocks into one long
     * data stream, which makes life much easier for XbrGfxReadCode().
     */
    ptr1 = raster;
    do {
	ch = ch1 = NEXTBYTE;
	while (ch--) *ptr1++ = NEXTBYTE;
	if ((raster - ptr1) > size) {
	    if(errmsg) *errmsg = "Corrupt GIF file\n*unblock*";
            return(NULL);
        }
    } while(ch1);


    /* Allocate the X image */
    image = (unsigned char *) malloc(Width*Height);
    if (image == NULL) {
        if(errmsg) *errmsg = "Not enough memory for Ximage!";
        return(NULL);
    }
    if(!html) {
        theImage = XCreateImage(display,theVisual,8,ZPixmap,0,(char *)image,
          Width, Height,8,Width);

        if(theImage == NULL) {
            if(errmsg) *errmsg = "Unable to create Ximage!";
             return(NULL);
       }
    }

    BytesPerScanline = Width;

    /* Decompress the file, continuing until you see the GIF EOF code.
       One obvious enhancement is to add checking for corrupt files here.
    */
    Code = XbrGfxReadCode(&BitOffset, raster, CodeSize, ReadMask);
    while (Code != EOFCode) {

        /* Clear code sets everything back to its initial value, then reads the
          immediately subsequent code as uncompressed data.
        */
	if (Code == ClearCode) {
	    CodeSize = InitCodeSize;
	    MaxCode = (1 << CodeSize);
	    ReadMask = MaxCode - 1;
	    FreeCode = FirstFree;
	    CurCode = OldCode = Code = XbrGfxReadCode(&BitOffset, raster,
              CodeSize, ReadMask);
	    FinChar = CurCode & BitMask;
	    XbrGfxAddtoPixel(FinChar, image);
	}
	else {

            /* If not a clear code, then must be data:save same as CurCode and
               InCode
            */
	    CurCode = InCode = Code;

            /* If greater or equal to FreeCode, not in the hash table yet;
               repeat the last character decoded
            */
	    if (CurCode >= FreeCode) {
		CurCode = OldCode;
		OutCode[OutCount++] = FinChar;
	    }

            /* Unless this code is raw data, pursue the chain pointed to by
              CurCode through the hash table to its end; each code in the chain
              puts its associated output code on the output queue.
            */
	    while (CurCode > BitMask) {
		if (OutCount > 1024) {
		    if(errmsg) *errmsg = "Corrupt GIF file!*OutCount*";
                    if(!html) XDestroyImage(theImage);
                    theImage = NULL;
                    return(NULL);
                    }
		OutCode[OutCount++] = Suffix[CurCode];
		CurCode = Prefix[CurCode];
	    }

            /* The last code in the chain is treated as raw data. */
	    FinChar = CurCode & BitMask;
	    OutCode[OutCount++] = FinChar;

            /* Now we put the data out to the Output routine.
               It's been stacked LIFO, so deal with it that way...
            */
            for (i = OutCount - 1; i >= 0; i--)
		XbrGfxAddtoPixel(OutCode[i], image);
	    OutCount = 0;

            /* Build the hash table on-the-fly. No table is stored in the
               file.
            */
	    Prefix[FreeCode] = OldCode;
	    Suffix[FreeCode] = FinChar;
	    OldCode = InCode;

            /* Point to the next slot in the table.  If we exceed the current
               MaxCode value, increment the code size unless it's already 12.
               If it is, do nothing: the next code decompressed better be CLEAR
            */
	    FreeCode++;
	    if (FreeCode >= MaxCode) {
		if (CodeSize < 12) {
		    CodeSize++;
		    MaxCode *= 2;
		    ReadMask = (1 << CodeSize) - 1;
		}
	    }
	}
	Code = XbrGfxReadCode(&BitOffset, raster, CodeSize, ReadMask);
    }

    free(raster);
/*
    xbrimage_colours(numused, ColorMapSize);
*/

    retval = XtNew(XBR_IMAGE);
    retval->size = size;
    retval->width = Width;
    retval->height = Height;
    retval->data = (char *)data;

    if(html) {
        retval->pixmap = (Pixmap)NULL;
        retval->num_colors = numcols;
        retval->reds = (int *) XtMalloc(sizeof(int)*numcols);
        retval->greens = (int *) XtMalloc(sizeof(int)*numcols);
        retval->blues = (int *) XtMalloc(sizeof(int)*numcols);
        for(i = 0; i < numcols; i++) {
            retval->reds[i] = Red[i] << 8;
            retval->greens[i] = Green[i] << 8;
            retval->blues[i] = Blue[i] << 8;
        }
	if(Transparent) {
	    retval->reds[TransparentColour] = backcol->red;
	    retval->greens[TransparentColour] = backcol->green;
	    retval->blues[TransparentColour] = backcol->blue;
	}
        retval->image_data = image;
        retval->npixels = 0;
    } else {
        retval->pixmap = XCreatePixmap(display, DefaultRootWindow(display),
          Width, Height, DefaultDepth(display, screen));
        retval->num_colors = numcols;
        retval->reds = NULL;
        retval->greens = NULL;
        retval->blues = NULL;
        retval->image_data = NULL;
        if(!XbrGfxGetColours(display, colormap,DispCells, image,backcol,Transparent,TransparentColour)) {
            if(errmsg) *errmsg = "Error allocating colours!";
            XDestroyImage(theImage);
            theImage = NULL;
            return(NULL);
        }

        for(i = 0; i < alloc; i++) {
            retval->pixels[i] = alloced[i];
        }
        retval->npixels = alloc-1;

        gc = XCreateGC(display, retval->pixmap,  0, NULL);
        XPutImage(display, retval->pixmap, gc, theImage, 0, 0, 0, 0, Width,
          Height);
        XFreeGC(display, gc);
        XDestroyImage(theImage);
    }

    theImage = NULL;

    return(retval);
}
Пример #4
0
void Xvars::destroy_image(XImage* image) {
  delete [] image->data;
  image->data = NULL;
  XDestroyImage(image);
}
Пример #5
0
FontInfoPtr
SuckGlyphsFromServer(Display * dpy, Font font)
{
  Pixmap offscreen;
  XFontStruct *fontinfo;
  XImage *image;
  GC xgc;
  XGCValues values;
  int numchars;
  int width, height, pixwidth;
  int i, j;
  XCharStruct *charinfo;
  XChar2b character;
  unsigned char *bitmapData;
  int x, y;
  int spanLength;
  int charWidth, charHeight, maxSpanLength;
  int grabList[MAX_GLYPHS_PER_GRAB];
  int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
  int numToGrab, thisglyph;
  FontInfoPtr myfontinfo;

  fontinfo = XQueryFont(dpy, font);
  if (!fontinfo)
    return NULL;

  numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
  if (numchars < 1)
    return NULL;

  myfontinfo = (FontInfoPtr) malloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerGlyphInfo));
  if (!myfontinfo)
    return NULL;

  myfontinfo->min_char = fontinfo->min_char_or_byte2;
  myfontinfo->max_char = fontinfo->max_char_or_byte2;
  myfontinfo->max_ascent = fontinfo->max_bounds.ascent;
  myfontinfo->max_descent = fontinfo->max_bounds.descent;

  width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing;
  height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent;

  maxSpanLength = (width + 7) / 8;
  /* Be careful determining the width of the pixmap; the X protocol allows
     pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
     max out at 2^15-1 (signed short size).  If the width is too large, we
     need to limit the glyphs per grab.  */
  if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
    glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
  }
  pixwidth = glyphsPerGrab * 8 * maxSpanLength;
  offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
    pixwidth, height, 1);

  values.font = font;
  values.background = 0;
  values.foreground = 0;
  xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values);

  XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
  XSetForeground(dpy, xgc, 1);

  numToGrab = 0;
  if (fontinfo->per_char == NULL) {
    charinfo = &(fontinfo->min_bounds);
    charWidth = charinfo->rbearing - charinfo->lbearing;
    charHeight = charinfo->ascent + charinfo->descent;
    spanLength = (charWidth + 7) / 8;
  }
  for (i = 0; i < numchars; i++) {
    if (fontinfo->per_char != NULL) {
      charinfo = &(fontinfo->per_char[i]);
      charWidth = charinfo->rbearing - charinfo->lbearing;
      charHeight = charinfo->ascent + charinfo->descent;
      if (charWidth == 0 || charHeight == 0) {
        /* Still must move raster pos even if empty character */
        myfontinfo->glyph[i].width = 0;
        myfontinfo->glyph[i].height = 0;
        myfontinfo->glyph[i].xoffset = 0;
        myfontinfo->glyph[i].yoffset = 0;
        myfontinfo->glyph[i].advance = charinfo->width;
        myfontinfo->glyph[i].bitmap = NULL;
        goto PossiblyDoGrab;
      }
    }
    grabList[numToGrab] = i;

    /* XXX is this right for large fonts? */
    character.byte2 = (i + fontinfo->min_char_or_byte2) & 255;
    character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8;

    /* XXX we could use XDrawImageString16 which would also paint the backing 

       rectangle but X server bugs in some scalable font rasterizers makes it 

       more effective to do XFillRectangles to clear the pixmap and
       XDrawImage16 for the text.  */
    XDrawString16(dpy, offscreen, xgc,
      -charinfo->lbearing + 8 * maxSpanLength * numToGrab,
      charinfo->ascent, &character, 1);

    numToGrab++;

  PossiblyDoGrab:

    if (numToGrab >= glyphsPerGrab || i == numchars - 1) {
      image = XGetImage(dpy, offscreen,
        0, 0, pixwidth, height, 1, XYPixmap);
      for (j = 0; j < numToGrab; j++) {
        thisglyph = grabList[j];
        if (fontinfo->per_char != NULL) {
          charinfo = &(fontinfo->per_char[thisglyph]);
          charWidth = charinfo->rbearing - charinfo->lbearing;
          charHeight = charinfo->ascent + charinfo->descent;
          spanLength = (charWidth + 7) / 8;
        }
        bitmapData = calloc(height * spanLength, sizeof(char));
        if (!bitmapData)
          goto FreeFontAndReturn;
        DEBUG_GLYPH4("index %d, glyph %d (%d by %d)\n",
          j, thisglyph + fontinfo->min_char_or_byte2, charWidth, charHeight);
        for (y = 0; y < charHeight; y++) {
          for (x = 0; x < charWidth; x++) {
            /* XXX The algorithm used to suck across the font ensures that
               each glyph begins on a byte boundary.  In theory this would
               make it convienent to copy the glyph into a byte oriented
               bitmap.  We actually use the XGetPixel function to extract
               each pixel from the image which is not that efficient.  We
               could either do tighter packing in the pixmap or more
               efficient extraction from the image.  Oh well.  */
            if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) {
              DEBUG_GLYPH("x");
              bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
            } else {
              DEBUG_GLYPH(" ");
            }
          }
          DEBUG_GLYPH("\n");
        }
        myfontinfo->glyph[thisglyph].width = charWidth;
        myfontinfo->glyph[thisglyph].height = charHeight;
        myfontinfo->glyph[thisglyph].xoffset = charinfo->lbearing;
        myfontinfo->glyph[thisglyph].yoffset = -charinfo->descent;
        myfontinfo->glyph[thisglyph].advance = charinfo->width;
        myfontinfo->glyph[thisglyph].bitmap = bitmapData;
      }
      XDestroyImage(image);
      numToGrab = 0;
      /* do we need to clear the offscreen pixmap to get more? */
      if (i < numchars - 1) {
        XSetForeground(dpy, xgc, 0);
        XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
        XSetForeground(dpy, xgc, 1);
      }
    }
  }
  XFreeGC(dpy, xgc);
  XFreePixmap(dpy, offscreen);
  return myfontinfo;

FreeFontAndReturn:
  XDestroyImage(image);
  XFreeGC(dpy, xgc);
  XFreePixmap(dpy, offscreen);
  for (j = i - 1; j >= 0; j--) {
    if (myfontinfo->glyph[j].bitmap)
      free(myfontinfo->glyph[j].bitmap);
  }
  free(myfontinfo);
  return NULL;
}
Пример #6
0
gint
nsFreeTypeXImage::DrawString(nsRenderingContextGTK* aContext,
                            nsDrawingSurfaceGTK* aSurface, nscoord aX,
                            nscoord aY, const PRUnichar* aString,
                            PRUint32 aLength)
{

#if DEBUG_SHOW_GLYPH_BOX
  PRUint32 x, y;
  // grey shows image size
  // red shows character cells
  // green box shows text ink
#endif

  if (aLength < 1) {
    return 0;
  }

  // get the face/size from the FreeType cache
  FT_Face face = getFTFace();
  NS_ASSERTION(face, "failed to get face/size");
  if (!face)
    return 0;

  nsresult rslt;
  PRInt32 leftBearing, rightBearing, ascent, descent, width;
  rslt = doGetBoundingMetrics(aString, aLength, &leftBearing, &rightBearing,
                              &ascent, &descent, &width);
  if (NS_FAILED(rslt))
    return 0;

  // make sure we bring down enough background for blending
  rightBearing = PR_MAX(rightBearing, width+1);

  // offset in the ximage to the x origin
  PRInt32 x_origin = PR_MAX(0, -leftBearing);
  // offset in the ximage to the x origin
  PRInt32 y_origin = ascent;
  PRInt32 x_pos = x_origin;

  int image_width  = x_origin + rightBearing;
  int image_height = y_origin + PR_MAX(descent, 0);
  if ((image_width<=0) || (image_height<=0)) {
    // if we do not have any pixels then no point in trying to draw
    // eg: the space char has 0 height
    NS_ASSERTION(width>=0, "Negative width");
    return width;
  }
  Display *dpy = GDK_DISPLAY();
  Drawable win = GDK_WINDOW_XWINDOW(aSurface->GetDrawable());
  GC gc = GDK_GC_XGC(aContext->GetGC());
  XGCValues values;
  if (!XGetGCValues(dpy, gc, GCForeground, &values)) {
    NS_ERROR("failed to get foreground pixel");
    return 0;
  }
  nscolor color = nsX11AlphaBlend::PixelToNSColor(values.foreground);

#if DEBUG_SHOW_GLYPH_BOX
  // show X/Y origin
  XDrawLine(dpy, win, DefaultGC(dpy, 0), aX-2, aY, aX+2, aY);
  XDrawLine(dpy, win, DefaultGC(dpy, 0), aX, aY-2, aX, aY+2);
  // show width
  XDrawLine(dpy, win, DefaultGC(dpy, 0), aX-x_origin,  aY-y_origin-2,
                                         aX+rightBearing, aY-y_origin-2);
#endif

  //
  // Get the background
  //
  XImage *sub_image = nsX11AlphaBlend::GetBackground(dpy, DefaultScreen(dpy),
                                 win, aX-x_origin, aY-y_origin,
                                 image_width, image_height);
  if (sub_image==nsnull) {
#ifdef DEBUG
    int screen = DefaultScreen(dpy);
    // complain if the requested area is not completely off screen
    int win_width = DisplayWidth(dpy, screen);
    int win_height = DisplayHeight(dpy, screen);
    if (((int)(aX-leftBearing+image_width) > 0)  // not hidden to left
        && ((int)(aX-leftBearing) < win_width)   // not hidden to right
        && ((int)(aY-ascent+image_height) > 0)// not hidden to top
        && ((int)(aY-ascent) < win_height))   // not hidden to bottom
    {
      NS_ASSERTION(sub_image, "failed to get the image");
    }
#endif
    return 0;
  }

#if DEBUG_SHOW_GLYPH_BOX
  DEBUG_AADRAWBOX(sub_image,0,0,image_width,image_height,0,0,0,255/4);
  nscolor black NS_RGB(0,255,0);
  blendPixel blendPixelFunc = nsX11AlphaBlend::GetBlendPixel();
  // x origin
  for (x=0; x<(unsigned int)image_height; x++)
    if (x%4==0) (*blendPixelFunc)(sub_image, x_origin, x, black, 255/2);
  // y origin
  for (y=0; y<(unsigned int)image_width; y++)
    if (y%4==0) (*blendPixelFunc)(sub_image, y, ascent-1, black, 255/2);
#endif

  FTC_Image_Cache icache;
  mFt2->GetImageCache(&icache);
  if (!icache)
    return 0;

  //
  // Get aa glyphs and blend with background
  //
  blendGlyph blendGlyph = nsX11AlphaBlend::GetBlendGlyph();
  PRUint32 i, extraSurrogateLength;
  for (i=0; i<aLength; i+=1+extraSurrogateLength) {
    FT_UInt glyph_index;
    FT_Glyph glyph;
    nsresult rv;
    FT_BBox glyph_bbox;
    FT_ULong code_point = aString[i];
    extraSurrogateLength = 0;

    if(i<aLength-1 && IS_HIGH_SURROGATE(code_point) && IS_LOW_SURROGATE(aString[i+1])) {
      // if surrogate, make UCS4 code point from high aString[i] surrogate and
      // low surrogate aString[i+1]
      code_point = SURROGATE_TO_UCS4(code_point, aString[i+1]);

      // skip aString[i+1], it is already used as low surrogate
      extraSurrogateLength = 1;
    }

    mFt2->GetCharIndex(face, code_point, &glyph_index);
    if (glyph_index) {
      rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph);
    }
    if ((glyph_index) && (NS_SUCCEEDED(rv))) {
      mFt2->GlyphGetCBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox);
    }
    else {
      // draw an empty box for the missing glyphs
      GetFallbackGlyphMetrics(&glyph_bbox, face);
      int x, y, w = glyph_bbox.xMax, h = glyph_bbox.yMax;
      for (x=1; x<w; x++) {
        XPutPixel(sub_image, x_pos+x, ascent-1,   values.foreground);
        XPutPixel(sub_image, x_pos+x, ascent-h, values.foreground);
      }
      for (y=1; y<h; y++) {
        XPutPixel(sub_image, x_pos+1, ascent-y, values.foreground);
        XPutPixel(sub_image, x_pos+w-1, ascent-y, values.foreground);
        x = (y*(w-2))/h;
        XPutPixel(sub_image, x_pos+x+1, ascent-y,   values.foreground);
      }
      x_pos += w + 1;
      continue;
    }

    FT_BitmapGlyph slot = (FT_BitmapGlyph)glyph;
    nsAntiAliasedGlyph aaglyph(glyph_bbox.xMax-glyph_bbox.xMin,
                               glyph_bbox.yMax-glyph_bbox.yMin, 0);
    PRUint8 buf[IMAGE_BUFFER_SIZE]; // try to use the stack for data
    if (!aaglyph.WrapFreeType(&glyph_bbox, slot, buf, IMAGE_BUFFER_SIZE)) {
      NS_ERROR("failed to wrap freetype image");
      XDestroyImage(sub_image);
      return 0;
    }

    //
    // blend the aa-glyph onto the background
    //
    NS_ASSERTION(ascent>=glyph_bbox.yMax,"glyph too tall");
    NS_ASSERTION(x_pos>=-aaglyph.GetLBearing(),"glyph extends too far to left");

#if DEBUG_SHOW_GLYPH_BOX
  // draw box around part of glyph that extends to the left
  // of the main area (negative LBearing)
  if (aaglyph.GetLBearing() < 0) {
    DEBUG_AADRAWBOX(sub_image, x_pos + aaglyph.GetLBearing(),
                    ascent-glyph_bbox.yMax,
                    -aaglyph.GetLBearing(), glyph_bbox.yMax, 255,0,0, 255/4);
  }
  // draw box around main glyph area
  DEBUG_AADRAWBOX(sub_image, x_pos, ascent-glyph_bbox.yMax,
                  aaglyph.GetAdvance(), glyph_bbox.yMax, 0,255,0, 255/4);
  // draw box around part of glyph that extends to the right
  // of the main area (negative LBearing)
  if (aaglyph.GetRBearing() > (int)aaglyph.GetAdvance()) {
    DEBUG_AADRAWBOX(sub_image, x_pos + aaglyph.GetAdvance(),
                    ascent-glyph_bbox.yMax,
                    aaglyph.GetRBearing()-aaglyph.GetAdvance(),
                    glyph_bbox.yMax, 0,0,255, 255/4);
  }
#endif
    (*blendGlyph)(sub_image, &aaglyph, sLinearWeightTable, color,
                  x_pos + aaglyph.GetLBearing(), ascent-glyph_bbox.yMax);

    x_pos += aaglyph.GetAdvance();
  }

  //
  // Send it to the display
  //
  XPutImage(dpy, win, gc, sub_image, 0, 0, aX-x_origin , aY-ascent,
            image_width, image_height);
  XDestroyImage(sub_image);

  return width;
}
Пример #7
0
/* translate a colorset spec into a colorset structure */
void parse_colorset(int n, char *line)
{
	int i;
	int w;
	int h;
	int tmp;
	int percent;
	colorset_t *cs;
	char *optstring;
	char *args;
	char *option;
	char *tmp_str;
	char *fg = NULL;
	char *bg = NULL;
	char *hi = NULL;
	char *sh = NULL;
	char *fgsh = NULL;
	char *tint = NULL;
	char *fg_tint = NULL;
	char *bg_tint = NULL;
	char *icon_tint = NULL;
	Bool have_pixels_changed = False;
	Bool has_icon_pixels_changed = False;
	Bool has_fg_changed = False;
	Bool has_bg_changed = False;
	Bool has_sh_changed = False;
	Bool has_hi_changed = False;
	Bool has_fgsh_changed = False;
	Bool has_fg_alpha_changed = False;
	Bool has_tint_changed = False;
	Bool has_fg_tint_changed = False;
	Bool has_bg_tint_changed = False;
	Bool has_icon_tint_changed = False;
	Bool has_pixmap_changed = False;
	Bool has_shape_changed = False;
	Bool has_image_alpha_changed = False;
	Bool pixmap_is_a_bitmap = False;
	Bool do_reload_pixmap = False;
	Bool is_server_grabbed = False;
	XColor color;
	XGCValues xgcv;
	static char *name = "parse_colorset";
	Window win = Scr.NoFocusWin;
	static GC gc = None;

	/* initialize statics */
	if (gc == None)
	{
		gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv);
	}

	/* make sure it exists and has sensible contents */
	alloc_colorset(n);
	cs = &Colorset[n];

	/*** Parse the options ***/
	while (line && *line)
	{
		/* Read next option specification delimited by a comma or \0.
		 */
		line = GetQuotedString(
			line, &optstring, ",", NULL, NULL, NULL);
		if (!optstring)
			break;
		args = GetNextToken(optstring, &option);
		if (!option)
		{
			free(optstring);
			break;
		}

		switch((i = GetTokenIndex(option, csetopts, 0, NULL)))
		{
		case 0: /* Foreground */
		case 1: /* Fore */
		case 2: /* fg */
			get_simple_color(
				args, &fg, cs, FG_SUPPLIED, FG_CONTRAST,
				"contrast");
			has_fg_changed = True;
			break;
		case 3: /* Background */
		case 4: /* Back */
		case 5: /* bg */
			get_simple_color(
				args, &bg, cs, BG_SUPPLIED, BG_AVERAGE,
				"average");
			has_bg_changed = True;
			break;
		case 6: /* Hilight */
		case 7: /* Hilite */
		case 8: /* hi */
			get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL);
			has_hi_changed = True;
			break;
		case 9: /* Shadow */
		case 10: /* Shade */
		case 11: /* sh */
			get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL);
			has_sh_changed = True;
			break;
		case 12: /* fgsh */
			get_simple_color(
				args, &fgsh, cs, FGSH_SUPPLIED, 0,NULL);
			has_fgsh_changed = True;
			break;
		case 13: /* fg_alpha */
		case 14: /* fgAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->fg_alpha_percent)
			{
				cs->fg_alpha_percent = tmp;
				has_fg_alpha_changed = True;
			}
			break;
		case 15: /* TiledPixmap */
		case 16: /* Pixmap */
		case 17: /* AspectPixmap */
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			tmp_str = PeekToken(args, &args);
			if (tmp_str)
			{
				CopyString(&cs->pixmap_args, tmp_str);
				do_reload_pixmap = True;
				cs->gradient_type = 0;
				/* set the flags */
				if (csetopts[i][0] == 'T')
				{
					cs->pixmap_type = PIXMAP_TILED;
				}
				else if (csetopts[i][0] == 'A')
				{
					cs->pixmap_type = PIXMAP_STRETCH_ASPECT;
				}
				else
				{
					cs->pixmap_type = PIXMAP_STRETCH;
				}
			}
			/* the pixmap is build later */
			break;
		case 18: /* Shape */
		case 19: /* TiledShape */
		case 20: /* AspectShape */
			parse_shape(win, cs, i, args, &has_shape_changed);
			break;
		case 21: /* Plain */
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			break;
		case 22: /* NoShape */
			has_shape_changed = True;
			if (cs->shape_mask)
			{
				add_to_junk(cs->shape_mask);
				cs->shape_mask = None;
			}
			break;
		case 23: /* Transparent */

			/* This is only allowable when the root depth == fvwm
			 * visual depth otherwise bad match errors happen,
			 * it may be even more restrictive but my tests (on
			 * exceed 6.2) show that only == depth is necessary */

			if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
			{
				fvwm_msg(
					ERR, name, "can't do Transparent "
					"when root_depth!=fvwm_depth");
				break;
			}
			has_pixmap_changed = True;
			free_colorset_background(cs, True);
			cs->pixmap = ParentRelative;
			cs->pixmap_type = PIXMAP_STRETCH;
			break;
		case 24: /* RootTransparent */
			if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy))))
			{
				fvwm_msg(
					ERR, name, "can't do RootTransparent "
					"when root_depth!=fvwm_depth");
				break;
			}
			free_colorset_background(cs, True);
			has_pixmap_changed = True;
			cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE;
			do_reload_pixmap = True;
			tmp_str = PeekToken(args, &args);
			if (StrEquals(tmp_str, "buffer"))
			{
				cs->allows_buffered_transparency = True;
			}
			else
			{
				cs->allows_buffered_transparency = False;
			}
			cs->is_maybe_root_transparent = True;
			break;
		case 25: /* Tint */
		case 26: /* PixmapTint */
		case 27: /* ImageTint */
		case 28: /* TintMask */
			parse_simple_tint(
				cs, args, &tint, TINT_SUPPLIED,
				&has_tint_changed, &percent, "tint");
			if (has_tint_changed)
			{
				cs->tint_percent = percent;
			}
			break;
		case 29: /* NoTint */
			has_tint_changed = True;
			cs->tint_percent = 0;
			cs->color_flags &= ~TINT_SUPPLIED;
			break;
		case 30: /* fgTint */
			parse_simple_tint(
				cs, args, &fg_tint, FG_TINT_SUPPLIED,
				&has_fg_tint_changed, &percent, "fgTint");
			if (has_fg_tint_changed)
			{
				cs->fg_tint_percent = percent;
			}
			break;
		case 31: /* bgTint */
			parse_simple_tint(
				cs, args, &bg_tint, BG_TINT_SUPPLIED,
				&has_bg_tint_changed, &percent, "bgTint");
			if (has_bg_tint_changed)
			{
				cs->bg_tint_percent = percent;
			}
			break;
		case 32: /* dither */
			if (cs->pixmap_args || cs->gradient_args)
			{
				has_pixmap_changed = True;
				do_reload_pixmap = True;
			}
			cs->dither = True;
			break;
		case 33: /* nodither */
			if (cs->pixmap_args || cs->gradient_args)
			{
				has_pixmap_changed = True;
				do_reload_pixmap = True;
			}
			cs->dither = False;
			break;
		case 34: /* Alpha */
		case 35: /* PixmapAlpha */
		case 36: /* ImageAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->image_alpha_percent)
			{
				has_image_alpha_changed = True;
				cs->image_alpha_percent = tmp;
			}
			break;
                /* dither icon is not dynamic (yet) maybe a bad opt: default
		 * to False ? */
		case 37: /* ditherIcon */
			cs->do_dither_icon = True;
			break;
		case 38: /* DoNotDitherIcon */
			cs->do_dither_icon = False;
			break;
		case 39: /* IconTint */
			parse_simple_tint(
				cs, args, &icon_tint, ICON_TINT_SUPPLIED,
				&has_icon_tint_changed, &percent, "IconTint");
			if (has_icon_tint_changed)
			{
				cs->icon_tint_percent = percent;
				has_icon_pixels_changed = True;
			}
			break;
		case 40: /* NoIconTint */
			has_icon_tint_changed = True;
			if (cs->icon_tint_percent != 0)
			{
				has_icon_pixels_changed = True;
			}
			cs->icon_tint_percent = 0;
			break;
		case 41: /* IconAlpha */
			if (GetIntegerArguments(args, NULL, &tmp, 1))
			{
				if (tmp > 100)
					tmp = 100;
				else if (tmp < 0)
					tmp = 0;
			}
			else
			{
				tmp = 100;
			}
			if (tmp != cs->icon_alpha_percent)
			{
				has_icon_pixels_changed = True;
				cs->icon_alpha_percent = tmp;
			}
			break;
		default:
			/* test for ?Gradient */
			if (option[0] && StrEquals(&option[1], "Gradient"))
			{
				cs->gradient_type = toupper(option[0]);
				if (!IsGradientTypeSupported(cs->gradient_type))
					break;
				has_pixmap_changed = True;
				free_colorset_background(cs, True);
				CopyString(&cs->gradient_args, args);
				do_reload_pixmap = True;
				if (cs->gradient_type == V_GRADIENT)
				{
					cs->pixmap_type = PIXMAP_STRETCH_Y;
				}
				else if (cs->gradient_type == H_GRADIENT)
					cs->pixmap_type = PIXMAP_STRETCH_X;
				else
					cs->pixmap_type = PIXMAP_STRETCH;
			}
			else
			{
				fvwm_msg(
					WARN, name, "bad colorset pixmap "
					"specifier %s %s", option, line);
			}
			break;
		} /* switch */

		if (option)
		{
			free(option);
			option = NULL;
		}
		free(optstring);
		optstring = NULL;
	} /* while (line && *line) */

	/*
	 * ---------- change the "pixmap" tint colour ----------
	 */
	if (has_tint_changed)
	{
		/* user specified colour */
		if (tint != NULL)
		{
			Pixel old_tint = cs->tint;
			PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True);
			cs->tint = GetColor(tint);
			if (old_tint != cs->tint)
			{
				have_pixels_changed = True;
			}
		}
		else if (tint == NULL)
		{
			/* default */
			Pixel old_tint = cs->tint;
			PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True);
			cs->tint = GetColor(black);
			if (old_tint != cs->tint)
			{
				have_pixels_changed = True;
			}
		}
	}

	/*
	 * reload the gradient if the tint or the alpha have changed.
	 * Do this too if we need to recompute the bg average and the
	 * gradient is tinted (perforemence issue).
	 */
	if ((has_tint_changed || has_image_alpha_changed ||
	     (has_bg_changed && (cs->color_flags & BG_AVERAGE) &&
	      cs->tint_percent > 0)) && cs->gradient_args)
	{
		do_reload_pixmap = True;
	}

	/*
	 * reset the pixmap if the tint or the alpha has changed
	 */
	if (!do_reload_pixmap &&
	    (has_tint_changed || has_image_alpha_changed  ||
	     (has_bg_changed && cs->alpha_pixmap != None)))
	{
		if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE ||
		    cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN)
		{
			do_reload_pixmap = True;
		}
		else if (cs->picture != NULL && cs->pixmap)
		{
			XSetClipMask(dpy, gc, cs->picture->mask);
			reset_cs_pixmap(cs, gc);
			XSetClipMask(dpy, gc, None);
			has_pixmap_changed = True;
		}
	}

	/*
	 * (re)build the pixmap or the gradient
	 */
	if (do_reload_pixmap)
	{
		free_colorset_background(cs, False);
		has_pixmap_changed = True;
		if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE ||
		    cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN)
		{
			cs->pixmap_type = 0;
			if (root_pic.pixmap)
			{
				cs->pixmap = root_pic.pixmap;
				cs->width = root_pic.width;
				cs->height = root_pic.height;
				cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE;
#if 0
				fprintf(stderr,"Cset %i LoadRoot 0x%lx\n",
					n, cs->pixmap);
#endif
			}
		}
		else if (cs->pixmap_args)
		{
			parse_pixmap(win, gc, cs, &pixmap_is_a_bitmap);
		}
		else if (cs->gradient_args)
		{
			cs->pixmap = CreateGradientPixmapFromString(
				dpy, win, gc, cs->gradient_type,
				cs->gradient_args, &w, &h, &cs->pixels,
				&cs->nalloc_pixels, cs->dither);
			cs->width = w;
			cs->height = h;
		}
		has_pixmap_changed = True;
	}

	if (cs->picture != NULL && cs->picture->depth != Pdepth)
	{
		pixmap_is_a_bitmap = True;
	}

	/*
	 * ---------- change the background colour ----------
	 */
	if (has_bg_changed ||
	    (has_pixmap_changed && (cs->color_flags & BG_AVERAGE) &&
	     cs->pixmap != None &&
	     cs->pixmap != ParentRelative &&
	     !pixmap_is_a_bitmap))
	{
		Bool do_set_default_background = False;
		Pixmap average_pix = None;

		if (cs->color_flags & BG_AVERAGE)
		{
			if (cs->picture != NULL && cs->picture->picture != None)
			{
				average_pix = cs->picture->picture;
			}
			else if (cs->pixmap != ParentRelative)
			{
				average_pix = cs->pixmap;
			}

			if (average_pix == root_pic.pixmap)
			{
				int w;
				int h;
				XID dummy;

				MyXGrabServer(dpy);
				is_server_grabbed = True;
				if (!XGetGeometry(
				    dpy, average_pix, &dummy,
				    (int *)&dummy, (int *)&dummy,
				    (unsigned int *)&w, (unsigned int *)&h,
				    (unsigned int *)&dummy,
				    (unsigned int *)&dummy))
				{
					average_pix = None;
				}
				else
				{
					if (w != cs->width || h != cs->height)
					{
						average_pix = None;
					}
				}
				if (average_pix == None)
				{
					MyXUngrabServer(dpy);
					is_server_grabbed = False;
				}
			}
		}

		/* note: no average for bitmap */
		if ((cs->color_flags & BG_AVERAGE) && average_pix)
		{
			/* calculate average background color */
			XColor *colors;
			XImage *image;
			XImage *mask_image = None;
			unsigned int i, j, k = 0;
			unsigned long red = 0, blue = 0, green = 0;
			unsigned long tred, tblue, tgreen;
			double dred = 0.0, dblue = 0.0, dgreen = 0.0;

			has_bg_changed = True;
			/* create an array to store all the pixmap colors in */
			/* Note: this may allocate a lot of memory:
			 * cs->width * cs->height * 12 and then the rest of the
			 * procedure can take a lot of times */
			colors = (XColor *)safemalloc(
				cs->width * cs->height * sizeof(XColor));
			/* get the pixmap and mask into an image */
			image = XGetImage(
				dpy, average_pix, 0, 0, cs->width, cs->height,
				AllPlanes, ZPixmap);
			if (cs->mask != None)
			{
				mask_image = XGetImage(
					dpy, cs->mask, 0, 0, cs->width,
					cs->height, AllPlanes, ZPixmap);
			}
			if (is_server_grabbed == True)
			{
				MyXUngrabServer(dpy);
			}
			if (image != None && mask_image != None)
			{
				/* only fetch the pixels that are not masked
				 * out */
				for (i = 0; i < cs->width; i++)
				{
					for (j = 0; j < cs->height; j++)
					{
						if (
							cs->mask == None ||
							XGetPixel(
								mask_image, i,
								j) == 0)
						{
							colors[k++].pixel =
								XGetPixel(
									image,
									i, j);
						}
					}
				}
			}
			if (image != None)
			{
				XDestroyImage(image);
			}
			if (mask_image != None)
			{
				XDestroyImage(mask_image);
			}
			if (k == 0)
			{
				do_set_default_background = True;
			}
			else
			{
				/* look them all up, XQueryColors() can't
				 * handle more than 256 */
				for (i = 0; i < k; i += 256)
				{
					XQueryColors(
						dpy, Pcmap, &colors[i],
						min(k - i, 256));
				}
				/* calculate average, add overflows in a double
				 * .red is short, red is long */
				for (i = 0; i < k; i++)
				{
					tred = red;
					red += colors[i].red;
					if (red < tred)
					{
						dred += (double)tred;
						red = colors[i].red;
					}
					tgreen = green;
					green += colors[i].green;
					if (green < tgreen)
					{
						dgreen += (double)tgreen;
						green = colors[i].green;
					}
					tblue = blue;
					blue += colors[i].blue;
					if (blue < tblue)
					{
						dblue += (double)tblue;
						blue = colors[i].blue;
					}
				}
				dred += red;
				dgreen += green;
				dblue += blue;
				/* get it */
				color.red = dred / k;
				color.green = dgreen / k;
				color.blue = dblue / k;
				{
					Pixel old_bg = cs->bg;

					PictureFreeColors(
						dpy, Pcmap, &cs->bg, 1, 0,
						True);
					PictureAllocColor(
						dpy, Pcmap, &color, True);
					cs->bg = color.pixel;
					if (old_bg != cs->bg)
					{
						have_pixels_changed = True;
					}
				}
			}
			free(colors);
		} /* average */
		else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL)
		{
			/* user specified colour */
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetColor(bg);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (bg == NULL && has_bg_changed)
		{
			/* default */
			do_set_default_background = True;
		} /* default */
		if (do_set_default_background)
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetColor(white);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
			}
			has_bg_changed = True;
		}

		if (has_bg_changed)
		{
			/* save the bg color for tinting */
			cs->bg_saved = cs->bg;
		}
	} /* has_bg_changed */


	/*
	 * ---------- setup the bg tint colour ----------
	 */
	if (has_bg_tint_changed && cs->bg_tint_percent > 0 && bg_tint != NULL)
	{
		PictureFreeColors(dpy, Pcmap, &cs->bg_tint, 1, 0, True);
		cs->bg_tint = GetColor(bg_tint);
	}

	/*
	 * ---------- tint the bg colour ----------
	 */
	if (has_bg_tint_changed || (has_bg_changed && cs->bg_tint_percent > 0))
	{
		if (cs->bg_tint_percent == 0)
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = cs->bg_saved;
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
				has_bg_changed = True;
			}
		}
		else
		{
			Pixel old_bg = cs->bg;

			PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True);
			cs->bg = GetTintedPixel(
				cs->bg_saved, cs->bg_tint, cs->bg_tint_percent);
			if (old_bg != cs->bg)
			{
				have_pixels_changed = True;
				has_bg_changed = True;
			}
		}
	}

	/*
	 * ---------- setup the fg tint colour ----------
	 */
	if (has_fg_tint_changed && cs->fg_tint_percent > 0 && fg_tint != NULL)
	{
		PictureFreeColors(dpy, Pcmap, &cs->fg_tint, 1, 0, True);
		cs->fg_tint = GetColor(fg_tint);
	}

	/*
	 * ---------- change the foreground colour ----------
	 */
	if (has_fg_changed ||
	    (has_bg_changed && (cs->color_flags & FG_CONTRAST)))
	{
		if (cs->color_flags & FG_CONTRAST)
		{
			Pixel old_fg = cs->fg;

			/* calculate contrasting foreground color */
			color.pixel = cs->bg;
			XQueryColor(dpy, Pcmap, &color);
			color.red = (color.red > 32767) ? 0 : 65535;
			color.green = (color.green > 32767) ? 0 : 65535;
			color.blue = (color.blue > 32767) ? 0 : 65535;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			PictureAllocColor(dpy, Pcmap, &color, True);
			cs->fg = color.pixel;
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		} /* contrast */
		else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL)
		{
			/* user specified colour */
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetColor(fg);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		} /* user specified */
		else if (fg == NULL)
		{
			/* default */
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetColor(black);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}

		/* save the fg color for tinting */
		cs->fg_saved = cs->fg;

	} /* has_fg_changed */

	/*
	 * ---------- tint the foreground colour ----------
	 */
	if (has_fg_tint_changed || (has_fg_changed && cs->fg_tint_percent > 0))
	{
		if (cs->fg_tint_percent == 0)
		{

			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = cs->fg_saved;
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}
		else
		{
			Pixel old_fg = cs->fg;

			PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True);
			cs->fg = GetTintedPixel(
				cs->fg_saved, cs->fg_tint,
				cs->fg_tint_percent);
			if (old_fg != cs->fg)
			{
				have_pixels_changed = True;
				has_fg_changed = 1;
			}
		}
	}


	/*
	 * ---------- change the hilight colour ----------
	 */
	if (has_hi_changed ||
	    (has_bg_changed && !(cs->color_flags & HI_SUPPLIED)))
	{
		has_hi_changed = 1;
		if ((cs->color_flags & HI_SUPPLIED) && hi != NULL)
		{
			/* user specified colour */
			Pixel old_hilite = cs->hilite;

			PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True);
			cs->hilite = GetColor(hi);
			if (old_hilite != cs->hilite)
			{
					have_pixels_changed = True;
			}
		} /* user specified */
		else if (hi == NULL)
		{
			Pixel old_hilite = cs->hilite;

			PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True);
			cs->hilite = GetHilite(cs->bg);
			if (old_hilite != cs->hilite)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_hi_changed */

	/*
	 * ---------- change the shadow colour ----------
	 */
	if (has_sh_changed ||
	    (has_bg_changed && !(cs->color_flags & SH_SUPPLIED)))
	{
		has_sh_changed = 1;
		if ((cs->color_flags & SH_SUPPLIED) && sh != NULL)
		{
			/* user specified colour */
			Pixel old_shadow = cs->shadow;

			PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True);
			cs->shadow = GetColor(sh);
			if (old_shadow != cs->shadow)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (sh == NULL)
		{
			Pixel old_shadow = cs->shadow;

			PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True);
			cs->shadow = GetShadow(cs->bg);
			if (old_shadow != cs->shadow)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_sh_changed */

	/*
	 * ---------- change the shadow foreground colour ----------
	 */
	if (has_fgsh_changed ||
	    ((has_fg_changed || has_bg_changed) &&
	     !(cs->color_flags & FGSH_SUPPLIED)))
	{
		has_fgsh_changed = 1;
		if ((cs->color_flags & FGSH_SUPPLIED) && fgsh != NULL)
		{
			/* user specified colour */
			Pixel old_fgsh = cs->fgsh;

			PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True);
			cs->fgsh = GetColor(fgsh);
			if (old_fgsh != cs->fgsh)
			{
				have_pixels_changed = True;
			}
		} /* user specified */
		else if (fgsh == NULL)
		{
			Pixel old_fgsh = cs->fgsh;

			PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True);
			cs->fgsh = GetForeShadow(cs->fg, cs->bg);
			if (old_fgsh != cs->fgsh)
			{
				have_pixels_changed = True;
			}
		}
	} /* has_fgsh_changed */

	/*
	 * ------- the pixmap is a bitmap: create here cs->pixmap -------
	 */
	if (cs->picture != None && pixmap_is_a_bitmap &&
	    (has_pixmap_changed || has_bg_changed))
	{
		cs->pixmap = XCreatePixmap(
			dpy, win, cs->width, cs->height, Pdepth);
		XSetBackground(dpy, gc, cs->bg);
		XSetForeground(dpy, gc, cs->fg);
		reset_cs_pixmap(cs, gc);
	}

	/*
	 * ------- change the masked out parts of the background pixmap -------
	 */
	if (cs->pixmap != None && cs->pixmap != ParentRelative &&
	    (!CSETS_IS_TRANSPARENT_ROOT(cs)||
	     cs->allows_buffered_transparency) &&
	    (cs->mask != None || cs->alpha_pixmap != None ||
	     cs->image_alpha_percent < 100 || cs->tint_percent > 0) &&
	    (has_pixmap_changed || has_bg_changed || has_image_alpha_changed
	     || has_tint_changed))
	{
		/* Now that we know the background colour we can update the
		 * pixmap background. */
		FvwmRenderAttributes fra;
		Pixmap temp, mask, alpha;

		memset(&fra, 0, sizeof(fra));
		temp = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth);
		if (cs->picture != NULL)
		{
			mask = cs->picture->mask;
			alpha = cs->picture->alpha;
		}
		else
		{
			mask = None;
			alpha = None;
		}
		XSetForeground(dpy, gc, cs->bg);
		XFillRectangle(
			dpy, temp, gc, 0, 0, cs->width, cs->height);

		fra.mask = FRAM_HAVE_ADDED_ALPHA | FRAM_HAVE_TINT;
		fra.added_alpha_percent = cs->image_alpha_percent;
		fra.tint = cs->tint;
		fra.tint_percent = cs->tint_percent;
		PGraphicsRenderPixmaps(
			dpy, win, cs->pixmap, mask, alpha, Pdepth, &fra,
			temp, gc, Scr.MonoGC, Scr.AlphaGC,
			0, 0, cs->width, cs->height,
			0, 0, cs->width, cs->height, False);
		if (cs->pixmap != root_pic.pixmap)
		{
			add_to_junk(cs->pixmap);
		}
		cs->pixmap = temp;
		has_pixmap_changed = True;
		if (CSETS_IS_TRANSPARENT_ROOT(cs))
		{
			cs->pixmap_type = PIXMAP_ROOT_PIXMAP_TRAN;
		}
	} /* has_pixmap_changed */


	/*
	 * ---------- change the icon tint colour ----------
	 */
	if (has_icon_tint_changed)
	{
		/* user specified colour */
		if (icon_tint != NULL)
		{
			Pixel old_tint = cs->icon_tint;
			PictureFreeColors(
				dpy, Pcmap, &cs->icon_tint, 1, 0, True);
			cs->icon_tint = GetColor(icon_tint);
			if (old_tint != cs->icon_tint)
			{
				has_icon_pixels_changed = True;
			}
		}
		else
		{
			/* default */
			Pixel old_tint = cs->icon_tint;
			PictureFreeColors(
				dpy, Pcmap, &cs->icon_tint, 1, 0, True);
			cs->icon_tint = GetColor(black);
			if (old_tint != cs->icon_tint)
			{
				has_icon_pixels_changed = True;
			}
		}
	}

	/*
	 * ---------- send new colorset to fvwm and clean up ----------
	 */
	/* make sure the server has this to avoid races */
	XSync(dpy, False);

	/* inform modules of the change */
	if (have_pixels_changed || has_pixmap_changed || has_shape_changed ||
	    has_fg_alpha_changed || has_icon_pixels_changed)
	{
		BroadcastColorset(n);
	}

	if (fg)
	{
		free(fg);
	}
	if (bg)
	{
		free(bg);
	}
	if (hi)
	{
		free(hi);
	}
	if (sh)
	{
		free(sh);
	}
	if (fgsh)
	{
		free(fgsh);
	}
	if (tint)
	{
		free(tint);
	}
	if (fg_tint)
	{
		free(fg_tint);
	}
	if (bg_tint)
	{
		free(bg_tint);
	}
	if (icon_tint)
	{
		free(icon_tint);
	}
	return;
}
Пример #8
0
static PyObject * try_shm_image(TkWinObject * self)
{
    XImage *ximage = NULL;
    XShmSegmentInfo * shminfo = NULL;

    /* create shminfo */
    shminfo = PyMem_Malloc(sizeof(XShmSegmentInfo));
    if (shminfo == NULL)
	return PyErr_NoMemory();
    shminfo->shmid = -1;
    shminfo->shmaddr = (char*) -1;

    ximage = XShmCreateImage(Tk_Display(self->tkwin),
			     Tk_Visual(self->tkwin),
			     Tk_Depth(self->tkwin), ZPixmap, NULL,
			     shminfo, 1, 1);
    if (ximage == NULL)
    {
	PyErr_SetString(PyExc_RuntimeError, "XShmCreateImage failed");
	goto error;
    }

    /* allocate the shm segment */
    shminfo->shmid = shmget(IPC_PRIVATE,
			    ximage->bytes_per_line * ximage->height,
			    IPC_CREAT | 0777);
    if (shminfo->shmid == -1)
    {
	PyErr_SetFromErrno(PyExc_RuntimeError);
	goto error;
    }

    shminfo->shmaddr = ximage->data = shmat(shminfo->shmid, 0, 0);
    if (shminfo->shmaddr == (char*) -1)
    {
	PyErr_SetFromErrno(PyExc_RuntimeError);
	goto error;
    }

    shminfo->readOnly = True;

    XShmAttach(Tk_Display(self->tkwin), shminfo);
    XSync(Tk_Display(self->tkwin), False);

    if (shmerror)
    {
	XDestroyImage(ximage);
	shmdt(shminfo->shmaddr);
	shmctl(shminfo->shmid, IPC_RMID, 0);
	PyMem_Free(shminfo);
	Py_INCREF(Py_None);
	return Py_None;
    }

    return PaxImage_FromShmImage(ximage, shminfo, Tk_Display(self->tkwin));

 error:
    if (ximage)
	XDestroyImage(ximage);
    if (shminfo)
    {
	if (shminfo->shmaddr != (char*) -1)
	    shmdt(shminfo->shmaddr);
	if (shminfo->shmid != -1)
	    shmctl(shminfo->shmid, IPC_RMID, 0);
	PyMem_Free(shminfo);
    }
    return NULL;
}
Пример #9
0
/* Finds NaCl/Chromium shm memory using external handler.
 * Reply must be in the form PID:file */
struct cache_entry* find_shm(uint64_t paddr, uint64_t sig, size_t length) {
    struct cache_entry* entry = NULL;

    /* Find entry in cache */
    if (cache[0].paddr == paddr) {
        entry = &cache[0];
    } else if (cache[1].paddr == paddr) {
        entry = &cache[1];
    } else {
        /* Not found: erase an existing entry. */
        entry = &cache[next_entry];
        next_entry = (next_entry + 1) % 2;
        close_mmap(entry);
    }

    int try;
    for (try = 0; try < 2; try++) {
        /* Check signature */
        if (entry->map) {
            if (*((uint64_t*)entry->map) == sig)
                return entry;

            log(1, "Invalid signature, fetching new shm!");
            close_mmap(entry);
        }

        /* Setup parameters and run command */
        char arg1[32], arg2[32];
        int c;

        c = snprintf(arg1, sizeof(arg1), "%08lx", (long)paddr & 0xffffffff);
        trueorabort(c > 0, "snprintf");
        int i, p = 0;
        for (i = 0; i < 8; i++) {
            c = snprintf(arg2 + p, sizeof(arg2) - p, "%02x",
                         ((uint8_t*)&sig)[i]);
            trueorabort(c > 0, "snprintf");
            p += c;
        }

        int sock;
        struct sockaddr_un addr;

        sock = socket(AF_UNIX, SOCK_STREAM, 0);
        addr.sun_family = AF_UNIX;
        strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path));

        if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
            syserror("Cannot connect to findnacl daemon.");
            return NULL;
        }

        char args[70];
        c = snprintf(args, sizeof(args), "%s %s", arg1, arg2);
        trueorabort(c > 0 && c < sizeof(args), "snprintf");

        if (write(sock, args, strlen(args)) < 0) {
            syserror("Cannot send arguments.");
            close(sock);
            return NULL;
        }

        entry->fd = recv_pid_fd(sock);
        if (entry->fd < 0) {
            error("Cannot open nacl file.");
            return NULL;
        }
        close(sock);

        entry->paddr = paddr;

        entry->length = length;
        entry->map = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED,
                          entry->fd, 0);
        if (!entry->map) {
            error("Cannot mmap.");
            close(entry->fd);
            return NULL;
        }

        log(2, "mmap ok %p %zu %d", entry->map, entry->length, entry->fd);
    }

    error("Cannot find shm.");
    return NULL;
}

/* WebSocket functions */

XImage* img = NULL;
XShmSegmentInfo shminfo;

/* Writes framebuffer image to websocket/shm */
int write_image(const struct screen* screen) {
    char reply_raw[FRAMEMAXHEADERSIZE + sizeof(struct screen_reply)];
    struct screen_reply* reply =
        (struct screen_reply*)(reply_raw + FRAMEMAXHEADERSIZE);
    int refresh = 0;

    memset(reply_raw, 0, sizeof(reply_raw));

    reply->type = 'S';
    reply->width = screen->width;
    reply->height = screen->height;

    /* Allocate XShmImage */
    if (!img || img->width != screen->width || img->height != screen->height) {
        if (img) {
            XDestroyImage(img);
            shmdt(shminfo.shmaddr);
            shmctl(shminfo.shmid, IPC_RMID, 0);
        }

        /* FIXME: Some error checking should happen here... */
        img = XShmCreateImage(dpy, DefaultVisual(dpy, 0), 24,
                              ZPixmap, NULL, &shminfo,
                              screen->width, screen->height);
        trueorabort(img, "XShmCreateImage");
        shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line*img->height,
                               IPC_CREAT|0777);
        trueorabort(shminfo.shmid != -1, "shmget");
        shminfo.shmaddr = img->data = shmat(shminfo.shmid, 0, 0);
        trueorabort(shminfo.shmaddr != (void*)-1, "shmat");
        shminfo.readOnly = False;
        int ret = XShmAttach(dpy, &shminfo);
        trueorabort(ret, "XShmAttach");
        /* Force refresh */
        refresh = 1;
    }

    if (screen->refresh) {
        log(1, "Force refresh from client.");
        /* refresh forced by the client */
        refresh = 1;
    }

    XEvent ev;
    /* Register damage on new windows */
    while (XCheckTypedEvent(dpy, MapNotify, &ev)) {
        register_damage(dpy, ev.xcreatewindow.window);
        refresh = 1;
    }

    /* Check for damage */
    while (XCheckTypedEvent(dpy, damageEvent + XDamageNotify, &ev)) {
        refresh = 1;
    }

    /* Check for cursor events */
    reply->cursor_updated = 0;
    while (XCheckTypedEvent(dpy, fixesEvent + XFixesCursorNotify, &ev)) {
        XFixesCursorNotifyEvent* curev = (XFixesCursorNotifyEvent*)&ev;
        if (verbose >= 2) {
            char* name = XGetAtomName(dpy, curev->cursor_name);
            log(2, "cursor! %ld %s", curev->cursor_serial, name);
            XFree(name);
        }
        reply->cursor_updated = 1;
        reply->cursor_serial = curev->cursor_serial;
    }

    /* No update */
    if (!refresh) {
        reply->shm = 0;
        reply->updated = 0;
        socket_client_write_frame(reply_raw, sizeof(*reply),
                                  WS_OPCODE_BINARY, 1);
        return 0;
    }

    /* Get new image from framebuffer */
    XShmGetImage(dpy, DefaultRootWindow(dpy), img, 0, 0, AllPlanes);

    int size = img->bytes_per_line * img->height;

    trueorabort(size == screen->width*screen->height*4,
                "Invalid screen byte count");

    trueorabort(screen->shm, "Non-SHM rendering is not supported");

    struct cache_entry* entry = find_shm(screen->paddr, screen->sig, size);

    reply->shm = 1;
    reply->updated = 1;
    reply->shmfailed = 0;

    if (entry && entry->map) {
        if (size == entry->length) {
            memcpy(entry->map, img->data, size);
            msync(entry->map, size, MS_SYNC);
        } else {
            /* This should never happen (it means the client passed an
             * outdated buffer to us). */
            error("Invalid shm entry length (client bug!).");
            reply->shmfailed = 1;
        }
    } else {
        /* Keep the flow going, even if we cannot find the shm. Next time
         * the NaCl client reallocates the buffer, we are likely to be able
         * to find it. */
        error("Cannot find shm, moving on...");
        reply->shmfailed = 1;
    }

    /* Confirm write is done */
    socket_client_write_frame(reply_raw, sizeof(*reply),
                              WS_OPCODE_BINARY, 1);

    return 0;
}

/* Writes cursor image to websocket */
int write_cursor() {
    XFixesCursorImage *img = XFixesGetCursorImage(dpy);
    if (!img) {
        error("XFixesGetCursorImage returned NULL");
        return -1;
    }
    int size = img->width*img->height;
    const int replylength = sizeof(struct cursor_reply) + size*sizeof(uint32_t);
    char reply_raw[FRAMEMAXHEADERSIZE + replylength];
    struct cursor_reply* reply =
        (struct cursor_reply*)(reply_raw + FRAMEMAXHEADERSIZE);

    memset(reply_raw, 0, sizeof(*reply_raw));

    reply->type = 'P';
    reply->width = img->width;
    reply->height = img->height;
    reply->xhot = img->xhot;
    reply->yhot = img->yhot;
    reply->cursor_serial = img->cursor_serial;
    /* This casts long[] to uint32_t[] */
    int i;
    for (i = 0; i < size; i++)
        reply->pixels[i] = img->pixels[i];

    socket_client_write_frame(reply_raw, replylength, WS_OPCODE_BINARY, 1);
    XFree(img);

    return 0;
}
/* Test a composite of a given operation, source, and destination picture.  */
Bool
blend_test(Display *dpy, picture_info *win, picture_info *dst,
	   const int *op, int num_op,
	   const picture_info **src_color, int num_src,
	   const picture_info **dst_color, int num_dst)
{
	color4d expected, tested, tdst;
	char testname[20];
	int i, j, k, y, iter;
	int page, num_pages;

	/* If the window is smaller than the number of sources to test,
	 * we need to break the sources up into pages.
	 *
	 * We however assume that the window will always be wider than num_ops.
	 */
	num_pages = num_src / win_height + 1;

	k = y = 0;
	while (k < num_dst) {
	    XImage *image;
	    int k0 = k, k1 = k;
	    int this_src, rem_src;

	    rem_src = num_src;
	    for (page = 0; page < num_pages; page++) {
		    this_src = rem_src / (num_pages - page);
		    for (iter = 0; iter < pixmap_move_iter; iter++) {
			    k1 = k0;
			    y = 0;
			    while (k1 < num_dst && y + this_src <= win_height) {
				    XRenderComposite(dpy, PictOpSrc,
						     dst_color[k1++]->pict, 0, dst->pict,
						     0, 0,
						     0, 0,
						     0, y,
						     num_op, this_src);
				    for (j = 0; j < this_src; j++) {
					    for (i = 0; i < num_op; i++) {
						    XRenderComposite(dpy, ops[op[i]].op,
								     src_color[j]->pict, 0, dst->pict,
								     0, 0,
								     0, 0,
								     i, y,
								     1, 1);
					    }
					    y++;
				    }
			    }
		    }

		    image = XGetImage(dpy, dst->d,
				      0, 0, num_ops, y,
				      0xffffffff, ZPixmap);
		    copy_pict_to_win(dpy, dst, win, win_width, win_height);

		    y = 0;
		    for (k = k0; k < k1; k++) {
			    XRenderDirectFormat dst_acc;

			    accuracy(&dst_acc,
				     &dst->format->direct,
				     &dst_color[k]->format->direct);

			    tdst = dst_color[k]->color;
			    color_correct(dst, &tdst);

			    for (j = 0; j < this_src; j++) {
				    XRenderDirectFormat acc;

				    accuracy(&acc, &src_color[j]->format->direct, &dst_acc);

				    for (i = 0; i < num_op; i++) {
					    get_pixel_from_image(image, dst, i, y, &tested);

					    do_composite(ops[op[i]].op,
							 &src_color[j]->color,
							 NULL,
							 &tdst,
							 &expected,
							 FALSE);
					    color_correct(dst, &expected);

					    if (eval_diff(&acc, &expected, &tested) > 3.) {
						    char *srcformat;

						    snprintf(testname, 20, "%s blend", ops[op[i]].name);
						    describe_format(&srcformat, NULL, src_color[j]->format);
						    print_fail(testname, &expected, &tested, 0, 0,
							       eval_diff(&acc, &expected, &tested));
						    printf("src color: %.2f %.2f %.2f %.2f (%s)\n"
							   "dst color: %.2f %.2f %.2f %.2f\n",
							   src_color[j]->color.r, src_color[j]->color.g,
							   src_color[j]->color.b, src_color[j]->color.a,
							   srcformat,
							   dst_color[k]->color.r,
							   dst_color[k]->color.g,
							   dst_color[k]->color.b,
							   dst_color[k]->color.a);
						    printf("src: %s, dst: %s\n", src_color[j]->name, dst->name);
						    free(srcformat);
						    return FALSE;
					    }
				    }
				    y++;
			    }
		    }

		    XDestroyImage(image);
		    rem_src -= this_src;
	    }
	}

	return TRUE;
}
Пример #11
0
static PyObject *
tkwin_ShmCreateImage(TkWinObject *self, PyObject *args)
{
    /* XXX error handling in this function is incomplete */
    unsigned int depth, width, height;
    int format;
    char *data;
    int datalength;
    XImage *ximage = NULL;
    XShmSegmentInfo * shminfo = NULL;
    PyObject * retval = NULL;
    int read_only = 0;

    if (!PyArg_ParseTuple(args, "iiz#ii|i", &depth, &format,
			  &data, &datalength, &width, &height, &read_only))
	return NULL;

    /* create shminfo */
    shminfo = PyMem_Malloc(sizeof(XShmSegmentInfo));
    if (shminfo == NULL)
	return PyErr_NoMemory();
    shminfo->shmid = -1;
    shminfo->shmaddr = (char*) -1;

    ximage = XShmCreateImage(Tk_Display(self->tkwin), Tk_Visual(self->tkwin),
			     depth, format, NULL, shminfo,
			     width, height);
    if (ximage == NULL)
    {
	PyErr_SetString(PyExc_RuntimeError, "XShmCreateImage failed");
	goto error;
    }

    /* allocate the shm segment */
    shminfo->shmid = shmget(IPC_PRIVATE,
			    ximage->bytes_per_line * ximage->height,
			    IPC_CREAT | 0777);
    if (shminfo->shmid == -1)
    {
	PyErr_SetFromErrno(PyExc_RuntimeError);
	goto error;
    }

    shminfo->shmaddr = ximage->data = shmat(shminfo->shmid, 0, 0);
    if (shminfo->shmaddr == (char*)-1)
    {
	PyErr_SetFromErrno(PyExc_RuntimeError);
	goto error;
    }

    if (read_only)
	shminfo->readOnly = True;
    else
	shminfo->readOnly = False;

    if (!XShmAttach(Tk_Display(self->tkwin), shminfo))
    {
	PyErr_SetString(PyExc_RuntimeError, "XShmAttach failed");
	goto error;
    }
    XSync(Tk_Display(self->tkwin), False);

    retval = PaxImage_FromShmImage(ximage, shminfo, Tk_Display(self->tkwin));
    if (!retval)
	goto error;

    /* copy the data */
    if (data)
    {
	/*printf("ShmCreateImage: copy data\n");*/
	if (datalength <= ximage->bytes_per_line * ximage->height)
	{
	    memcpy(shminfo->shmaddr, data, datalength);
	}
	else
	{
	    fprintf(stderr, "image data longer that ximage\n");
	}
    }

    return (PyObject*)retval;

 error:
    if (ximage)
	XDestroyImage(ximage);
    if (shminfo)
    {
	if (shminfo->shmaddr != (char*) -1)
	    shmdt(shminfo->shmaddr);
	if (shminfo->shmid != -1)
	    shmctl(shminfo->shmid, IPC_RMID, 0);
	PyMem_Free(shminfo);
    }
    return NULL;
}
Пример #12
0
static void exit_x11(void)
{
    XDestroyImage(g_x11.bitmap);
    XDestroyWindow(g_x11.dpy, g_x11.win);
    XCloseDisplay(g_x11.dpy);
}
Пример #13
0
i_img *
imss_x11(unsigned long display_ul, int window_id,
	 int left, int top, int right, int bottom) {
  Display *display = (Display *)display_ul;
  int own_display = 0; /* non-zero if we connect */
  XImage *image;
  XWindowAttributes attr;
  i_img *result;
  i_color *line, *cp;
  int x, y;
  XColor *colors;
  XErrorHandler old_handler;
  int width, height;

  i_clear_error();

  /* we don't want the default noisy error handling */
  old_handler = XSetErrorHandler(my_handler);

  if (!display) {
    display = XOpenDisplay(NULL);
    ++own_display;
    if (!display) {
      XSetErrorHandler(old_handler);
      i_push_error(0, "No display supplied and cannot connect");
      return NULL;
    }
  }

  if (!window_id) {
    int screen = DefaultScreen(display);
    window_id = RootWindow(display, screen);
  }

  if (!XGetWindowAttributes(display, window_id, &attr)) {
    XSetErrorHandler(old_handler);
    if (own_display)
      XCloseDisplay(display);
    i_push_error(0, "Cannot XGetWindowAttributes");
    return NULL;
  }

  /* adjust negative/zero values to window size */
  if (left < 0)
    left += attr.width;
  if (top < 0)
    top += attr.height;
  if (right <= 0)
    right += attr.width;
  if (bottom <= 0)
    bottom += attr.height;
  
  /* clamp */
  if (left < 0)
    left = 0;
  if (right > attr.width)
    right = attr.width;
  if (top < 0)
    top = 0;
  if (bottom > attr.height)
    bottom = attr.height;

  /* validate */
  if (right <= left || bottom <= top) {
    XSetErrorHandler(old_handler);
    if (own_display)
      XCloseDisplay(display);
    i_push_error(0, "image would be empty");
    return NULL;
  }
  width = right - left;
  height = bottom - top;
  image = XGetImage(display, window_id, left, top, width, height,
                    -1, ZPixmap);
  if (!image) {
    XSetErrorHandler(old_handler);
    if (own_display)
      XCloseDisplay(display);
    i_push_error(0, "Cannot XGetImage");
    return NULL;
  }

  result = i_img_8_new(width, height, 3);
  line = mymalloc(sizeof(i_color) * width);
  colors = mymalloc(sizeof(XColor) * width);
  for (y = 0; y < height; ++y) {
    cp = line;
    /* XQueryColors seems to be a round-trip, so do one big request
       instead of one per pixel */
    for (x = 0; x < width; ++x) {
      colors[x].pixel = XGetPixel(image, x, y);
    }
    XQueryColors(display, attr.colormap, colors, width);
    for (x = 0; x < width; ++x) {
      cp->rgb.r = colors[x].red >> 8;
      cp->rgb.g = colors[x].green >> 8;
      cp->rgb.b = colors[x].blue >> 8;
      ++cp;
    }
    i_plin(result, 0, width, y, line);
  }
  myfree(line);
  myfree(colors);
  XDestroyImage(image);

  XSetErrorHandler(old_handler);
  if (own_display)
    XCloseDisplay(display);

  i_tags_setn(&result->tags, "ss_window_width", attr.width);
  i_tags_setn(&result->tags, "ss_window_height", attr.height);
  i_tags_set(&result->tags, "ss_type", "X11", 3);
  i_tags_setn(&result->tags, "ss_left", left);
  i_tags_setn(&result->tags, "ss_top", top);

  return result;
}
Пример #14
0
static void draw_gradient(Widget w, Pixmap scribble)
{
	MwAnimatorWidget aw = (MwAnimatorWidget)w;
	char *bgrad = aw->animator.bgrad;
	Display *dpy = XtDisplay(w);
	int screen = DefaultScreen(dpy);
	Visual *visual = DefaultVisual(dpy, screen);
	int bitmap_pad = XBitmapPad(dpy);
	GC gc = aw->animator.gc;
	int bytes_per_line = 0;
	XColor color;
	unsigned long pixel;
	int format = ZPixmap;
	int offset = 0;
	char *data = NULL;
	int width, height, depth;
	int x, y;
	int bw, bh, bc, ba, bz, bn;
	char bc1[100], bc2[100];
	XColor top, bot;

	unsigned int neww = aw->core.width;
	unsigned int newh = aw->core.height;
	unsigned int ox, oy;
	unsigned int oldw = width, oldh = height;

	/* we're going from black at the top to blue
	   at the bottom */
	if (bgrad == NULL) bgrad = "";
	if (aw->animator.ximage == NULL) {
		XImage *img;
		bn = sscanf(bgrad, "%d %d %d %d %d %s %s",
			&bw, &bh, &bc, &ba, &bz, bc1, bc2);
		if (bn < 0) bn = 0;
		switch (bn) {
		case 0:	bw = 100;
		case 1:	bh = 100;
		case 2: bc = 128;
		case 3: ba = 0;
		case 4:	bz = 1;
		case 5: strcpy(bc1, "black");
		case 6:	strcpy(bc2, "blue");
		default: ;	/* catches e.g. -1 */
		}

		width = aw->core.width*bw/100;
		height = aw->core.height*bh/100;
		depth = aw->core.depth;
		img = aw->animator.ximage = XCreateImage(dpy,
			visual, depth, format, offset, data,
			width, height, bitmap_pad, bytes_per_line);
		img->data = MwMalloc(img->bytes_per_line*img->height);
		MwAllocNamedColor(dpy, bc1, &top);
		MwAllocNamedColor(dpy, bc2, &bot);
		for (y = 0; y < height; y++) {
			color.red = (int)top.red
				+((int)bot.red-top.red)*y/height;
			color.green = (int)top.green
				+((int)bot.green-top.green)*y/height;
			color.blue = (int)top.blue
				+((int)bot.blue-top.blue)*y/height;
			MwAllocColor(dpy, None, &color);
			pixel = color.pixel;
			for (x = 0; x < width; x++ ) {
				XPutPixel(img, x, y, pixel);
			}
		}
		aw->animator.ximage = XCreateImage(dpy,
			visual, depth, format, offset, data,
			aw->core.width, aw->core.height,
			bitmap_pad, bytes_per_line);
		aw->animator.ximage->data = MwMalloc(
					aw->animator.ximage->bytes_per_line
					*aw->animator.ximage->height);

		neww = aw->core.width;
		newh = aw->core.height;
		oldw = width, oldh = height;

		if (bz) {	/* zoom */
			/* snarfed from Image widget */
			for (y = 0; y < newh; y++) {
				oy = y*oldh/newh;
				for (x = 0; x < neww; x++) {
					ox = x*oldw/neww;
					pixel = XGetPixel(img, ox, oy);
					XPutPixel(aw->animator.ximage,
						x, y, pixel);
				}
			}
		} else {	/* tile */
			for (y = 0; y < newh; y++) {
				oy = y % oldh;
				for (x = 0; x < neww; x++) {
					ox = x % oldw;
					pixel = XGetPixel(img, ox, oy);
					XPutPixel(aw->animator.ximage,
						x, y, pixel);
				}
			}
		}
		XDestroyImage(img);
	}
	XPutImage(dpy, scribble, gc, aw->animator.ximage,
		0, 0, 0, 0, aw->core.width, aw->core.height);
}
Пример #15
0
gboolean
myDisplayTestXrender (DisplayInfo *display, gdouble min_time)
{
#ifdef HAVE_RENDER
    GTimeVal t1, t2;
    gdouble dt;
    Display *dpy;
    Picture picture1, picture2, picture3;
    XRenderPictFormat *format_src, *format_dst;
    Pixmap fillPixmap, rootPixmap;
    XRenderPictureAttributes pa;
    XSetWindowAttributes attrs;
    XImage *ximage;
    Window output;
    XRenderColor c;
    Visual *visual;
    Screen *screen;
    int x, y, w, h;
    int screen_number;
    int depth;
    int iterations;

    g_return_val_if_fail (display != NULL, FALSE);
    TRACE ("entering myDisplayTesxrender");

    c.alpha = 0x7FFF;
    c.red   = 0xFFFF;
    c.green = 0xFFFF;
    c.blue  = 0xFFFF;

    dpy = display->dpy;
    screen_number = DefaultScreen (dpy);
    screen = DefaultScreenOfDisplay (dpy);
    visual = DefaultVisual (dpy, screen_number);
    depth = DefaultDepth (dpy, screen_number);

    w = WidthOfScreen(screen) / 16;
    h = HeightOfScreen(screen) / 16;
    x = (WidthOfScreen(screen) - w);
    y = (HeightOfScreen(screen) - h);

    format_dst = XRenderFindVisualFormat (dpy, visual);
    g_return_val_if_fail (format_dst != NULL , FALSE);

    format_src = XRenderFindStandardFormat (dpy, PictStandardA8);
    g_return_val_if_fail (format_src != NULL , FALSE);

    ximage = XGetImage (dpy,
                        DefaultRootWindow(dpy),
                        x, y, w, h,
                        AllPlanes, ZPixmap);
    g_return_val_if_fail (ximage != NULL , FALSE);

    rootPixmap = XCreatePixmap (dpy,
                                DefaultRootWindow(dpy),
                                w, h, depth);
    XPutImage (dpy, rootPixmap,
               DefaultGC (dpy, screen_number), ximage,
               0, 0, 0, 0, w, h);
    XDestroyImage (ximage);

    attrs.override_redirect = TRUE;
    output = XCreateWindow (dpy,
                            DefaultRootWindow(dpy),
                            x, y, w, h,
                            0, CopyFromParent, CopyFromParent,
                            (Visual *) CopyFromParent,
                            CWOverrideRedirect, &attrs);
    XMapRaised (dpy, output);

    fillPixmap = XCreatePixmap (dpy,
                                DefaultRootWindow(dpy),
                                1, 1, 8);

    g_get_current_time (&t1);

    pa.repeat = TRUE;
    picture1 = XRenderCreatePicture (dpy,
                                     rootPixmap,
                                     format_dst, 0, NULL);
    picture2 = XRenderCreatePicture (dpy,
                                     fillPixmap,
                                     format_src, CPRepeat, &pa);
    picture3 = XRenderCreatePicture (dpy,
                                     output,
                                     format_dst, 0, NULL);
    XRenderComposite (dpy, PictOpSrc,
                    picture1, None, picture3,
                    0, 0, 0, 0, 0, 0, w, h);
    XRenderFillRectangle (dpy, PictOpSrc,
                          picture2, &c, 0, 0,
                          1, 1);
    for (iterations = 0; iterations < 10; iterations++)
    {
        XRenderComposite (dpy, PictOpOver,
                        picture1, picture2, picture3,
                        0, 0, 0, 0, 0, 0, w, h);
        ximage = XGetImage (dpy, output,
                            0, 0, 1, 1,
                            AllPlanes, ZPixmap);
        if (ximage)
        {
                XDestroyImage (ximage);
        }
    }
    XRenderFreePicture (dpy, picture1);
    XRenderFreePicture (dpy, picture2);
    XRenderFreePicture (dpy, picture3);

    XFreePixmap (dpy, fillPixmap);
    XFreePixmap (dpy, rootPixmap);

    XDestroyWindow (dpy, output);

    g_get_current_time (&t2);

    dt = (gdouble) (t2.tv_sec - t1.tv_sec) * G_USEC_PER_SEC +
         (gdouble) (t2.tv_usec - t1.tv_usec) / 1000.0;

    if (dt < min_time)
    {
        TRACE ("XRender test passed (target %3.4f sec., measured %3.4f sec.).", min_time, dt);
        return TRUE;
    }
    g_print ("XRender test failed (target %3.4f sec., measured %3.4f sec.).\n", min_time, dt);
    return FALSE;
#else  /* HAVE_RENDER */
    return FALSE;
#endif /* HAVE_RENDER */
}
Пример #16
0
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
                             jclass cls,
                             jobject xgc,
                             jint x,
                             jint y,
                             jint width,
                             jint height,
                             jintArray pixelArray) {

    XImage *image;
    jint *ary;               /* Array of jints for sending pixel values back
                              * to parent process.
                              */
    Window rootWindow;
    AwtGraphicsConfigDataPtr adata;

    DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);

    AWT_LOCK();

    /* avoid a lot of work for empty rectangles */
    if ((width * height) == 0) {
        AWT_UNLOCK();
        return;
    }
    DASSERT(width * height > 0); /* only allow positive size */

    adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
    DASSERT(adata != NULL);

    rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
    image = getWindowImage(awt_display, rootWindow, x, y, width, height);

    /* Array to use to crunch around the pixel values */
    ary = (jint *) malloc(width * height * sizeof (jint));
    if (ary == NULL) {
        JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
        XDestroyImage(image);
        AWT_UNLOCK();
        return;
    }
    /* convert to Java ARGB pixels */
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper
                                                         * 32-bits on 64-bit
                                                         * OSes.
                                                         */

            pixel |= 0xff000000; /* alpha - full opacity */

            ary[(y * width) + x] = pixel;
        }
    }
    (*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
    free(ary);

    XDestroyImage(image);

    AWT_UNLOCK();
}
Пример #17
0
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRect rect)
{
#if defined(IS_MACOSX)
	/* The following is a very modified version of the glGrab code example
	 * given by Apple (as are some of the convenience functions called). */
	size_t bytewidth;
	uint8_t bitsPerPixel, bytesPerPixel;
	uint8_t *buffer;

	/* Build OpenGL context of entire screen */
	CGDirectDisplayID displayID = CGMainDisplayID();
	CGOpenGLDisplayMask mask = CGDisplayIDToOpenGLDisplayMask(displayID);
	CGLContextObj glContext = createFullScreenCGLContext(mask);
	if (glContext == NULL) return NULL;

	/* TODO: CGDisplayBitsPerPixel() is deprecated in Snow Leopard; I'm not
	 * sure of the replacement function. */
	bitsPerPixel = (uint8_t)CGDisplayBitsPerPixel(displayID);
	bytesPerPixel = bitsPerPixel / 8;

	/* Align width to padding. */
	bytewidth = ADD_PADDING(rect.size.width * bytesPerPixel);

	/* Convert Quartz point to postscript point. */
	rect.origin.y = CGDisplayPixelsHigh(displayID) - rect.origin.y - rect.size.height;

	/* Extract buffer from context */
	buffer = createBufferFromCurrentCGLContext((GLint)rect.origin.x,
	                                           (GLint)rect.origin.y,
	                                           (GLsizei)rect.size.width,
	                                           (GLsizei)rect.size.height,
	                                           bytewidth);
	/* Reset and release GL context */
	destroyFullScreenCGLContext(glContext);
	if (buffer == NULL) return NULL;

	/* Convert from OpenGL (origin at bottom left) to Quartz (origin at top
	 * left) coordinate system. */
	flipBitmapData(buffer, rect.size.width, rect.size.height, bytewidth);

	return createMMBitmap(buffer, rect.size.width, rect.size.height, bytewidth,
	                      bitsPerPixel, bytesPerPixel);
#elif defined(USE_X11)
	MMBitmapRef bitmap;

	Display *display = XOpenDisplay(NULL);
	XImage *image = XGetImage(display,
	                          XDefaultRootWindow(display),
	                          (int)rect.origin.x,
	                          (int)rect.origin.y,
	                          (unsigned int)rect.size.width,
	                          (unsigned int)rect.size.height,
	                          AllPlanes, ZPixmap);
	XCloseDisplay(display);
	if (image == NULL) return NULL;

	bitmap = createMMBitmap((uint8_t *)image->data,
	                        rect.size.width,
	                        rect.size.height,
	                        (size_t)image->bytes_per_line,
	                        (uint8_t)image->bits_per_pixel,
	                        (uint8_t)image->bits_per_pixel / 8);
	image->data = NULL; /* Steal ownership of bitmap data so we don't have to
	                     * copy it. */
	XDestroyImage(image);

	return bitmap;
#elif defined(IS_WINDOWS)
	MMBitmapRef bitmap;
	void *data;
	HDC screen = NULL, screenMem = NULL;
	HBITMAP dib;
	BITMAPINFO bi;

	/* Initialize bitmap info. */
	bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
   	bi.bmiHeader.biWidth = (long)rect.size.width;
   	bi.bmiHeader.biHeight = -(long)rect.size.height; /* Non-cartesian, please */
   	bi.bmiHeader.biPlanes = 1;
   	bi.bmiHeader.biBitCount = 32;
   	bi.bmiHeader.biCompression = BI_RGB;
   	bi.bmiHeader.biSizeImage = (DWORD)(4 * rect.size.width * rect.size.height);
	bi.bmiHeader.biXPelsPerMeter = 0;
	bi.bmiHeader.biYPelsPerMeter = 0;
	bi.bmiHeader.biClrUsed = 0;
	bi.bmiHeader.biClrImportant = 0;

	screen = GetDC(NULL); /* Get entire screen */
	if (screen == NULL) return NULL;

	/* Get screen data in display device context. */
   	dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0);

	/* Copy the data into a bitmap struct. */
	if ((screenMem = CreateCompatibleDC(screen)) == NULL ||
	    SelectObject(screenMem, dib) == NULL ||
	    !BitBlt(screenMem, 
	            (int)rect.origin.x, 
	            (int)rect.origin.y, 
	            (int)rect.size.width,
	            (int)rect.size.height, screen, 0, 0, SRCCOPY)) {
		/* Error copying data. */
		ReleaseDC(NULL, screen);
		DeleteObject(dib);
		if (screenMem != NULL) DeleteDC(screenMem);

		return NULL;
	}

	bitmap = createMMBitmap(NULL,
	                        rect.size.width,
	                        rect.size.height,
	                        4 * rect.size.width,
	                        (uint8_t)bi.bmiHeader.biBitCount, 
	                        4);

	/* Copy the data to our pixel buffer. */
	if (bitmap != NULL) {
		bitmap->imageBuffer = malloc(bitmap->bytewidth * bitmap->height);
		memcpy(bitmap->imageBuffer, data, bitmap->bytewidth * bitmap->height);
	}

	ReleaseDC(NULL, screen);
	DeleteObject(dib);
	DeleteDC(screenMem);

	return bitmap;
#endif
}
Пример #18
0
void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool /*isSnapshot*/)
{
    if (m_isWindowed)
        return;

    if (!m_isStarted) {
        // FIXME: we should paint a missing plugin icon.
        return;
    }

    if (context->paintingDisabled() || !m_drawable)
        return;

    XEvent xevent;
    memset(&xevent, 0, sizeof(XEvent));
    XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
    exposeEvent.type = GraphicsExpose;
    exposeEvent.display = x11HostDisplay();
    exposeEvent.drawable = m_drawable;

    IntRect exposedRect(dirtyRect);
    exposeEvent.x = exposedRect.x();
    exposeEvent.y = exposedRect.y();

    // Note: in transparent mode Flash thinks width is the right and height is the bottom.
    // We should take it into account if we want to support transparency.
    exposeEvent.width = exposedRect.width();
    exposeEvent.height = exposedRect.height();

    NPP_HandleEvent(&xevent);

    if (m_pluginDisplay != x11HostDisplay())
        XSync(m_pluginDisplay, false);

#if PLATFORM(QT)
    XImage* xImage = XGetImage(NetscapePlugin::x11HostDisplay(), m_drawable, exposedRect.x(), exposedRect.y(),
                               exposedRect.width(), exposedRect.height(), ULONG_MAX, ZPixmap);
    QPainter* painter = context->platformContext();
    painter->drawImage(QPoint(exposedRect.x(), exposedRect.y()), qimageFromXImage(xImage), exposedRect);

    XDestroyImage(xImage);
#elif PLATFORM(GTK)
    RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(m_pluginDisplay,
                                                                                 m_drawable,
                                                                                 static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info)->visual,
                                                                                 m_pluginSize.width(),
                                                                                 m_pluginSize.height()));
    cairo_t* cr = context->platformContext()->cr();
    cairo_save(cr);

    cairo_set_source_surface(cr, drawableSurface.get(), 0, 0);

    cairo_rectangle(cr, exposedRect.x(), exposedRect.y(), exposedRect.width(), exposedRect.height());
    cairo_clip(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint(cr);

    cairo_restore(cr);
#else
    notImplemented();
#endif
}
Пример #19
0
slop::GLSelectRectangle::GLSelectRectangle( int sx, int sy, int ex, int ey, int border, bool highlight, float r, float g, float b, float a ) {
    m_x = std::min( sx, ex );
    m_y = std::min( sy, ey );
    m_width = std::max( sx, ex ) - m_x;
    m_height = std::max( sy, ey ) - m_y;
    m_r = r;
    m_g = g;
    m_b = b;
    m_a = a;
    m_border = border;
    m_window = None;
    m_highlight = highlight;
    m_glassPixels = 64;
    m_glassx = xengine->m_mousex;
    m_glassy = xengine->m_mousey;
    m_realglassx = xengine->m_mousex;
    m_realglassy = xengine->m_mousey;
    m_glassSize = 4;
    m_glassBorder = 1;
    m_monitors = xengine->getCRTCS();
    m_themed = false;
    m_shader = "simple";
    m_time = 0;

    // If we don't have a border, we don't exist, so just die.
    if ( m_border == 0 ) {
        return;
    }

    if ( m_highlight ) {
        m_border = 0;
    }

    static int visdata[] = {
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
        GLX_DOUBLEBUFFER, True,
        GLX_RED_SIZE, 8,
        GLX_GREEN_SIZE, 8,
        GLX_BLUE_SIZE, 8,
        GLX_ALPHA_SIZE, 8,
        GLX_DEPTH_SIZE, 16,
        None
    };

    int numfbconfigs = 0;
    GLXFBConfig* fbconfigs = glXChooseFBConfig( xengine->m_display,  DefaultScreen( xengine->m_display ), visdata, &numfbconfigs );
    m_fbconfig = 0;
    for ( int i=0; i<numfbconfigs; i++ ) {
        m_visual = (XVisualInfo*)glXGetVisualFromFBConfig( xengine->m_display, fbconfigs[i] );
        if ( !m_visual ) {
            continue;
        }
        m_pictFormat = XRenderFindVisualFormat( xengine->m_display, m_visual->visual );
        if ( !m_pictFormat ) {
            continue;
        }
        m_fbconfig = fbconfigs[i];
        if ( m_pictFormat->direct.alphaMask > 0 ) {
            break;
        }
    }

    if ( !m_fbconfig ) {
        fprintf( stderr, "Couldn't find a matching FB config for a transparent OpenGL window!\n");
    }

    m_cmap = XCreateColormap( xengine->m_display, xengine->m_root, m_visual->visual, AllocNone );

    XSetWindowAttributes attributes;
    attributes.colormap = m_cmap;
    attributes.background_pixmap = None;
    attributes.border_pixmap = None;
    attributes.border_pixel = 0;
    // Disable window decorations.
    attributes.override_redirect = True;
    // Make sure we know when we've been successfully destroyed later!
    attributes.event_mask = StructureNotifyMask;
    unsigned long valueMask = CWOverrideRedirect | CWEventMask | CWBackPixmap | CWColormap | CWBorderPixel;


    // Create the window
    m_window = XCreateWindow( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(),
                              0, m_visual->depth, InputOutput,
                              m_visual->visual, valueMask, &attributes );

    if ( !m_window ) {
        fprintf( stderr, "Couldn't create a GL window!\n");
    }

    m_glxWindow = m_window;

    static char title[] = "OpenGL Slop";
    XWMHints* startup_state = XAllocWMHints();
    startup_state->initial_state = NormalState;
    startup_state->flags = StateHint;
    XTextProperty textprop;
    textprop.value = (unsigned char*)title;
    textprop.encoding = XA_STRING;
    textprop.format = 8;
    textprop.nitems = strlen( title );
    XSizeHints sizehints;
    sizehints.x = 0;
    sizehints.y = 0;
    sizehints.width = xengine->getWidth();
    sizehints.height = xengine->getHeight();
    sizehints.flags = USPosition | USSize;
    XClassHint classhints;
    char name[] = "slop";
    classhints.res_name = name;
    classhints.res_class = name;
    XSetClassHint( xengine->m_display, m_window, &classhints );
    XSetWMProperties( xengine->m_display, m_window, &textprop, &textprop, NULL, 0, &sizehints, startup_state, NULL );
    XFree( startup_state );

    // Make it so all input falls through
    XRectangle rect;
    rect.x = rect.y = rect.width = rect.height = 0;
    XShapeCombineRectangles( xengine->m_display, m_window, ShapeInput, 0, 0, &rect, 1, ShapeSet, 0);

    XMapWindow( xengine->m_display, m_window );

    int dummy;
    if ( !glXQueryExtension( xengine->m_display, &dummy, &dummy ) ) {
        fprintf( stderr, "OpenGL is not supported!\n" );
    }
    m_renderContext = glXCreateNewContext( xengine->m_display, m_fbconfig, GLX_RGBA_TYPE, 0, True );
    if ( !m_renderContext ) {
        fprintf( stderr, "Failed to create a GL context.\n" );
    }
    if ( !glXMakeContextCurrent( xengine->m_display, m_glxWindow, m_glxWindow, m_renderContext ) ) {
        fprintf( stderr, "Failed to attach GL context to window!\n" );
    }
    GLenum err = glewInit();
    if ( GLEW_OK != err ) {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    }

    // Get an image of the entire desktop for use in shaders.
    XImage* image = XGetImage( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(), 0xffffffff, ZPixmap );
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &m_desktop);
    glBindTexture(GL_TEXTURE_2D, m_desktop);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, xengine->getWidth(), xengine->getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0])));
    XDestroyImage( image );

    glDisable(GL_TEXTURE_2D);
    m_framebuffer = new slop::Framebuffer( xengine->getWidth(), xengine->getHeight(), slop::Framebuffer::color, m_shader );
    m_framebuffer->bind();
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glClearColor( 0, 0, 0, 0 );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glXSwapBuffers( xengine->m_display, m_glxWindow );
    m_framebuffer->unbind();
}
Пример #20
0
x_picture_rep::~x_picture_rep () {
  XFreePixmap (the_gui->dpy, pm);
  if (im != NULL) XDestroyImage (im);
  if (bm != 0) XFreePixmap (the_gui->dpy, bm);
  if (data != NULL) tm_delete_array (data); }
Пример #21
0
Boolean Xvars::load_pixmap(Drawable* pixmap,Drawable* mask,
                           int dpyNum,char** xpmBits,Boolean fullSize) {
  // Just load XPM as is.
  if (fullSize) {
    XpmAttributes attr;
    attr.valuemask = XpmCloseness;
    attr.closeness = XPM_CLOSENESS;
    attr.alloc_close_colors = True;

    int val = 
      XpmCreatePixmapFromData(dpy[dpyNum],root[dpyNum],
                              xpmBits,
                              pixmap,mask,
                              &attr);
    XpmFreeAttributes(&attr);

    Boolean ret = (val == XpmSuccess);
    if (!*pixmap || (mask && !*mask)) {
      ret = False;
    }

    return ret; 
  }


  //// Load image and mask into memory, reduce them and put them up to the
  //// display server as a new pixmap and mask

  XImage* srcImage;
  XImage* srcMask;
  Size srcSize;

  // Load in src image from supplied data.
  XpmAttributes attr;
  attr.valuemask = XpmReturnPixels | XpmCloseness;
  attr.closeness = XPM_CLOSENESS;
  attr.alloc_close_colors = True;

  // Perhaps should use XpmReturnAllocPixels, neither gives the transparent 
  // value.
  int val = 
    XpmCreateImageFromData(dpy[dpyNum],
                           xpmBits,
                           &srcImage,(mask ? &srcMask : (XImage**)NULL),
                           &attr);
  srcSize.width = attr.width;
  srcSize.height = attr.height;
  if (val != XpmSuccess) {
    XpmFreeAttributes(&attr);
    return False;
  }
  // Must be even size.
  assert((srcSize.width % 2 == 0) && 
         (srcSize.height % 2 == 0));
  int depth = srcImage->depth;
  int bitmap_pad = srcImage->bitmap_pad;

  // Size of reduced, destination image.
  Size destSize;
  destSize.set(srcSize.width / 2,srcSize.height / 2);
  
  // Create image for dest data.
  char* destData = 
    new_bytes_for_image(destSize,depth,bitmap_pad);
  XImage *destImage = 
    XCreateImage(dpy[dpyNum],visual[dpyNum],depth,ZPixmap,0,
                 destData,destSize.width,destSize.height,
                 bitmap_pad,0);
  assert(destImage);

  // Create dest mask if needed.
  XImage *destMask;
  if (mask) {
    assert(srcMask->depth == 1);
    char* destMaskData = 
      new_bytes_for_image(destSize,1,bitmap_pad);
    destMask = 
      XCreateImage(dpy[dpyNum],visual[dpyNum],1,ZPixmap,0,
                   destMaskData,destSize.width,destSize.height,
                   bitmap_pad,0);
    assert(destMask);
  }
    
  // Do the pixel reduction.
  //  unstretch_image(dpyNum,destImage,srcImage,attr.pixels,attr.npixels);
  unstretch_image(dpyNum,destImage,srcImage,
                  attr.pixels,attr.npixels);
  if (mask) {
    unstretch_image(dpyNum,destMask,srcMask,NULL,0);
  }

  // Kill src image and mask.
  XpmFreeAttributes(&attr);
  XDestroyImage(srcImage);  
  if (mask) {
    XDestroyImage(srcMask);
  }
      
  // Create dest pixmap and mask
  *pixmap = XCreatePixmap(dpy[dpyNum],root[dpyNum],
                          destSize.width,destSize.height,
                          depth);
  if (!*pixmap) {
    // Should do more cleanup.
    return False;
  }
  if (mask) {
    *mask = XCreatePixmap(dpy[dpyNum],root[dpyNum],
                          destSize.width,destSize.height,
                          1);
    if (!*mask) {
      // Should do more cleanup.
      return False;
    }
  }

  // Put dest image and mask up to the display server.
  put_image(dpyNum,*pixmap,destImage,destSize);
  if (mask) {
    put_image(dpyNum,*mask,destMask,destSize);
  }

  // Kill dest image and mask
  destroy_image(destImage);
  if (mask) {
    destroy_image(destMask);
  }
  return True;
}
Пример #22
0
/* This function checks that it is actually really possible to create an image
   using XShm */
gboolean
ximageutil_check_xshm_calls (GstXContext * xcontext)
{
  XImage *ximage;
  XShmSegmentInfo SHMInfo;
  size_t size;
  int (*handler) (Display *, XErrorEvent *);
  gboolean result = FALSE;
  gboolean did_attach = FALSE;

  g_return_val_if_fail (xcontext != NULL, FALSE);

  /* Sync to ensure any older errors are already processed */
  XSync (xcontext->disp, FALSE);

  /* Set defaults so we don't free these later unnecessarily */
  SHMInfo.shmaddr = ((void *) -1);
  SHMInfo.shmid = -1;

  /* Setting an error handler to catch failure */
  error_caught = FALSE;
  handler = XSetErrorHandler (ximageutil_handle_xerror);

  /* Trying to create a 1x1 ximage */
  GST_DEBUG ("XShmCreateImage of 1x1");

  ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
      xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);

  /* Might cause an error, sync to ensure it is noticed */
  XSync (xcontext->disp, FALSE);
  if (!ximage || error_caught) {
    GST_WARNING ("could not XShmCreateImage a 1x1 image");
    goto beach;
  }
  size = ximage->height * ximage->bytes_per_line;

  SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
  if (SHMInfo.shmid == -1) {
    GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
        size);
    goto beach;
  }

  SHMInfo.shmaddr = shmat (SHMInfo.shmid, 0, 0);
  if (SHMInfo.shmaddr == ((void *) -1)) {
    GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
    goto beach;
  }

  /* Delete the SHM segment. It will actually go away automatically
   * when we detach now */
  shmctl (SHMInfo.shmid, IPC_RMID, 0);

  ximage->data = SHMInfo.shmaddr;
  SHMInfo.readOnly = FALSE;

  if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
    GST_WARNING ("Failed to XShmAttach");
    goto beach;
  }

  /* Sync to ensure we see any errors we caused */
  XSync (xcontext->disp, FALSE);

  if (!error_caught) {
    did_attach = TRUE;
    /* store whether we succeeded in result */
    result = TRUE;
  }
beach:
  /* Sync to ensure we swallow any errors we caused and reset error_caught */
  XSync (xcontext->disp, FALSE);
  error_caught = FALSE;
  XSetErrorHandler (handler);

  if (did_attach) {
    XShmDetach (xcontext->disp, &SHMInfo);
    XSync (xcontext->disp, FALSE);
  }
  if (SHMInfo.shmaddr != ((void *) -1))
    shmdt (SHMInfo.shmaddr);
  if (ximage)
    XDestroyImage (ximage);
  return result;
}
Пример #23
0
int main(int argc, char ** argv){
	XImage* img,*img1;
	Window w;
	char** windows_names;
	int size;
	int i;
	char filename[20];
	

	/*This part contains an example of capturing and resizing a full-screen image*/
	img=fullScreenCapture();
	if(img!=NULL)
	{
		saveXImageToBitmap(img,"fullscreen1.bmp");
		img1=resizeBilinear(img,2048,1536);
		if(img1!=NULL)
		{
			saveXImageToBitmap(img1,"fullscreen1_resized.bmp");
			XDestroyImage(img1);
		}
		else fprintf(stderr,"No resized image\n");

		XDestroyImage(img);
	}

	/*Here the rectangular part is captured, resized and stored*/

	img=rectangleCapture(15,50,320,240);
	if(img!=NULL)
	{
		saveXImageToBitmap(img,"rectanglecapture_original.bmp");
		img1=resizeBicubic(img,800,600);
		if(img1!=NULL)
		{
			saveXImageToBitmap(img1,"rectanglecapture_800x600.bmp");
			XDestroyImage(img1);
		}
		else fprintf(stderr,"No resized image\n");
		XDestroyImage(img);
	}

	/*Here is the example of capturing particular windows*/

	getWindowsNames(&windows_names,&size);
	for(i=0;i<size;i++)
	{
		w=getWindowHandler(windows_names[i]);

		printf("%d\t%d\t%s\n",i,(int)w,windows_names[i]);

		if(w!=ERROR_HANDLER){
			img=windowCapture(w);
			if(img!=NULL)
			{
				sprintf(filename,"window%d.bmp",i);
				saveXImageToBitmap(img,filename);
				XDestroyImage(img);
			}
		}
	}

	for(i=0;i<size;i++){
		free(windows_names[i]);
	}
	free(windows_names);

	/*Example of capturing the contents of active window*/
	img=windowCapture(getActiveWindowHandler());
	if(img!=NULL)
		{
			saveXImageToBitmap(img,"active.bmp");
			XDestroyImage(img);
		}

	return 0;

}
int CaptureAndCompare(Display* display, Window desktop, XImage* baseimg,
		XImage* newimg, unsigned int* block_n)
{
	int block_num = 0, block_n_index = 0;//the length of block_n,新添加的指针索引变量block_n_index
	int screen_width = (int) baseimg->width;
	//int screen_height = (int) baseimg->height;

	int tile_width = 64, tile_height = 64, i = 0, j = 0;
	int n_x = (baseimg->width - 1) / tile_width + 1, tail_x = baseimg->width
			- tile_width * (n_x - 1);
	int n_y = (baseimg->height - 1) / tile_height + 1, tail_y = baseimg->height
			- tile_height * (n_y - 1);
	int tile_diff[n_x * n_y];	//save the next frame diff
	//unsigned int tile_diff[264];
	//compare 2 frames ,TileDiff
	{
		int k = 0, xx = 0, j, i;
		srand((int) time(NULL));
		for (i = 0; i < n_y - 1; i++)
		{
			j = (int) (((float) tile_height) * rand() / RAND_MAX)
					+ tile_height * i;    //the scan line
			for (xx = 0; xx < n_x - 1; xx++)
				tile_diff[k++] = XImageDataCmp(
						baseimg->data + j * screen_width * 4
								+ xx * tile_width * 4,
						newimg->data + j * screen_width * 4
								+ xx * tile_width * 4, tile_width * 4);
			tile_diff[k++] = XImageDataCmp(
					baseimg->data + j * screen_width * 4 + xx * tile_width * 4,
					newimg->data + j * screen_width * 4 + xx * tile_width * 4,
					tail_x * 4);
		}
		j = (int) (((float) tail_y) * rand() / RAND_MAX) + tile_height * i; //the scan line
		for (xx = 0; xx < n_x - 1; xx++)
			tile_diff[k++] = XImageDataCmp(
					baseimg->data + j * screen_width * 4 + xx * tile_width * 4,
					newimg->data + j * screen_width * 4 + xx * tile_width * 4,
					tile_width * 4);
		tile_diff[k++] = XImageDataCmp(
				baseimg->data + j * screen_width * 4 + xx * tile_width * 4,
				newimg->data + j * screen_width * 4 + xx * tile_width * 4,
				tail_x * 4);
	}    //compare 2 frames done;save result to tile_diff[]
	for (i = 0; i < n_y; i++)    //calculate block_num
		for (j = 0; j < n_x; j++)
			if (tile_diff[i * n_x + j])
				block_num++;
	if (!block_num)
		return 0;
	//if 更新基础帧
	if (block_num >= (n_x * n_y * 0.5))
	{
		XDestroyImage(baseimg);
		baseimg = newimg;
		return 1;    //更新基础帧
	}
	//这里是函数体,比较不同并保存(按block_x,block_y,block_width,block_height)数据在block_n
	for (i = 0; i < n_y - 1; i++)
	{
		for (j = 0; j < n_x - 1; j++)
			if (tile_diff[i * n_x + j])
			{
				*(block_n + block_n_index++) = j * tile_width;    //x
				*(block_n + block_n_index++) = i * tile_height;    //y
				*(block_n + block_n_index++) = tile_width;    //w
				*(block_n + block_n_index++) = tile_height;    //h
			}
		//the last column
		if (tile_diff[i * n_x + j])
		{
			*(block_n + block_n_index++) = j * tile_width;    //x
			*(block_n + block_n_index++) = i * tile_height;    //y
			*(block_n + block_n_index++) = tail_x;    //;w
			*(block_n + block_n_index++) = tile_height;    //h
		}
	}
	//the last line
	for (j = 0; j < n_x - 1; j++)
		if (tile_diff[i * n_x + j])
		{
			*(block_n + block_n_index++) = j * tile_width;    //x
			*(block_n + block_n_index++) = i * tile_height;    //y
			*(block_n + block_n_index++) = tile_width;    //w
			*(block_n + block_n_index++) = tail_y;    //;h
		}
	//the last block
	if (tile_diff[i * n_x + j])
	{
		*(block_n + block_n_index++) = j * tile_width;    //x
		*(block_n + block_n_index++) = i * tile_height;    //y
		*(block_n + block_n_index++) = tail_x;    //;w
		*(block_n + block_n_index++) = tail_y;    //;h
	}
	{    //进行区域合并
		struct DiffBlock *head = NULL;
		block_num = ConcatenateDiffBlocks(head, block_n, block_num * 4);
	}

	return block_num;  //返回block_n的长度(按block_x,block_y,block_width,block_height)
}
Пример #25
0
void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc,
                              int ySrc, int xDest, int yDest, int width,
                              int height, bool blend )
{
    // Get the bitmap size if necessary
    if( width == -1 )
    {
        width = rBitmap.getWidth();
    }
    else if( width > rBitmap.getWidth() )
    {
        msg_Dbg( getIntf(), "bitmap width too small (%i)", rBitmap.getWidth() );
        width = rBitmap.getWidth();
    }
    if( height == -1 )
    {
        height = rBitmap.getHeight();
    }
    else if( height > rBitmap.getHeight() )
    {
        msg_Dbg( getIntf(), "bitmap height too small (%i)", rBitmap.getHeight()
                                 );
        height = rBitmap.getHeight();
    }

    // Nothing to draw if width or height is null
    if( width == 0 || height == 0 )
    {
        return;
    }

    // Safety check for debugging purpose
    if( xDest + width > m_width || yDest + height > m_height )
    {
        msg_Dbg( getIntf(), "bitmap too large" );
        return;
    }

    // Get a buffer on the image data
    uint8_t *pBmpData = rBitmap.getData();
    if( pBmpData == NULL )
    {
        // Nothing to draw
        return;
    }

    // Get the image from the pixmap
    XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width,
                                height, AllPlanes, ZPixmap );
    if( pImage == NULL )
    {
        msg_Dbg( getIntf(), "XGetImage returned NULL" );
        return;
    }
    char *pData = pImage->data;

    // Get the padding of this image
    int pad = pImage->bitmap_pad >> 3;
    int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad;

    // Mask for transparency
    Region mask = XCreateRegion();

    // Get a pointer on the right X11Display::makePixel method
    X11Display::MakePixelFunc_t makePixelFunc = ( blend ?
        m_rDisplay.getBlendPixel() : m_rDisplay.getPutPixel() );

    // Skip the first lines of the image
    pBmpData += 4 * ySrc * rBitmap.getWidth();

    // Copy the bitmap on the image and compute the mask
    for( int y = 0; y < height; y++ )
    {
        // Skip uninteresting bytes at the beginning of the line
        pBmpData += 4 * xSrc;
        // Flag to say whether the previous pixel on the line was visible
        bool wasVisible = false;
        // Beginning of the current visible segment on the line
        int visibleSegmentStart = 0;
        for( int x = 0; x < width; x++ )
        {
            uint8_t b = *(pBmpData++);
            uint8_t g = *(pBmpData++);
            uint8_t r = *(pBmpData++);
            uint8_t a = *(pBmpData++);
            // Draw the pixel
            (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a );
            pData += XPIXELSIZE;
            if( a > 0 )
            {
                // Pixel is visible
                if( ! wasVisible )
                {
                    // Beginning of a visible segment
                    visibleSegmentStart = x;
                }
                wasVisible = true;
            }
            else
            {
                // Pixel is transparent
                if( wasVisible )
                {
                    // End of a visible segment: add it to the mask
                    addHSegmentInRegion( mask, visibleSegmentStart, x, y );
                }
                wasVisible = false;
            }
        }
        if( wasVisible )
        {
            // End of a visible segment: add it to the mask
            addHSegmentInRegion( mask, visibleSegmentStart, width, y );
        }
        pData += shift;
        // Skip uninteresting bytes at the end of the line
        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
    }

    // Apply the mask to the graphics context
    XOffsetRegion( mask, xDest, yDest );
    XSetRegion( XDISPLAY, m_gc, mask );
    // Copy the image on the pixmap
    XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width,
               height);
    XDestroyImage( pImage );

    // Add the bitmap mask to the global graphics mask
    Region newMask = XCreateRegion();
    XUnionRegion( mask, m_mask, newMask );
    XDestroyRegion( m_mask );
    m_mask = newMask;

    XDestroyRegion( mask );
}
int CompressAndWrite(const char* filename, int frame_rate,
		int video_time_length, const char* SeverIpAddress)
{
	Window desktop;
	Display* display;
	XImage* base_img;
	XImage* new_img;
	unsigned int Frame_number = 0;
	unsigned int block_x;
	unsigned int block_y;
	unsigned int block_width;
	unsigned int block_height;
	unsigned long uncompress_block_size = 0;
	unsigned long blen;
	unsigned char* buf = NULL;
	int block_num = 0;
	char* block_data = NULL;
	display = XOpenDisplay(NULL); //connect to a local display
	if (NULL == display)
	{
		printf("CaptureDesktop cannot get root window");
		return 0;
	}
	desktop = RootWindow(display, 0); //refer to root window
	if (desktop == 0)
	{
		printf("CaptureDesktop cannot get root window");
		return 0;
	}
	//get the image of the root window
	//FILE *fp = fopen(filename, "wb");
	gzFile gfp = gzopen(filename, "wb9"); //用于测试文件格式
	if (gfp == 0)
	{
		printf("could not open  file!!");
		return 0;
	}
	unsigned int screen_width = DisplayWidth(display, 0);
	unsigned int screen_height = DisplayHeight(display, 0);
	base_img = XGetImage(display, desktop, 0, 0, screen_width, screen_height,
			~0,
			ZPixmap);
	/* new_img = XCreateImage(display, DefaultVisual(display, 0), 24, ZPixmap, 0,
	 NULL, screen_width, screen_height, 32, 0);*/
	time_t start_time, end_time;
	time(&start_time);
	struct timeval start_tv;
	gettimeofday(&start_tv, NULL);
	//printf("%s", ctime(&start_time));
	int x = 0; //测试用,可删除
	while (1)
	{ //控制帧率的块
		x += block_num; //测试用,可删除
		new_img = XGetImage(display, desktop, 0, 0, screen_width, screen_height,
				~0,
				ZPixmap);
		unsigned int* block_parameter;
		int i = 0; //处理blocks的循环变量
		if ((block_parameter = (unsigned int*) malloc(2200)) == NULL)
		{
			printf("no enough memory!\n");
			return -1;
		}
		block_num = CaptureAndCompare(display, desktop, base_img, new_img,
				block_parameter);

		if (Frame_number != 0 && block_num == 0)
		{
			size_t no_update = 0;
			//fwrite(&no_update, sizeof(size_t), 1, fp);
			gzwrite(gfp, &no_update, sizeof(size_t)); //用于测试文件格式
			continue;
		}
		if (Frame_number == 0)
		{
			block_num = 1;
			block_x = 0;
			block_y = 0;
			block_width = screen_width;
			block_height = screen_height;
		}

		for (i = 0; i < block_num; i++)
		{
			if (Frame_number != 0)
			{ //赋值给block变量
				block_x = *(block_parameter + i * 4);
				block_y = *(block_parameter + i * 4 + 1);
				block_width = *(block_parameter + i * 4 + 2);
				block_height = *(block_parameter + i * 4 + 3);
				printf("%d %d %d %d 帧号:%d 块数:%d\n", block_x, block_y,
						block_width, block_height, Frame_number, x);
			}

			uncompress_block_size = block_width * block_height * 4;
			if ((block_data = (char*) malloc(uncompress_block_size)) == NULL)
			{
				printf("no enough memory!\n");
				return -1;
			}
			if (GetDatablockFromXImage(new_img, block_data, block_x, block_y,
					block_width, block_height) != 1)
			{
				printf("the GetDatablockFromXImage function has an error!\n");
				return -1;
			}

			//压缩部分 计算缓冲区大小,并为其分配内存
			blen = compressBound(uncompress_block_size);  //压缩后的长度是不会超过blen的
			if ((buf = (unsigned char*) malloc(sizeof(unsigned char) * blen))
					== NULL)
			{
				printf("no enough memory!\n");
				return -1;
			}

			//压缩
			if (compress(buf, &blen, (unsigned char*) block_data,
					uncompress_block_size) != Z_OK)
			{
				printf("compress failed!\n");
				return -1;
			}
			/*			WriteBlockToDisk(buf, blen, fp, Frame_number, block_x, block_y,
			 block_width, block_height);*/
			if (SeverIpAddress != NULL)
			{  //直播传输

			}
			gzWriteBlockToDisk(buf, blen, gfp, Frame_number, block_x, block_y,
					block_width, block_height);  //用于测试文件格式
			if (buf != NULL || block_data != NULL)
			{
				free(buf);
				free(block_data);
				block_data = NULL;
				buf = NULL;

			}
		}

		Frame_number++;  //帧号
		free(block_parameter);
		block_parameter = NULL;
		XDestroyImage(new_img);

		while (1)
		{  //控制帧率
			struct timeval end_tv;
			gettimeofday(&end_tv, NULL);
			if (((end_tv.tv_sec - start_tv.tv_sec)
					+ 0.000001 * (end_tv.tv_usec - start_tv.tv_usec))
					>= Frame_number * 1.0 / frame_rate)
			{
				break;
			}
		}
		time(&end_time);
		if (difftime(end_time, start_time) >= video_time_length)
		{
			break;
		}
		//控制帧率的块end
	}

	/* 释放内存 */
	//fflush(fp);
	//fclose(fp);
	//fp = NULL;
	gzclose(gfp);	//用于测试文件格式
	XDestroyImage(base_img);
	XCloseDisplay(display);

	printf("CompressAndWrite performs successfully!\n");
	return 1;

}
Пример #27
0
PlatformFont::CharInfo &x86UNIXFont::getCharInfo(const UTF16 ch) const
{
  Display *display = XOpenDisplay(getenv("DISPLAY"));
  if (!display )
    AssertFatal(false, "createFont: cannot connect to X server");

  static PlatformFont::CharInfo c;
  dMemset(&c, 0, sizeof(c));
  c.bitmapIndex = 0;
  c.xOffset     = 0;
  c.yOffset     = 0;

  XftFont *fontInfo  = XftFontOpenName(display, DefaultScreen(display), mFontName);
  if (!fontInfo)
    AssertFatal(false, "createFont: cannot load font");

  int screen = DefaultScreen(display);
  // Create the pixmap to draw on.
  Drawable pixmap = XCreatePixmap(display,
				  DefaultRootWindow(display),
				  fontInfo->max_advance_width,
				  fontInfo->height,
				  DefaultDepth(display, screen));
  // And the Xft wrapper around it.
  XftDraw *draw = XftDrawCreate(display,
                                pixmap,
                                DefaultVisual(display, screen),
                                DefaultColormap(display, screen));
  // Allocate some colors, we don't use XftColorAllocValue here as that
  // Don't appear to function correctly (or I'm using it wrong) As we only do
  // this twice per new un cached font it isn't that big of a penalty. (Each
  // call to XftColorAllocName involves a round trip to the X Server)
  XftColor black, white;
  XftColorAllocName(display,
                    DefaultVisual(display, screen),
                    DefaultColormap(display, screen),
                    "black",
                    &black);
  // White
  XftColorAllocName(display,
                    DefaultVisual(display, screen),
                    DefaultColormap(display, screen),
                    "white",
                    &white);
  
  XGlyphInfo charinfo;
  XftTextExtents16(display, fontInfo, &ch, 1, &charinfo);
  c.height     = fontInfo->height;
  c.xOrigin    = 0; 
  c.yOrigin    = fontInfo->ascent;
  c.xIncrement = charinfo.xOff;
  c.width      = charinfo.xOff;
  // kick out early if the character is undrawable
  if( c.width == 0 || c.height == 0)
    return c;

  // allocate a greyscale bitmap and clear it.
  int bitmapDataSize = c.width * c.height;
  c.bitmapData = new U8[bitmapDataSize];
  dMemset(c.bitmapData, 0, bitmapDataSize);

  XftDrawRect (draw, &black, 0, 0, fontInfo->max_advance_width, fontInfo->height);
  XftDrawString16 (draw, &white, fontInfo, 0, fontInfo->ascent, &ch, 1);
  // grab the pixmap image

  XImage *ximage = XGetImage(display, pixmap, 0, 0, 
			     charinfo.xOff, fontInfo->height, 
			     AllPlanes, XYPixmap);
  if (!ximage)
    AssertFatal(false, "cannot get x image");
  int x, y;

  // grab each pixel and store it in the scratchPad
  for(y = 0; y < fontInfo->height; y++)
  {
    for(x = 0; x < charinfo.xOff; x++)
      c.bitmapData[y * charinfo.xOff + x] = static_cast<U8>(XGetPixel(ximage, x, y));
  }
  XDestroyImage(ximage);

  XftColorFree(display, DefaultVisual(display, screen),
               DefaultColormap(display, screen), &black);
  XftColorFree(display, DefaultVisual(display, screen),
               DefaultColormap(display, screen), &white);
  XftDrawDestroy(draw);
  XFreePixmap(display, pixmap);
  XCloseDisplay(display);

  return c;
}
Пример #28
0
static void getMyXImage(void)
{
#ifdef HAVE_SHM
    if (mLocalDisplay && XShmQueryExtension(mDisplay))
        Shmem_Flag = 1;
    else
    {
        Shmem_Flag = 0;
        mp_msg(MSGT_VO, MSGL_WARN,
               "Shared memory not supported\nReverting to normal Xlib\n");
    }
    if (Shmem_Flag)
        CompletionType = XShmGetEventBase(mDisplay) + ShmCompletion;

    if (Shmem_Flag)
    {
        myximage =
            XShmCreateImage(mDisplay, vinfo.visual, depth, ZPixmap, NULL,
                            &Shminfo[0], image_width, image_height);
        if (myximage == NULL)
        {
            mp_msg(MSGT_VO, MSGL_WARN,
                   "Shared memory error,disabling ( Ximage error )\n");
            goto shmemerror;
        }
        Shminfo[0].shmid = shmget(IPC_PRIVATE,
                                  myximage->bytes_per_line *
                                  myximage->height, IPC_CREAT | 0777);
        if (Shminfo[0].shmid < 0)
        {
            XDestroyImage(myximage);
            mp_msg(MSGT_VO, MSGL_V, "%s\n", strerror(errno));
            //perror( strerror( errno ) );
            mp_msg(MSGT_VO, MSGL_WARN,
                   "Shared memory error,disabling ( seg id error )\n");
            goto shmemerror;
        }
        Shminfo[0].shmaddr = (char *) shmat(Shminfo[0].shmid, 0, 0);

        if (Shminfo[0].shmaddr == ((char *) -1))
        {
            XDestroyImage(myximage);
            if (Shminfo[0].shmaddr != ((char *) -1))
                shmdt(Shminfo[0].shmaddr);
            mp_msg(MSGT_VO, MSGL_WARN,
                   "Shared memory error,disabling ( address error )\n");
            goto shmemerror;
        }
        myximage->data = Shminfo[0].shmaddr;
        ImageData = (unsigned char *) myximage->data;
        Shminfo[0].readOnly = False;
        XShmAttach(mDisplay, &Shminfo[0]);

        XSync(mDisplay, False);

        if (gXErrorFlag)
        {
            XDestroyImage(myximage);
            shmdt(Shminfo[0].shmaddr);
            mp_msg(MSGT_VO, MSGL_WARN, "Shared memory error,disabling.\n");
            gXErrorFlag = 0;
            goto shmemerror;
        } else
            shmctl(Shminfo[0].shmid, IPC_RMID, 0);

        {
            static int firstTime = 1;

            if (firstTime)
            {
                mp_msg(MSGT_VO, MSGL_V, "Sharing memory.\n");
                firstTime = 0;
            }
        }
    } else
    {
      shmemerror:
        Shmem_Flag = 0;
#endif
        myximage = XCreateImage(mDisplay, vinfo.visual, depth, ZPixmap,
                             0, NULL, image_width, image_height, 8, 0);
        ImageDataOrig = malloc(myximage->bytes_per_line * image_height + 32);
        myximage->data = ImageDataOrig + 16 - ((long)ImageDataOrig & 15);
        memset(myximage->data, 0, myximage->bytes_per_line * image_height);
        ImageData = myximage->data;
#ifdef HAVE_SHM
    }
#endif
}
Пример #29
0
static void vo_x11_zoom (int mulriple)
{
    unsigned long xswamask, event_mask;
    XSetWindowAttributes xswa;
    XSizeHints hint;
    XVisualInfo xvinfo;

    if (dlpctxp->pwidth * mulriple > screen_width || dlpctxp->pheight * mulriple > screen_height)
    {
        av_log (NULL, AV_LOG_INFO, "vo x11: zoom %d will > fullscrren\n", mulriple);
        return;
    }

    vo_lock ();

    if (Xvowin != None)
    {
        XClearWindow (Xdisplay, Xvowin);
        XUnmapWindow (Xdisplay, Xvowin);
        XDestroyWindow (Xdisplay, Xvowin);
        Xvowin = None;
    }
    if (Ximg)
    {
        Ximg->data = NULL;
        XDestroyImage (Ximg);
        Ximg = NULL;
    }

    avpicture_free (my_pic);
    av_free (my_pic);

    xswamask = CWBackingStore | CWBorderPixel;

    dw = dlpctxp->pwidth * mulriple;
    dh = dlpctxp->pheight * mulriple;

    dx = (screen_width - dw) / 2;
    dy = (screen_height - dh) / 2;

    Xdepth = XDefaultDepth (Xdisplay, 0);
    if (!XMatchVisualInfo (Xdisplay, Xscreen, Xdepth, DirectColor, &xvinfo))
        XMatchVisualInfo (Xdisplay, Xscreen, Xdepth, TrueColor, &xvinfo);

    xswa.background_pixel = 0;
    xswa.border_pixel = 0;
    xswa.backing_store = Always;
    xswa.bit_gravity = StaticGravity;

    Xvowin = XCreateWindow (Xdisplay, Xrootwin, dx, dy, dw, dh, 0, Xdepth, CopyFromParent, CopyFromParent, xswamask, &xswa);

    hint.x = dx;
    hint.y = dy;
    hint.width = dw;
    hint.height = dh;
    hint.flags = PPosition | PSize;
    XSetStandardProperties (Xdisplay, Xvowin, Xtitle, Xtitle, None, NULL, 0, &hint);

    XMapWindow (Xdisplay, Xvowin);
    XClearWindow (Xdisplay, Xvowin);

    event_mask = StructureNotifyMask | KeyPressMask | ExposureMask;
    XSelectInput (Xdisplay, Xvowin, event_mask);
    XSync (Xdisplay, False);

    Ximg = XCreateImage (Xdisplay, xvinfo.visual, Xdepth, ZPixmap, 0, NULL, dw, dh, 8, 0);

    if (dw < 600)
        Xfont = Xfont_120;
    else
        Xfont = Xfont_240;

    if (Xfont)
        XSetFont (Xdisplay, Xvogc, Xfont->fid);

    my_pic = av_mallocz (sizeof (AVPicture));
    avpicture_alloc (my_pic, my_pic_fmt, dw, dh);

    vo_unlock ();
}
Пример #30
0
int fbx_init(fbx_struct *fb, fbx_wh wh, int width_, int height_, int useShm)
{
	int width, height;
	int rmask, gmask, bmask, ps, i;
	#ifdef _WIN32
	BMINFO bminfo;  HBITMAP hmembmp=0;  RECT rect;  HDC hdc=NULL;
	#else
	XWindowAttributes xwa;  int shmok=1, alphaFirst, pixmap=0;
	#endif

	if(!fb) _throw("Invalid argument");

	#ifdef _WIN32

	if(!wh) _throw("Invalid argument");
	_w32(GetClientRect(wh, &rect));
	if(width_>0) width=width_;
	else
	{
		width=rect.right-rect.left;  if(width<=0) width=MINWIDTH;
	}
	if(height_>0) height=height_;
	else
	{
		height=rect.bottom-rect.top;  if(height<=0) height=MINHEIGHT;
	}
	if(fb->wh==wh)
	{
		if(width==fb->width && height==fb->height && fb->hmdc && fb->hdib
			&& fb->bits)
			return 0;
		else if(fbx_term(fb)==-1) return -1;
	}
	memset(fb, 0, sizeof(fbx_struct));
	fb->wh=wh;

	_w32(hdc=GetDC(fb->wh));
	_w32(fb->hmdc=CreateCompatibleDC(hdc));
	_w32(hmembmp=CreateCompatibleBitmap(hdc, width, height));
	_w32(GetDeviceCaps(hdc, RASTERCAPS)&RC_BITBLT);
	_w32(GetDeviceCaps(fb->hmdc, RASTERCAPS)&RC_DI_BITMAP);
	bminfo.bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	bminfo.bmi.bmiHeader.biBitCount=0;
	_w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS));
	_w32(GetDIBits(fb->hmdc, hmembmp, 0, 1, NULL, &bminfo.bmi, DIB_RGB_COLORS));
	_w32(DeleteObject(hmembmp));  hmembmp=0;
		/* (we only needed it to get the screen properties) */
	ps=bminfo.bmi.bmiHeader.biBitCount/8;
	if(width>0) bminfo.bmi.bmiHeader.biWidth=width;
	if(height>0) bminfo.bmi.bmiHeader.biHeight=height;
	fb->width=bminfo.bmi.bmiHeader.biWidth;
	fb->height=bminfo.bmi.bmiHeader.biHeight;

	if(ps<3)
	{
		/* Make the buffer BGRA */
		bminfo.bmi.bmiHeader.biCompression=BI_BITFIELDS;
		bminfo.bmi.bmiHeader.biBitCount=32;
		ps=4;
		(*(DWORD *)&bminfo.bmi.bmiColors[0])=0xFF0000;
		(*(DWORD *)&bminfo.bmi.bmiColors[1])=0xFF00;
		(*(DWORD *)&bminfo.bmi.bmiColors[2])=0xFF;
	}

	fb->pitch=BMPPAD(fb->width*ps);  /* Windoze bitmaps are always padded */

	if(bminfo.bmi.bmiHeader.biCompression==BI_BITFIELDS)
	{
		rmask=(*(DWORD *)&bminfo.bmi.bmiColors[0]);
		gmask=(*(DWORD *)&bminfo.bmi.bmiColors[1]);
		bmask=(*(DWORD *)&bminfo.bmi.bmiColors[2]);
	}
	else
	{
		rmask=0xFF0000;
		gmask=0xFF00;
		bmask=0xFF;
	}

	fb->format=-1;
	for(i=0; i<FBX_FORMATS; i++)
		if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i]
			&& ps==fbx_ps[i] && fbx_alphafirst[i]==0) fb->format=i;
	if(fb->format==-1) _throw("Display has unsupported pixel format");

	bminfo.bmi.bmiHeader.biHeight=-bminfo.bmi.bmiHeader.biHeight;
		/* (our convention is top-down) */
	_w32(fb->hdib=CreateDIBSection(hdc, &bminfo.bmi, DIB_RGB_COLORS,
		(void **)&fb->bits, NULL, 0));
	_w32(SelectObject(fb->hmdc, fb->hdib));
	ReleaseDC(fb->wh, hdc);
	return 0;

	finally:
	if(hmembmp) DeleteObject(hmembmp);
	if(hdc) ReleaseDC(fb->wh, hdc);

	#else

	if(!wh.dpy || !wh.d) _throw("Invalid argument");
	if(wh.v)
	{
		_x11(XGetGeometry(wh.dpy, wh.d, &xwa.root, &xwa.x, &xwa.y,
			(unsigned int *)&xwa.width, (unsigned int *)&xwa.height,
			(unsigned int *)&xwa.border_width, (unsigned int *)&xwa.depth));
		xwa.visual=wh.v;
		useShm=0;
		pixmap=1;
	}
	else
	{
		_x11(XGetWindowAttributes(wh.dpy, wh.d, &xwa));
	}
	if(width_>0) width=width_;  else width=xwa.width;
	if(height_>0) height=height_;  else height=xwa.height;
	if(fb->wh.dpy==wh.dpy && fb->wh.d==wh.d)
	{
		if(width==fb->width && height==fb->height && fb->xi && fb->xgc && fb->bits)
			return 0;
		else if(fbx_term(fb)==-1) return -1;
	}
	memset(fb, 0, sizeof(fbx_struct));
	fb->wh.dpy=wh.dpy;  fb->wh.d=wh.d;

	#ifdef USESHM
	if(!useShm)
	{
		static int alreadyWarned=0;
		if(!alreadyWarned && warningFile)
		{
			fprintf(warningFile, "[FBX] Disabling shared memory blitting\n");
			alreadyWarned=1;
		}
	}
	if(useShm && XShmQueryExtension(fb->wh.dpy))
	{
		static int alreadyWarned=0;
		fb->shminfo.shmid=-1;
		if(!(fb->xi=XShmCreateImage(fb->wh.dpy, xwa.visual, xwa.depth,
			ZPixmap, NULL, &fb->shminfo, width, height)))
		{
			useShm=0;  goto noshm;
		}
		if((fb->shminfo.shmid=shmget(IPC_PRIVATE,
			fb->xi->bytes_per_line*fb->xi->height+1, IPC_CREAT|0777))==-1)
		{
			useShm=0;  XDestroyImage(fb->xi);  goto noshm;
		}
		if((fb->shminfo.shmaddr=fb->xi->data
			=(char *)shmat(fb->shminfo.shmid, 0, 0))==(char *)-1)
		{
			useShm=0;  XDestroyImage(fb->xi);
			shmctl(fb->shminfo.shmid, IPC_RMID, 0);  goto noshm;
		}
		fb->shminfo.readOnly=False;
		XLockDisplay(fb->wh.dpy);
		XSync(fb->wh.dpy, False);
		prevHandler=XSetErrorHandler(xhandler);
		extok=1;
		serial=NextRequest(fb->wh.dpy);
		XShmAttach(fb->wh.dpy, &fb->shminfo);
		XSync(fb->wh.dpy, False);
		XSetErrorHandler(prevHandler);
		shmok=extok;
		if(!alreadyWarned && !shmok && warningFile)
		{
			fprintf(warningFile,
				"[FBX] WARNING: MIT-SHM extension failed to initialize (this is normal on a\n");
			fprintf(warningFile,
				"[FBX]    remote connection.)  Will use X Pixmap drawing instead.\n");
			alreadyWarned=1;
		}
		XUnlockDisplay(fb->wh.dpy);
		if(shmok)
		{
			char *env=getenv("FBX_USESHMPIXMAPS");
			if(env && !strcmp(env, "1"))
			{
				static int alreadyWarned=0;
				if(!alreadyWarned && warningFile)
				{
					fprintf(warningFile, "[FBX] Using MIT-SHM pixmaps\n");
					alreadyWarned=1;
				}
				fb->pm=XShmCreatePixmap(fb->wh.dpy, fb->wh.d, fb->shminfo.shmaddr,
					&fb->shminfo, width, height, xwa.depth);
				if(!fb->pm) shmok=0;
			}
		}
		shmctl(fb->shminfo.shmid, IPC_RMID, 0);
		if(!shmok)
		{
			useShm=0;  XDestroyImage(fb->xi);  shmdt(fb->shminfo.shmaddr);
			shmctl(fb->shminfo.shmid, IPC_RMID, 0);  goto noshm;
		}
		fb->xattach=1;  fb->shm=1;
	}
	else if(useShm)
	{
		static int alreadyWarned=0;
		if(!alreadyWarned && warningFile)
		{
			fprintf(warningFile,
				"[FBX] WARNING: MIT-SHM extension not available.  Will use X pixmap\n");
			fprintf(warningFile, "[FBX]    drawing instead.\n");
			alreadyWarned=1;
		}
		useShm=0;
	}
	noshm:
	if(!useShm)
	#endif
	{
		if(!pixmap)
			_x11(fb->pm=XCreatePixmap(fb->wh.dpy, fb->wh.d, width, height,
				xwa.depth));
		_x11(fb->xi=XCreateImage(fb->wh.dpy, xwa.visual, xwa.depth, ZPixmap, 0,
			NULL, width, height, 8, 0));
		if((fb->xi->data=(char *)malloc(fb->xi->bytes_per_line*fb->xi->height+1))
			==NULL)
			_throw("Memory allocation error");
	}
	ps=fb->xi->bits_per_pixel/8;
	fb->width=fb->xi->width;
	fb->height=fb->xi->height;
	fb->pitch=fb->xi->bytes_per_line;
	if(fb->width!=width || fb->height!=height)
		_throw("Bitmap returned does not match requested size");
	rmask=fb->xi->red_mask;  gmask=fb->xi->green_mask;  bmask=fb->xi->blue_mask;
	alphaFirst=0;
	if(fb->xi->byte_order==MSBFirst)
	{
		if(ps<4)
		{
			rmask=fb->xi->blue_mask;  gmask=fb->xi->green_mask;
			bmask=fb->xi->red_mask;
		}
		else alphaFirst=1;
	}

	fb->format=-1;
	for(i=0; i<FBX_FORMATS; i++)
		if(rmask==fbx_rmask[i] && gmask==fbx_gmask[i] && bmask==fbx_bmask[i]
			&& ps==fbx_ps[i] && fbx_alphafirst[i]==alphaFirst) fb->format=i;
	if(fb->format==-1) _throw("Display has unsupported pixel format");

	fb->bits=fb->xi->data;
	fb->pixmap=pixmap;
	_x11(fb->xgc=XCreateGC(fb->wh.dpy, fb->pm? fb->pm:fb->wh.d, 0, NULL));
	return 0;

	finally:

	#endif

	fbx_term(fb);
	return -1;
}