static Bool scalefilterSetScaledPaintAttributes (CompWindow *w, WindowPaintAttrib *attrib) { Bool ret; FILTER_SCREEN (w->screen); SCALE_SCREEN (w->screen); UNWRAP (fs, ss, setScaledPaintAttributes); ret = (*ss->setScaledPaintAttributes) (w, attrib); WRAP (fs, ss, setScaledPaintAttributes, scalefilterSetScaledPaintAttributes); if (fs->matchApplied || (fs->filterInfo && fs->filterInfo->filterStringLength)) { SCALE_WINDOW (w); if (ret && !sw->slot) { ret = FALSE; attrib->opacity = 0; } } return ret; }
static void scalefilterInitFilterInfo (CompScreen *s) { FILTER_SCREEN (s); SCALE_SCREEN (s); ScaleFilterInfo *info = fs->filterInfo; memset (info->filterString, 0, sizeof (info->filterString)); info->filterStringLength = 0; info->textPixmap = None; info->textWidth = 0; info->textHeight = 0; info->timeoutHandle = 0; info->outputDevice = s->currentOutputDev; initTexture (s, &info->textTexture); matchInit (&info->match); matchCopy (&info->match, &fs->scaleMatch); info->origMatch = ss->currentMatch; ss->currentMatch = &info->match; }
static Bool scalefilterPaintOutput (CompScreen *s, const ScreenPaintAttrib *sAttrib, const CompTransform *transform, Region region, CompOutput *output, unsigned int mask) { Bool status; FILTER_SCREEN (s); UNWRAP (fs, s, paintOutput); status = (*s->paintOutput) (s, sAttrib, transform, region, output, mask); WRAP (fs, s, paintOutput, scalefilterPaintOutput); if (status && fs->filterInfo) { if ((output->id == ~0 || output->id == fs->filterInfo->outputDevice) && fs->filterInfo->textPixmap) { CompTransform sTransform = *transform; transformToScreenSpace (s, output, -DEFAULT_Z_CAMERA, &sTransform); glPushMatrix (); glLoadMatrixf (sTransform.m); scalefilterDrawFilterText (s, output); glPopMatrix (); } } return status; }
static void scalefilterUpdateFilter (CompScreen *s, CompMatch *match) { char filterMatch[2 * MAX_FILTER_TEXT_LEN]; unsigned int offset; FILTER_SCREEN (s); matchFini (match); matchInit (match); if (scalefilterGetFilterCaseInsensitive (s)) { strncpy (filterMatch, "ititle=", MAX_FILTER_TEXT_LEN); offset = 7; } else { strncpy (filterMatch, "title=", MAX_FILTER_TEXT_LEN); offset = 6; } wcstombs (filterMatch + offset, fs->filterInfo->filterString, MAX_FILTER_STRING_LEN); matchAddExp (match, 0, filterMatch); matchAddGroup (match, MATCH_OP_AND_MASK, &fs->scaleMatch); matchUpdate (s->display, match); }
/* * Filters list setting update callback */ static void colorFiltersChanged (CompScreen *s, CompOption *opt, ColorfilterScreenOptions num) { FILTER_SCREEN (s); /* Just set the filtersLoaded boolean to FALSE, unloadFilters will be * called in loadFilters */ cfs->filtersLoaded = FALSE; }
/* * Wrapper that enables filters if the window is filtered */ static void colorFilterDrawWindowTexture (CompWindow *w, CompTexture *texture, const FragmentAttrib *attrib, unsigned int mask) { int i, function; FILTER_SCREEN (w->screen); FILTER_WINDOW (w); /* Check if filters have to be loaded and load them if so * Maybe should this check be done only if a filter is going to be applied * for this texture? */ if (!cfs->filtersLoaded) loadFilters (w->screen, texture); /* Filter texture if : * o GL_ARB_fragment_program available * o Filters are loaded * o Texture's window is filtered */ /* Note : if required, filter window contents only and not decorations * (use that w->texture->name != texture->name for decorations) */ if (cfs->filtersCount && cfw->isFiltered && (colorfilterGetFilterDecorations (w->screen) || (texture->name == w->texture->name))) { FragmentAttrib fa = *attrib; if (cfs->currentFilter == 0) /* Cumulative filters mode */ { /* Enable each filter one by one */ for (i = 0; i < cfs->filtersCount; i++) { function = cfs->filtersFunctions[i]; if (function) addFragmentFunction (&fa, function); } } /* Single filter mode */ else if (cfs->currentFilter <= cfs->filtersCount) { /* Enable the currently selected filter if possible (i.e. if it * was successfully loaded) */ function = cfs->filtersFunctions[cfs->currentFilter - 1]; if (function) addFragmentFunction (&fa, function); } UNWRAP (cfs, w->screen, drawWindowTexture); (*w->screen->drawWindowTexture) (w, texture, &fa, mask); WRAP(cfs, w->screen, drawWindowTexture, colorFilterDrawWindowTexture); } else /* Not filtering */ { UNWRAP (cfs, w->screen, drawWindowTexture); (*w->screen->drawWindowTexture) (w, texture, attrib, mask); WRAP(cfs, w->screen, drawWindowTexture, colorFilterDrawWindowTexture); } }
/* * Filter windows when they are open if they match the filtering rules */ static void colorFilterWindowAdd (CompScreen *s, CompWindow *w) { FILTER_SCREEN (s); /* cfw->isFiltered is initialized to FALSE in InitWindow, so we only have to toggle it to TRUE if necessary */ if (cfs->isFiltered && matchEval (colorfilterGetFilterMatch (s), w)) colorFilterToggleWindow (w); }
static void colorFilterFiniScreen (CompPlugin * p, CompScreen * s) { FILTER_SCREEN (s); freeWindowPrivateIndex (s, cfs->windowPrivateIndex); UNWRAP (cfs, s, drawWindowTexture); unloadFilters (s); free (cfs); }
/* * Filter windows when they are open if they match the filtering rules */ static void colorFilterWindowAddNotify (CompWindow *w) { FILTER_SCREEN (w->screen); /* cfw->isFiltered is initialized to FALSE in InitWindow, so we only have to toggle it to TRUE if necessary */ if (cfs->isFiltered && matchEval (&cfs->filter_match, w)) colorFilterToggleWindow (w); UNWRAP (cfs, w->screen, windowAddNotify); (*w->screen->windowAddNotify) (w); WRAP (cfs, w->screen, windowAddNotify, colorFilterWindowAddNotify); }
/* * Toggle filtering for the whole screen */ static void colorFilterToggleScreen (CompScreen *s) { CompWindow *w; FILTER_SCREEN (s); /* Toggle screen filtering flag */ cfs->isFiltered = !cfs->isFiltered; /* Toggle filtering for every window */ for (w = s->windows; w; w = w->next) if (w) colorFilterToggleWindow (w); }
static void scalefilterFiniFilterInfo (CompScreen *s, Bool freeTimeout) { FILTER_SCREEN (s); scalefilterFreeFilterText (s); matchFini (&fs->filterInfo->match); if (freeTimeout && fs->filterInfo->timeoutHandle) compRemoveTimeout (fs->filterInfo->timeoutHandle); free (fs->filterInfo); fs->filterInfo = NULL; }
/* * Toggle filtering for a specific window */ static void colorFilterToggleWindow (CompWindow *w) { FILTER_WINDOW (w); FILTER_SCREEN (w->screen); /* Toggle window filtering flag */ cfw->isFiltered = !cfw->isFiltered; /* Check exclude list */ if (matchEval (&cfs->exclude_match, w)) cfw->isFiltered = FALSE; /* Ensure window is going to be repainted */ addWindowDamage (w); }
static void scalefilterFreeFilterText (CompScreen *s) { FILTER_SCREEN (s); if (!fs->filterInfo) return; if (!fs->filterInfo->textPixmap) return; releasePixmapFromTexture(s, &fs->filterInfo->textTexture); XFreePixmap (s->display->display, fs->filterInfo->textPixmap); initTexture (s, &fs->filterInfo->textTexture); fs->filterInfo->textPixmap = None; }
static Bool scalefilterFilterTimeout (void *closure) { CompScreen *s = (CompScreen *) closure; FILTER_SCREEN (s); SCALE_SCREEN (s); if (fs->filterInfo) { ss->currentMatch = fs->filterInfo->origMatch; scalefilterFiniFilterInfo (s, FALSE); scalefilterRelayout (s); } return FALSE; }
static void scalefilterHandleEcompEvent (CompDisplay *d, char *pluginName, char *eventName, CompOption *option, int nOption) { FILTER_DISPLAY (d); UNWRAP (fd, d, handleEcompEvent); (*d->handleEcompEvent) (d, pluginName, eventName, option, nOption); WRAP (fd, d, handleEcompEvent, scalefilterHandleEcompEvent); if ((strcmp (pluginName, "scale") == 0) && (strcmp (eventName, "activate") == 0)) { Window xid = getIntOptionNamed (option, nOption, "root", 0); Bool activated = getBoolOptionNamed (option, nOption, "active", FALSE); CompScreen *s = findScreenAtDisplay (d, xid); if (s) { FILTER_SCREEN (s); SCALE_SCREEN (s); if (activated) { matchFini (&fs->scaleMatch); matchInit (&fs->scaleMatch); matchCopy (&fs->scaleMatch, ss->currentMatch); matchUpdate (d, &fs->scaleMatch); fs->matchApplied = FALSE; } if (!activated) { if (fs->filterInfo) { ss->currentMatch = fs->filterInfo->origMatch; scalefilterFiniFilterInfo (s, TRUE); } fs->matchApplied = FALSE; } } } }
static void scalefilterFiniScreen (CompPlugin *p, CompScreen *s) { FILTER_SCREEN (s); SCALE_SCREEN (s); UNWRAP (fs, s, paintOutput); UNWRAP (fs, ss, setScaledPaintAttributes); if (fs->filterInfo) { ss->currentMatch = fs->filterInfo->origMatch; scalefilterFiniFilterInfo (s, TRUE); } free (fs); }
/* * Switch current filter */ static void colorFilterSwitchFilter (CompScreen *s) { int id; CompFunction *function; CompWindow *w; FILTER_SCREEN (s); /* % (count + 1) because of the cumulative filters mode */ cfs->currentFilter++; if (cfs->currentFilter >= cfs->filtersCount + 1) cfs->currentFilter = 0; if (cfs->currentFilter == 0) compLogMessage ("colorfilter", CompLogLevelInfo, "Cumulative filters mode"); else { id = cfs->filtersFunctions[cfs->currentFilter - 1]; if (id) { function = findFragmentFunction (s, id); compLogMessage ("colorfilter", CompLogLevelInfo, "Single filter mode (using %s filter)", function->name); } else { compLogMessage ("colorfilter", CompLogLevelInfo, "Single filter mode (filter loading failure)"); } } /* Damage currently filtered windows */ for (w = s->windows; w; w = w->next) { FILTER_WINDOW (w); if (cfw->isFiltered) addWindowDamage (w); } }
/* * Filtering match settings update callback */ static void colorFilterMatchsChanged (CompScreen *s, CompOption *opt, ColorfilterScreenOptions num) { CompWindow *w; FILTER_SCREEN (s); /* Re-check every window against new match settings */ for (w = s->windows; w; w = w->next) { FILTER_WINDOW (w); if (matchEval (colorfilterGetFilterMatch (s), w) && cfs->isFiltered && !cfw->isFiltered) { colorFilterToggleWindow (w); } } }
static Bool colorFilterInitWindow (CompPlugin * p, CompWindow * w) { ColorFilterWindow *cfw; if (!w->screen->fragmentProgram) return TRUE; FILTER_SCREEN (w->screen); cfw = malloc (sizeof (ColorFilterWindow)); if (!cfw) return FALSE; cfw->isFiltered = FALSE; w->base.privates[cfs->windowPrivateIndex].ptr = cfw; return TRUE; }
/* * Free filters resources if any */ static void unloadFilters (CompScreen *s) { int i; FILTER_SCREEN (s); if (cfs->filtersFunctions) { /* Destroy loaded filters one by one */ for (i = 0; i < cfs->filtersCount; i++) { if (cfs->filtersFunctions[i]) destroyFragmentFunction (s, cfs->filtersFunctions[i]); } free (cfs->filtersFunctions); cfs->filtersFunctions = NULL; cfs->filtersCount = 0; /* Reset current filter */ cfs->currentFilter = 0; } }
static void scalefilterScreenOptionChanged (CompScreen *s, CompOption *opt, ScalefilterScreenOptions num) { switch (num) { case ScalefilterScreenOptionFontBold: case ScalefilterScreenOptionFontSize: case ScalefilterScreenOptionFontColor: case ScalefilterScreenOptionBackColor: { FILTER_SCREEN (s); if (fs->filterInfo) scalefilterRenderFilterText (s); } break; default: break; } }
static void scalefilterHandleKeyPress (CompScreen *s, XKeyEvent *event) { ScaleFilterInfo *info; Bool needRelayout = FALSE; Bool dropKeyEvent = FALSE; int count, timeout; char buffer[10]; wchar_t wbuffer[10]; KeySym ks; FILTER_DISPLAY (s->display); FILTER_SCREEN (s); SCALE_SCREEN (s); info = fs->filterInfo; memset (buffer, 0, sizeof (buffer)); memset (wbuffer, 0, sizeof (wbuffer)); if (fd->xic) { Status status; XSetICFocus (fd->xic); count = Xutf8LookupString (fd->xic, event, buffer, 9, &ks, &status); XUnsetICFocus (fd->xic); } else { count = XLookupString (event, buffer, 9, &ks, NULL); } mbstowcs (wbuffer, buffer, 9); if (ks == XK_Escape) { if (info) { /* Escape key - drop current filter */ ss->currentMatch = info->origMatch; scalefilterFiniFilterInfo (s, TRUE); needRelayout = TRUE; dropKeyEvent = TRUE; } else if (fs->matchApplied) { /* remove filter applied previously if currently not in input mode */ matchFini (&ss->match); matchInit (&ss->match); matchCopy (&ss->match, &fs->scaleMatch); matchUpdate (s->display, &ss->match); ss->currentMatch = &ss->match; fs->matchApplied = FALSE; needRelayout = TRUE; dropKeyEvent = TRUE; } } else if (ks == XK_Return) { if (info) { /* Return key - apply current filter persistently */ matchFini (&ss->match); matchInit (&ss->match); matchCopy (&ss->match, &info->match); matchUpdate (s->display, &ss->match); ss->currentMatch = &ss->match; fs->matchApplied = TRUE; dropKeyEvent = TRUE; needRelayout = TRUE; scalefilterFiniFilterInfo (s, TRUE); } } else if (ks == XK_BackSpace) { if (info && info->filterStringLength > 0) { /* remove last character in string */ info->filterString[--(info->filterStringLength)] = '\0'; needRelayout = TRUE; } } else if (count > 0) { if (!info) { fs->filterInfo = info = malloc (sizeof (ScaleFilterInfo)); scalefilterInitFilterInfo (s); } else if (info->timeoutHandle) compRemoveTimeout (info->timeoutHandle); timeout = scalefilterGetTimeout (s); if (timeout > 0) info->timeoutHandle = compAddTimeout (timeout, scalefilterFilterTimeout, s); if (info->filterStringLength < MAX_FILTER_SIZE) { info->filterString[info->filterStringLength++] = wbuffer[0]; info->filterString[info->filterStringLength] = '\0'; needRelayout = TRUE; } } /* set the event type invalid if we don't want other plugins see it */ if (dropKeyEvent) event->type = LASTEvent+1; if (needRelayout) { scalefilterRenderFilterText (s); if (fs->filterInfo) scalefilterUpdateFilter (s, &fs->filterInfo->match); scalefilterRelayout (s); } }
/* * Load filters from a list of files for current screen */ static int loadFilters (CompScreen *s, CompTexture *texture) { int i, target, loaded, function, count; char *name; CompWindow *w; FILTER_SCREEN (s); cfs->filtersLoaded = TRUE; /* Fetch filters filenames */ const BananaValue * option_filters = bananaGetOption (bananaIndex, "filters", s->screenNum); count = option_filters->list.nItem; /* The texture target that will be used for some ops */ if (texture->target == GL_TEXTURE_2D) target = COMP_FETCH_TARGET_2D; else target = COMP_FETCH_TARGET_RECT; /* Free previously loaded filters and malloc */ unloadFilters (s); cfs->filtersFunctions = malloc (sizeof (int) * count); if (!cfs->filtersFunctions) return 0; cfs->filtersCount = count; /* Load each filter one by one */ loaded = 0; for (i = 0; i < count; i++) { name = base_name (option_filters->list.item[i].s); if (!name || !strlen (name)) { if (name) free (name); cfs->filtersFunctions[i] = 0; continue; } compLogMessage ("colorfilter", CompLogLevelInfo, "Loading filter %s (item %s).", name, option_filters->list.item[i].s); function = loadFragmentProgram (option_filters->list.item[i].s, name, s, target); free (name); cfs->filtersFunctions[i] = function; if (function) loaded++; } /* Warn if there was at least one loading failure */ if (loaded < count) compLogMessage ("colorfilter", CompLogLevelWarn, "Tried to load %d filter(s), %d succeeded.", count, loaded); if (!loaded) cfs->filtersCount = 0; /* Damage currently filtered windows */ for (w = s->windows; w; w = w->next) { FILTER_WINDOW (w); if (cfw->isFiltered) addWindowDamage (w); } return loaded; }
static void colorFilterChangeNotify (const char *optionName, BananaType optionType, const BananaValue *optionValue, int screenNum) { FILTER_DISPLAY (&display); if (strcasecmp (optionName, "toggle_window_key") == 0) updateKey (optionValue->s, &cfd->toggle_window_key); else if (strcasecmp (optionName, "toggle_screen_key") == 0) updateKey (optionValue->s, &cfd->toggle_screen_key); else if (strcasecmp (optionName, "switch_filter_key") == 0) updateKey (optionValue->s, &cfd->switch_filter_key); else if (strcasecmp (optionName, "filter_match") == 0) { CompWindow *w; CompScreen *s = getScreenFromScreenNum (screenNum); FILTER_SCREEN (s); //Re-check every window against new match settings for (w = s->windows; w; w = w->next) { FILTER_WINDOW (w); if (matchEval (&cfs->filter_match, w) && cfs->isFiltered && !cfw->isFiltered) { colorFilterToggleWindow (w); } } } else if (strcasecmp (optionName, "exclude_match") == 0) { CompWindow *w; CompScreen *s = getScreenFromScreenNum (screenNum); FILTER_SCREEN (s); // Re-check every window against new match settings for (w = s->windows; w; w = w->next) { Bool isExcluded; FILTER_WINDOW (w); isExcluded = matchEval (&cfs->exclude_match, w); if (isExcluded && cfw->isFiltered) colorFilterToggleWindow (w); else if (!isExcluded && cfs->isFiltered && !cfw->isFiltered) colorFilterToggleWindow (w); } } else if (strcasecmp (optionName, "filters") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); FILTER_SCREEN (s); /* Just set the filtersLoaded boolean to FALSE, unloadFilters will be * called in loadFilters */ cfs->filtersLoaded = FALSE; } else if (strcasecmp (optionName, "filter_decorations") == 0) { CompScreen *s = getScreenFromScreenNum (screenNum); damageScreen (s); } }
static void scalefilterRenderFilterText (CompScreen *s) { CompDisplay *d = s->display; CompTextAttrib tA; int stride; void* data; int x1, x2, y1, y2; int width, height; REGION reg; char buffer[2 * MAX_FILTER_STRING_LEN]; FILTER_SCREEN (s); if (!fs->filterInfo) return; x1 = s->outputDev[fs->filterInfo->outputDevice].region.extents.x1; x2 = s->outputDev[fs->filterInfo->outputDevice].region.extents.x2; y1 = s->outputDev[fs->filterInfo->outputDevice].region.extents.y1; y2 = s->outputDev[fs->filterInfo->outputDevice].region.extents.y2; reg.rects = ®.extents; reg.numRects = 1; /* damage the old draw rectangle */ width = fs->filterInfo->textWidth + (2 * scalefilterGetBorderSize (s)); height = fs->filterInfo->textHeight + (2 * scalefilterGetBorderSize (s)); reg.extents.x1 = x1 + ((x2 - x1) / 2) - (width / 2) - 1; reg.extents.x2 = reg.extents.x1 + width + 1; reg.extents.y1 = y1 + ((y2 - y1) / 2) - (height / 2) - 1; reg.extents.y2 = reg.extents.y1 + height + 1; damageScreenRegion (s, ®); scalefilterFreeFilterText (s); if (!scalefilterGetFilterDisplay (s)) return; if (fs->filterInfo->filterStringLength == 0) return; tA.maxwidth = x2 - x1 - (2 * scalefilterGetBorderSize (s)); tA.maxheight = y2 - y1 - (2 * scalefilterGetBorderSize (s)); tA.screen = s; tA.size = scalefilterGetFontSize (s); tA.color[0] = scalefilterGetFontColorRed (s); tA.color[1] = scalefilterGetFontColorGreen (s); tA.color[2] = scalefilterGetFontColorBlue (s); tA.color[3] = scalefilterGetFontColorAlpha (s); tA.style = (scalefilterGetFontBold (s)) ? TEXT_STYLE_BOLD : TEXT_STYLE_NORMAL; tA.family = "Sans"; tA.ellipsize = TRUE; wcstombs (buffer, fs->filterInfo->filterString, MAX_FILTER_STRING_LEN); tA.renderMode = TextRenderNormal; tA.data = (void*)buffer; if ((*d->fileToImage) (s->display, TEXT_ID, (char *)&tA, &fs->filterInfo->textWidth, &fs->filterInfo->textHeight, &stride, &data)) { fs->filterInfo->textPixmap = (Pixmap)data; if (!bindPixmapToTexture (s, &fs->filterInfo->textTexture, fs->filterInfo->textPixmap, fs->filterInfo->textWidth, fs->filterInfo->textHeight, 32)) { compLogMessage (d, "scalefilterinfo", CompLogLevelError, "Bind Pixmap to Texture failure"); XFreePixmap (d->display, fs->filterInfo->textPixmap); fs->filterInfo->textPixmap = None; return; } } else { fs->filterInfo->textPixmap = None; fs->filterInfo->textWidth = 0; fs->filterInfo->textHeight = 0; } /* damage the new draw rectangle */ width = fs->filterInfo->textWidth + (2 * scalefilterGetBorderSize (s)); height = fs->filterInfo->textHeight + (2 * scalefilterGetBorderSize (s)); reg.extents.x1 = x1 + ((x2 - x1) / 2) - (width / 2) - 1; reg.extents.x2 = reg.extents.x1 + width + 1; reg.extents.y1 = y1 + ((y2 - y1) / 2) - (height / 2) - 1; reg.extents.y2 = reg.extents.y1 + height + 1; damageScreenRegion (s, ®); }
static void scalefilterDrawFilterText (CompScreen *s, CompOutput *output) { FILTER_SCREEN (s); GLboolean wasBlend; GLint oldBlendSrc, oldBlendDst; int ox1, ox2, oy1, oy2; float width = fs->filterInfo->textWidth; float height = fs->filterInfo->textHeight; float border = scalefilterGetBorderSize (s); ox1 = output->region.extents.x1; ox2 = output->region.extents.x2; oy1 = output->region.extents.y1; oy2 = output->region.extents.y2; float x = ox1 + ((ox2 - ox1) / 2) - (width / 2); float y = oy1 + ((oy2 - oy1) / 2) + (height / 2); x = floor (x); y = floor (y); wasBlend = glIsEnabled (GL_BLEND); glGetIntegerv (GL_BLEND_SRC, &oldBlendSrc); glGetIntegerv (GL_BLEND_DST, &oldBlendDst); if (!wasBlend) glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColor4us (scalefilterGetBackColorRed (s), scalefilterGetBackColorGreen (s), scalefilterGetBackColorBlue (s), scalefilterGetBackColorAlpha (s)); glPushMatrix (); glTranslatef (x, y - height, 0.0f); glRectf (0.0f, height, width, 0.0f); glRectf (0.0f, 0.0f, width, -border); glRectf (0.0f, height + border, width, height); glRectf (-border, height, 0.0f, 0.0f); glRectf (width, height, width + border, 0.0f); glTranslatef (-border, -border, 0.0f); #define CORNER(a,b) \ for (k = a; k < b; k++) \ {\ float rad = k* (3.14159 / 180.0f);\ glVertex2f (0.0f, 0.0f);\ glVertex2f (cos (rad) * border, sin (rad) * border);\ glVertex2f (cos ((k - 1) * (3.14159 / 180.0f)) * border, \ sin ((k - 1) * (3.14159 / 180.0f)) * border);\ } /* Rounded corners */ int k; glTranslatef (border, border, 0.0f); glBegin (GL_TRIANGLES); CORNER (180, 270) glEnd(); glTranslatef (-border, -border, 0.0f); glTranslatef (width + border, border, 0.0f); glBegin (GL_TRIANGLES); CORNER (270, 360) glEnd(); glTranslatef (-(width + border), -border, 0.0f); glTranslatef (border, height + border, 0.0f); glBegin (GL_TRIANGLES); CORNER (90, 180) glEnd(); glTranslatef (-border, -(height + border), 0.0f); glTranslatef (width + border, height + border, 0.0f); glBegin (GL_TRIANGLES); CORNER (0, 90) glEnd(); glTranslatef (-(width + border), -(height + border), 0.0f); glPopMatrix (); #undef CORNER glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f (1.0, 1.0, 1.0, 1.0); enableTexture (s, &fs->filterInfo->textTexture, COMP_TEXTURE_FILTER_GOOD); CompMatrix *m = &fs->filterInfo->textTexture.matrix; glBegin (GL_QUADS); glTexCoord2f (COMP_TEX_COORD_X(m, 0),COMP_TEX_COORD_Y(m ,0)); glVertex2f (x, y - height); glTexCoord2f (COMP_TEX_COORD_X(m, 0),COMP_TEX_COORD_Y(m, height)); glVertex2f (x, y); glTexCoord2f (COMP_TEX_COORD_X(m, width),COMP_TEX_COORD_Y(m, height)); glVertex2f (x + width, y); glTexCoord2f (COMP_TEX_COORD_X(m, width),COMP_TEX_COORD_Y(m, 0)); glVertex2f (x + width, y - height); glEnd (); disableTexture (s, &fs->filterInfo->textTexture); glColor4usv (defaultColor); if (!wasBlend) glDisable (GL_BLEND); glBlendFunc (oldBlendSrc, oldBlendDst); }