static void EmbedStructureProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { Container *containerPtr = clientData; Tk_ErrorHandler errHandler; if (eventPtr->type == ConfigureNotify) { if (containerPtr->embedded != None) { /* * Ignore errors, since the embedded application could have * deleted its window. */ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, -1, -1, NULL, NULL); Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0, (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr), (unsigned) Tk_Height((Tk_Window)containerPtr->parentPtr)); Tk_DeleteErrorHandler(errHandler); } } else if (eventPtr->type == DestroyNotify) { EmbedWindowDeleted(containerPtr->parentPtr); } }
static void FinishedWithFont( UnixFtFont *fontPtr) { Display *display = fontPtr->display; int i; Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, (ClientData) NULL); for (i = 0; i < fontPtr->nfaces; i++) { if (fontPtr->faces[i].ftFont) { XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont); } if (fontPtr->faces[i].charset) { FcCharSetDestroy(fontPtr->faces[i].charset); } } if (fontPtr->faces) { ckfree((char *)fontPtr->faces); } if (fontPtr->pattern) { FcPatternDestroy(fontPtr->pattern); } if (fontPtr->ftDraw) { XftDrawDestroy(fontPtr->ftDraw); } if (fontPtr->font.fid) { XUnloadFont(fontPtr->display, fontPtr->font.fid); } if (fontPtr->fontset) { FcFontSetDestroy(fontPtr->fontset); } Tk_DeleteErrorHandler(handler); }
static void EmbedFocusProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { Container *containerPtr = clientData; Tk_ErrorHandler errHandler; Display *display; display = Tk_Display(containerPtr->parentPtr); if (eventPtr->type == FocusIn) { /* * The focus just arrived at the container. Change the X focus to move * it to the embedded application, if there is one. Ignore X errors * that occur during this operation (it's possible that the new focus * window isn't mapped). */ if (containerPtr->wrapper != None) { errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, -1, -1, NULL, NULL); XSetInputFocus(display, containerPtr->wrapper, RevertToParent, CurrentTime); Tk_DeleteErrorHandler(errHandler); } } }
static int RotateOp(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) { Tk_Window tkwin = clientData; int count; int result; Tk_ErrorHandler handler; count = 1; /* Default: rotate one position */ if (objc == 3) { if (Tcl_GetIntFromObj(interp, objv[2], &count) != TCL_OK) { return TCL_ERROR; } if ((count < 0) || (count > 8)) { Tcl_AppendResult(interp, "bad rotate count \"", Tcl_GetString(objv[2]), "\"", (char *)NULL); return TCL_ERROR; } } result = TCL_OK; handler = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch, X_RotateProperties, -1, RotateErrorProc, &result); XRotateBuffers(Tk_Display(tkwin), count); Tk_DeleteErrorHandler(handler); XSync(Tk_Display(tkwin), False); if (result != TCL_OK) { Tcl_AppendResult(interp, "can't rotate cutbuffers unless all are set", (char *)NULL); return TCL_ERROR; } return TCL_OK; }
static bool tk_start(char **result) { static bool first_init = false; Tk_Window mainw; if (!first_init) { first_init = true; /* this works around a bug in some Tcl/Tk versions */ Tcl_FindExecutable(NULL); /* finalize Tcl at program exit */ atexit(Tcl_Finalize); } *result = NULL; if (interp) return true; /* start up a new interpreter */ if (!(interp = Tcl_CreateInterp())) return false; if (Tcl_Init(interp) != TCL_OK) { if (check_result(interp)) set_result(result, get_result(interp)); else set_result(result, "error initializing Tcl"); tk_stop(); return false; } /* create a command to invoke Pure callbacks from Tcl */ Tcl_CreateCommand(interp, "pure", (Tcl_CmdProc*)tk_pure, (ClientData)0, NULL); /* oddly, there are no `env' variables passed, and this one is needed */ Tcl_SetVar2(interp, "env", "DISPLAY", getenv("DISPLAY"), TCL_GLOBAL_ONLY); if (Tk_Init(interp) != TCL_OK) { if (check_result(interp)) set_result(result, get_result(interp)); else set_result(result, "error initializing Tk"); tk_stop(); return false; } /* set up an X error handler */ mainw = Tk_MainWindow(interp); Tk_CreateErrorHandler(Tk_Display(mainw), -1, -1, -1, XErrorProc, (ClientData)mainw); return true; }
const char * Tk_GetAtomName( Tk_Window tkwin, /* Window token; map atom to name relative to * this window's display. */ Atom atom) /* Atom whose name is wanted. */ { TkDisplay *dispPtr; Tcl_HashEntry *hPtr; dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->atomInit) { AtomInit(dispPtr); } hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, (char *) atom); if (hPtr == NULL) { const char *name; Tk_ErrorHandler handler; int isNew; char *mustFree = NULL; handler = Tk_CreateErrorHandler(dispPtr->display, BadAtom, -1, -1, NULL, (ClientData) NULL); name = mustFree = XGetAtomName(dispPtr->display, atom); if (name == NULL) { name = "?bad atom?"; } Tk_DeleteErrorHandler(handler); hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew); Tcl_SetHashValue(hPtr, atom); if (mustFree) { XFree(mustFree); } name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, &isNew); Tcl_SetHashValue(hPtr, name); } return Tcl_GetHashValue(hPtr); }
static void ContainerEventProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { TkWindow *winPtr = clientData; Container *containerPtr; Tk_ErrorHandler errHandler; /* * Ignore any X protocol errors that happen in this procedure (almost any * operation could fail, for example, if the embedded application has * deleted its window). */ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, -1, -1, NULL, NULL); /* * Find the Container structure associated with the parent window. */ for (containerPtr = firstContainerPtr; containerPtr->parent != eventPtr->xmaprequest.parent; containerPtr = containerPtr->nextPtr) { if (containerPtr == NULL) { Tcl_Panic("ContainerEventProc couldn't find Container record"); } } if (eventPtr->type == CreateNotify) { /* * A new child window has been created in the container. Record its id * in the Container structure (if more than one child is created, just * remember the last one and ignore the earlier ones). */ containerPtr->embedded = eventPtr->xcreatewindow.window; } else if (eventPtr->type == ConfigureRequest) { if ((eventPtr->xconfigurerequest.x != 0) || (eventPtr->xconfigurerequest.y != 0)) { /* * The embedded application is trying to move itself, which isn't * legal. At this point, the window hasn't actually moved, but we * need to send it a ConfigureNotify event to let it know that its * request has been denied. If the embedded application was also * trying to resize itself, a ConfigureNotify will be sent by the * geometry management code below, so we don't need to do * anything. Otherwise, generate a synthetic event. */ if ((eventPtr->xconfigurerequest.width == winPtr->changes.width) && (eventPtr->xconfigurerequest.height == winPtr->changes.height)) { EmbedSendConfigure(containerPtr); } } EmbedGeometryRequest(containerPtr, eventPtr->xconfigurerequest.width, eventPtr->xconfigurerequest.height); } else if (eventPtr->type == MapRequest) { /* * The embedded application's map request was ignored and simply * passed on to us, so we have to map the window for it to appear on * the screen. */ XMapWindow(eventPtr->xmaprequest.display, eventPtr->xmaprequest.window); } else if (eventPtr->type == DestroyNotify) { /* * The embedded application is gone. Destroy the container window. */ Tk_DestroyWindow((Tk_Window) winPtr); } Tk_DeleteErrorHandler(errHandler); }
int TkpUseWindow( Tcl_Interp *interp, /* If not NULL, used for error reporting if * string is bogus. */ Tk_Window tkwin, /* Tk window that does not yet have an * associated X window. */ const char *string) /* String identifying an X window to use for * tkwin; must be an integer value. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *usePtr; int id, anyError; Window parent; Tk_ErrorHandler handler; Container *containerPtr; XWindowAttributes parentAtts; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->window != None) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't modify container after widget is created", -1)); Tcl_SetErrorCode(interp, "TK", "EMBED", "POST_CREATE", NULL); return TCL_ERROR; } if (Tcl_GetInt(interp, string, &id) != TCL_OK) { return TCL_ERROR; } parent = (Window) id; usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent); if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "window \"%s\" doesn't have -container option set", usePtr->pathName)); Tcl_SetErrorCode(interp, "TK", "EMBED", "CONTAINER", NULL); return TCL_ERROR; } /* * Tk sets the window colormap to the screen default colormap in * tkWindow.c:AllocWindow. This doesn't work well for embedded windows. So * we override the colormap and visual settings to be the same as the * parent window (which is in the container app). */ anyError = 0; handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, EmbedErrorProc, &anyError); if (!XGetWindowAttributes(winPtr->display, parent, &parentAtts)) { anyError = 1; } XSync(winPtr->display, False); Tk_DeleteErrorHandler(handler); if (anyError) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't create child of window \"%s\"", string)); Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL); } return TCL_ERROR; } Tk_SetWindowVisual(tkwin, parentAtts.visual, parentAtts.depth, parentAtts.colormap); /* * Create an event handler to clean up the Container structure when tkwin * is eventually deleted. */ Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, winPtr); /* * Save information about the container and the embedded window in a * Container structure. If there is already an existing Container * structure, it means that both container and embedded app. are in the * same process. */ for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->parent == parent) { winPtr->flags |= TK_BOTH_HALVES; containerPtr->parentPtr->flags |= TK_BOTH_HALVES; break; } } if (containerPtr == NULL) { containerPtr = ckalloc(sizeof(Container)); containerPtr->parent = parent; containerPtr->parentRoot = parentAtts.root; containerPtr->parentPtr = NULL; containerPtr->wrapper = None; containerPtr->nextPtr = tsdPtr->firstContainerPtr; tsdPtr->firstContainerPtr = containerPtr; } containerPtr->embeddedPtr = winPtr; winPtr->flags |= TK_EMBEDDED; return TCL_OK; }
void Tk_DrawChars( Display *display, /* Display on which to draw. */ Drawable drawable, /* Window or pixmap in which to draw. */ GC gc, /* Graphics context for drawing characters. */ Tk_Font tkfont, /* Font in which characters will be drawn; * must be the same as font used in GC. */ CONST char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) * should be stripped out of the string that * is passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ int x, int y) /* Coordinates at which to place origin of * string when drawing. */ { const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */ UnixFtFont *fontPtr = (UnixFtFont *) tkfont; XGCValues values; XColor xcolor; int clen, nspec; XftGlyphFontSpec specs[NUM_SPEC]; XGlyphInfo metrics; if (fontPtr->ftDraw == 0) { #if DEBUG_FONTSEL printf("Switch to drawable 0x%x\n", drawable); #endif /* DEBUG_FONTSEL */ fontPtr->ftDraw = XftDrawCreate(display, drawable, DefaultVisual(display, fontPtr->screen), DefaultColormap(display, fontPtr->screen)); } else { Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, (ClientData) NULL); XftDrawChange(fontPtr->ftDraw, drawable); Tk_DeleteErrorHandler(handler); } XGetGCValues(display, gc, GCForeground, &values); if (values.foreground != fontPtr->color.pixel) { xcolor.pixel = values.foreground; XQueryColor(display, DefaultColormap(display, fontPtr->screen), &xcolor); fontPtr->color.color.red = xcolor.red; fontPtr->color.color.green = xcolor.green; fontPtr->color.color.blue = xcolor.blue; fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } nspec = 0; while (numBytes > 0 && x <= maxCoord && y <= maxCoord) { XftFont *ftFont; FcChar32 c; clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); if (clen <= 0) { /* * This should not happen, but it can. */ return; } source += clen; numBytes -= clen; ftFont = GetFont(fontPtr, c); if (ftFont) { specs[nspec].font = ftFont; specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c); specs[nspec].x = x; specs[nspec].y = y; XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1, &metrics); x += metrics.xOff; y += metrics.yOff; nspec++; if (nspec == NUM_SPEC) { XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec); nspec = 0; } } } if (nspec) { XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec); } }
static int CanvasPsWindow( Tcl_Interp *interp, /* Leave Postscript or error message here. */ Tk_Window tkwin, /* window to be printed */ Tk_Canvas canvas, /* Information about overall canvas. */ double x, double y, /* origin of window. */ int width, int height) /* width/height of window. */ { XImage *ximage; int result; #ifdef X_GetImage Tk_ErrorHandler handle; #endif Tcl_Obj *cmdObj, *psObj; Tcl_InterpState interpState = Tcl_SaveInterpState(interp, TCL_OK); /* * Locate the subwindow within the wider window. */ psObj = Tcl_ObjPrintf( "\n%%%% %s item (%s, %d x %d)\n" /* Comment */ "%.15g %.15g translate\n", /* Position */ Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y); /* * First try if the widget has its own "postscript" command. If it exists, * this will produce much better postscript than when a pixmap is used. */ Tcl_ResetResult(interp); cmdObj = Tcl_ObjPrintf("%s postscript -prolog 0", Tk_PathName(tkwin)); Tcl_IncrRefCount(cmdObj); result = Tcl_EvalObjEx(interp, cmdObj, 0); Tcl_DecrRefCount(cmdObj); if (result == TCL_OK) { Tcl_AppendPrintfToObj(psObj, "50 dict begin\nsave\ngsave\n" "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d 0 rlineto closepath\n" "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n", height, width, height, width); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); Tcl_AppendToObj(psObj, "\nrestore\nend\n\n\n", -1); goto done; } /* * If the window is off the screen it will generate a BadMatch/XError. We * catch any BadMatch errors here */ #ifdef X_GetImage handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch, X_GetImage, -1, xerrorhandler, tkwin); #endif /* * Generate an XImage from the window. We can then read pixel values out * of the XImage. */ ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0, (unsigned) width, (unsigned) height, AllPlanes, ZPixmap); #ifdef X_GetImage Tk_DeleteErrorHandler(handle); #endif if (ximage == NULL) { result = TCL_OK; } else { Tcl_ResetResult(interp); result = TkPostscriptImage(interp, tkwin, Canvas(canvas)->psInfo, ximage, 0, 0, width, height); Tcl_AppendObjToObj(psObj, Tcl_GetObjResult(interp)); XDestroyImage(ximage); } /* * Plug the accumulated postscript back into the result. */ done: if (result == TCL_OK) { (void) Tcl_RestoreInterpState(interp, interpState); Tcl_AppendObjToObj(Tcl_GetObjResult(interp), psObj); } else { Tcl_DiscardInterpState(interpState); } Tcl_DecrRefCount(psObj); return result; }
void TkDrawAngledChars( Display *display, /* Display on which to draw. */ Drawable drawable, /* Window or pixmap in which to draw. */ GC gc, /* Graphics context for drawing characters. */ Tk_Font tkfont, /* Font in which characters will be drawn; * must be the same as font used in GC. */ const char *source, /* UTF-8 string to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) * should be stripped out of the string that * is passed to this function. If they are not * stripped out, they will be displayed as * regular printing characters. */ int numBytes, /* Number of bytes in string. */ double x, double y, /* Coordinates at which to place origin of * string when drawing. */ double angle) /* What angle to put text at, in degrees. */ { const int maxCoord = 0x7FFF;/* Xft coordinates are 16 bit values */ const int minCoord = -1000; /* Should be good enough... */ UnixFtFont *fontPtr = (UnixFtFont *) tkfont; XGCValues values; XColor xcolor; int xStart = x, yStart = y; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); #ifdef XFT_HAS_FIXED_ROTATED_PLACEMENT int clen, nglyph; FT_UInt glyphs[NUM_SPEC]; XGlyphInfo metrics; XftFont *currentFtFont; int originX, originY; if (fontPtr->ftDraw == 0) { #if DEBUG_FONTSEL printf("Switch to drawable 0x%x\n", drawable); #endif /* DEBUG_FONTSEL */ fontPtr->ftDraw = XftDrawCreate(display, drawable, DefaultVisual(display, fontPtr->screen), DefaultColormap(display, fontPtr->screen)); } else { Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); XftDrawChange(fontPtr->ftDraw, drawable); Tk_DeleteErrorHandler(handler); } XGetGCValues(display, gc, GCForeground, &values); if (values.foreground != fontPtr->color.pixel) { xcolor.pixel = values.foreground; XQueryColor(display, DefaultColormap(display, fontPtr->screen), &xcolor); fontPtr->color.color.red = xcolor.red; fontPtr->color.color.green = xcolor.green; fontPtr->color.color.blue = xcolor.blue; fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } if (tsdPtr->clipRegion != None) { XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); } nglyph = 0; currentFtFont = NULL; originX = originY = 0; /* lint */ while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord && y >= minCoord) { XftFont *ftFont; FcChar32 c; clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); if (clen <= 0) { /* * This should not happen, but it can. */ goto doUnderlineStrikeout; } source += clen; numBytes -= clen; ftFont = GetFont(fontPtr, c, angle); if (!ftFont) { continue; } if (ftFont != currentFtFont || nglyph == NUM_SPEC) { if (nglyph) { /* * We pass multiple glyphs at once to enable the code to * perform better rendering of sub-pixel inter-glyph spacing. * If only the current Xft implementation could make use of * this information... but we'll be ready when it does! */ XftDrawGlyphs(fontPtr->ftDraw, &fontPtr->color, currentFtFont, originX, originY, glyphs, nglyph); } originX = ROUND16(x); originY = ROUND16(y); if (nglyph) { XftGlyphExtents(fontPtr->display, currentFtFont, glyphs, nglyph, &metrics); nglyph = 0; x += metrics.xOff; y += metrics.yOff; } currentFtFont = ftFont; } glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c); } if (nglyph) { XftDrawGlyphs(fontPtr->ftDraw, &fontPtr->color, currentFtFont, originX, originY, glyphs, nglyph); } #else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */ int clen, nspec; XftGlyphFontSpec specs[NUM_SPEC]; XGlyphInfo metrics; double sinA = sin(angle * PI/180.0), cosA = cos(angle * PI/180.0); if (fontPtr->ftDraw == 0) { #if DEBUG_FONTSEL printf("Switch to drawable 0x%x\n", drawable); #endif /* DEBUG_FONTSEL */ fontPtr->ftDraw = XftDrawCreate(display, drawable, DefaultVisual(display, fontPtr->screen), DefaultColormap(display, fontPtr->screen)); } else { Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL); XftDrawChange(fontPtr->ftDraw, drawable); Tk_DeleteErrorHandler(handler); } XGetGCValues(display, gc, GCForeground, &values); if (values.foreground != fontPtr->color.pixel) { xcolor.pixel = values.foreground; XQueryColor(display, DefaultColormap(display, fontPtr->screen), &xcolor); fontPtr->color.color.red = xcolor.red; fontPtr->color.color.green = xcolor.green; fontPtr->color.color.blue = xcolor.blue; fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } if (tsdPtr->clipRegion != None) { XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); } nspec = 0; while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord && y >= minCoord) { XftFont *ftFont, *ft0Font; FcChar32 c; clen = FcUtf8ToUcs4((FcChar8 *) source, &c, numBytes); if (clen <= 0) { /* * This should not happen, but it can. */ goto doUnderlineStrikeout; } source += clen; numBytes -= clen; ftFont = GetFont(fontPtr, c, angle); ft0Font = GetFont(fontPtr, c, 0.0); if (ftFont && ft0Font) { specs[nspec].font = ftFont; specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c); specs[nspec].x = ROUND16(x); specs[nspec].y = ROUND16(y); XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1, &metrics); x += metrics.xOff*cosA + metrics.yOff*sinA; y += metrics.yOff*cosA - metrics.xOff*sinA; nspec++; if (nspec == NUM_SPEC) { XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec); nspec = 0; } } } if (nspec) { XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec); } #endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */ doUnderlineStrikeout: if (tsdPtr->clipRegion != None) { XftDrawSetClip(fontPtr->ftDraw, None); } if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) { XPoint points[5]; double width = (x - xStart) * cosA + (yStart - y) * sinA; double barHeight = fontPtr->font.underlineHeight; double dy = fontPtr->font.underlinePos; if (fontPtr->font.fa.underline != 0) { if (fontPtr->font.underlineHeight == 1) { dy++; } points[0].x = xStart + ROUND16(dy*sinA); points[0].y = yStart + ROUND16(dy*cosA); points[1].x = xStart + ROUND16(dy*sinA + width*cosA); points[1].y = yStart + ROUND16(dy*cosA - width*sinA); if (fontPtr->font.underlineHeight == 1) { XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin); } else { points[2].x = xStart + ROUND16(dy*sinA + width*cosA + barHeight*sinA); points[2].y = yStart + ROUND16(dy*cosA - width*sinA + barHeight*cosA); points[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA); points[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA); points[4].x = points[0].x; points[4].y = points[0].y; XFillPolygon(display, drawable, gc, points, 5, Complex, CoordModeOrigin); XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin); } } if (fontPtr->font.fa.overstrike != 0) { dy = -fontPtr->font.fm.descent - (fontPtr->font.fm.ascent) / 10; points[0].x = xStart + ROUND16(dy*sinA); points[0].y = yStart + ROUND16(dy*cosA); points[1].x = xStart + ROUND16(dy*sinA + width*cosA); points[1].y = yStart + ROUND16(dy*cosA - width*sinA); if (fontPtr->font.underlineHeight == 1) { XDrawLines(display, drawable, gc, points, 2, CoordModeOrigin); } else { points[2].x = xStart + ROUND16(dy*sinA + width*cosA + barHeight*sinA); points[2].y = yStart + ROUND16(dy*cosA - width*sinA + barHeight*cosA); points[3].x = xStart + ROUND16(dy*sinA + barHeight*sinA); points[3].y = yStart + ROUND16(dy*cosA + barHeight*cosA); points[4].x = points[0].x; points[4].y = points[0].y; XFillPolygon(display, drawable, gc, points, 5, Complex, CoordModeOrigin); XDrawLines(display, drawable, gc, points, 5, CoordModeOrigin); } } } }