1/*****************************************************************************
2Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
3
4                        All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of Digital not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************************/
23
24#include "x11perf.h"
25#include <stdio.h>
26#include "bitmaps.h"
27
28static char **charBuf;
29static XFontStruct *font, *bfont;
30static int height, ypos;
31static XTextItem *items;
32static int charsPerLine, totalLines;
33
34#define XPOS 20
35#define SEGS 3
36
37
38int
39InitText(XParms xp, Parms p, int64_t reps)
40{
41    XGCValues   gcv;
42
43    font = XLoadQueryFont(xp->d, p->font);
44    if (font == NULL) {
45	printf("Could not load font '%s', benchmark omitted\n", p->font);
46	return 0;
47    }
48
49    bfont = NULL;
50    if (p->bfont != NULL) {
51	bfont = XLoadQueryFont(xp->d, p->bfont);
52	if (bfont == NULL) {
53	    printf("Could not load font '%s', benchmark omitted\n", p->bfont);
54	    return 0;
55	}
56    }
57
58    ypos = XPOS;
59    height = (font->max_bounds.ascent + font->max_bounds.descent) + 1;
60    if (bfont != NULL) {
61	int     h = (bfont->max_bounds.ascent + bfont->max_bounds.descent) + 1;
62	if (h > height)
63	    height = h;
64    }
65    gcv.font = font->fid;
66    XChangeGC(xp->d, xp->fggc, GCFont, &gcv);
67    XChangeGC(xp->d, xp->bggc, GCFont, &gcv);
68
69    SetFillStyle(xp, p);
70
71    charsPerLine = p->objects;
72    charsPerLine = (charsPerLine + 3) & ~3;
73    p->objects = charsPerLine;
74
75    totalLines = '\177' - ' ' + 1;
76    if (totalLines > reps) totalLines = reps;
77
78    charBuf = malloc(totalLines * sizeof (char *));
79    if (p->special)
80	items = malloc(totalLines * SEGS * sizeof (XTextItem));
81
82    for (int i = 0; i != totalLines; i++) {
83	char	ch;
84
85	charBuf[i] = malloc (sizeof (char) * charsPerLine);
86	ch = i + ' ';
87	for (int j = 0; j != charsPerLine; j++) {
88	    charBuf[i][j] = ch;
89	    if (ch == '\177') ch = ' '; else ch++;
90	}
91	if (p->special) {
92	    items[i*SEGS+0].chars = &(charBuf[i][0]);
93	    items[i*SEGS+0].nchars = charsPerLine/4;
94	    items[i*SEGS+0].delta = 0;
95	    items[i*SEGS+0].font = font->fid;
96	    items[i*SEGS+1].chars = &(charBuf[i][charsPerLine/4]);
97	    items[i*SEGS+1].nchars = charsPerLine/2;
98	    items[i*SEGS+1].delta = 3;
99	    items[i*SEGS+1].font = bfont->fid;
100	    items[i*SEGS+2].chars = &(charBuf[i][3*charsPerLine/4]);
101	    items[i*SEGS+2].nchars = charsPerLine/4;
102	    items[i*SEGS+2].delta = 3;
103	    items[i*SEGS+2].font = font->fid;
104	}
105    }
106    return reps;
107}
108
109
110#define GetRealChar(font, totalChars, ch)				\
111{									\
112    XCharStruct *pci;							\
113    do {								\
114	ch--;								\
115	if (ch < 0) {							\
116	    ch = totalChars-1;						\
117	}								\
118	if (font->per_char == NULL) break;				\
119	pci = &(font->per_char[ch]);					\
120    } while ( (pci->lbearing | pci->rbearing | pci->width		\
121             | pci->ascent | pci->descent | pci->attributes) == 0);     \
122} /* GetRealChar */
123
124int
125InitText16(XParms xp, Parms p, int64_t reps)
126{
127    XGCValues   	gcv;
128    int			rows, columns, totalChars, ch;
129    int			brows, bcolumns = 0, btotalChars = 0, bch = 0;
130
131    font = XLoadQueryFont(xp->d, p->font);
132    if (font == NULL) {
133	printf("Could not load font '%s', benchmark omitted\n", p->font);
134	return 0;
135    }
136    rows = font->max_byte1 - font->min_byte1 + 1;
137    columns = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
138    totalChars = rows * columns;
139    totalLines = rows;
140    ch = totalChars;
141
142    bfont = NULL;
143    if (p->bfont != NULL) {
144	bfont = XLoadQueryFont(xp->d, p->bfont);
145	if (bfont == NULL) {
146	    printf("Could not load font '%s', benchmark omitted\n", p->bfont);
147	    return 0;
148	}
149	brows = bfont->max_byte1 - bfont->min_byte1 + 1;
150	bcolumns = bfont->max_char_or_byte2 - bfont->min_char_or_byte2 + 1;
151	btotalChars = brows * bcolumns;
152	bch = btotalChars;
153	if (brows > totalLines) totalLines = brows;
154    }
155
156    ypos = XPOS;
157    height = (font->max_bounds.ascent + font->max_bounds.descent) + 1;
158    if (bfont != NULL) {
159	int     h = (bfont->max_bounds.ascent + bfont->max_bounds.descent) + 1;
160	if (h > height)
161	    height = h;
162    }
163    gcv.font = font->fid;
164    XChangeGC(xp->d, xp->fggc, GCFont, &gcv);
165    XChangeGC(xp->d, xp->bggc, GCFont, &gcv);
166
167    charsPerLine = p->objects;
168
169    if (totalLines > reps) totalLines = reps;
170
171    if (p->special) {
172	charsPerLine = (charsPerLine + 3) & ~3;	/* make a multiple of four */
173	p->objects = charsPerLine;
174
175	items = malloc(totalLines * SEGS * sizeof (XTextItem));
176
177	for (int i = 0; i < totalLines; i++) {
178	    char	*pbuf0, *pbuf1, *pbuf2;
179
180	    pbuf0 = items[i*SEGS+0].chars =
181                malloc (sizeof (char) * charsPerLine/2);
182	    items[i*SEGS+0].nchars = charsPerLine/4;
183	    items[i*SEGS+0].delta = 0;
184	    items[i*SEGS+0].font = font->fid;
185	    pbuf1 = items[i*SEGS+1].chars =
186                malloc (sizeof (char) * charsPerLine);
187	    items[i*SEGS+1].nchars = charsPerLine/2;
188	    items[i*SEGS+1].delta = 3;
189	    items[i*SEGS+1].font = bfont->fid;
190	    pbuf2 = items[i*SEGS+2].chars =
191                malloc (sizeof (char) * charsPerLine/2);
192	    items[i*SEGS+2].nchars = charsPerLine/4;
193	    items[i*SEGS+2].delta = 3;
194	    items[i*SEGS+2].font = font->fid;
195	    for (int j = 0; j < charsPerLine/4; j++) {
196		GetRealChar(font, totalChars, ch);
197		*pbuf0++ = ch / columns + font->min_byte1;
198		*pbuf0++ = ch % columns + font->min_char_or_byte2;
199		GetRealChar(font, totalChars, ch);
200		*pbuf2++ = ch / columns + font->min_byte1;
201		*pbuf2++ = ch % columns + font->min_char_or_byte2;
202	    }
203	    for (int j = 0; j < charsPerLine/2; j++) {
204		GetRealChar(bfont, btotalChars, bch);
205		*pbuf1++ = bch / bcolumns + bfont->min_byte1;
206		*pbuf1++ = bch % bcolumns + bfont->min_char_or_byte2;
207	    }
208	}
209    } else {
210	charBuf = malloc(totalLines * sizeof (char *));
211	for (int i = 0; i < totalLines; i++) {
212	    char *pbuf0 = charBuf[i] =
213                malloc (sizeof (char) * charsPerLine * 2);
214	    for (int j = 0; j < charsPerLine; j++) {
215		GetRealChar(font, totalChars, ch);
216		*pbuf0++ = ch / columns + font->min_byte1;
217		*pbuf0++ = ch % columns + font->min_char_or_byte2;
218	    }
219	}
220    }
221    return reps;
222}
223
224void
225DoText(XParms xp, Parms p, int64_t reps)
226{
227    int     line, startLine;
228
229    startLine = 0;
230    line = 0;
231    for (int i = 0; i != reps; i++) {
232	XDrawString(
233	    xp->d, xp->w, xp->fggc, XPOS, ypos, charBuf[line], charsPerLine);
234	ypos += height;
235	if (ypos > HEIGHT - height) {
236	    /* Wraparound to top of window */
237	    ypos = XPOS;
238	    line = startLine;
239	    startLine = (startLine + 1) % totalLines;
240	}
241	line = (line + 1) % totalLines;
242	CheckAbort ();
243    }
244}
245
246void
247DoText16(XParms xp, Parms p, int64_t reps)
248{
249    int     line, startLine;
250
251    startLine = 0;
252    line = 0;
253    for (int i = 0; i < reps; i++) {
254	XDrawString16(
255	    xp->d, xp->w, xp->fggc, XPOS, ypos, (XChar2b *)charBuf[line], charsPerLine);
256	ypos += height;
257	if (ypos > HEIGHT - height) {
258	    /* Wraparound to top of window */
259	    ypos = XPOS;
260	    line = startLine;
261	    startLine = (startLine + 1) % totalLines;
262	}
263	line = (line + 1) % totalLines;
264	CheckAbort ();
265    }
266}
267
268void
269DoPolyText(XParms xp, Parms p, int64_t reps)
270{
271    int     line, startLine;
272
273    startLine = 0;
274    line = 0;
275    for (int i = 0; i != reps; i++) {
276	XDrawText(
277	    xp->d, xp->w, xp->fggc, XPOS, ypos, &items[line*SEGS], SEGS);
278	ypos += height;
279	if (ypos > HEIGHT - height) {
280	    /* Wraparound to top of window */
281	    ypos = XPOS;
282	    line = startLine;
283	    startLine = (startLine + 1) % totalLines;
284	}
285	line = (line + 1) % totalLines;
286	CheckAbort ();
287    }
288}
289
290void
291DoPolyText16(XParms xp, Parms p, int64_t reps)
292{
293    int     line, startLine;
294
295    startLine = 0;
296    line = 0;
297    for (int i = 0; i != reps; i++) {
298	XDrawText16(
299	    xp->d, xp->w, xp->fggc, XPOS, ypos, (XTextItem16 *)&items[line*SEGS], SEGS);
300	ypos += height;
301	if (ypos > HEIGHT - height) {
302	    /* Wraparound to top of window */
303	    ypos = XPOS;
304	    line = startLine;
305	    startLine = (startLine + 1) % totalLines;
306	}
307	line = (line + 1) % totalLines;
308	CheckAbort ();
309    }
310}
311
312void
313DoImageText(XParms xp, Parms p, int64_t reps)
314{
315    int     line, startLine;
316
317    startLine = 0;
318    line = 0;
319    for (int i = 0; i != reps; i++) {
320	XDrawImageString(
321	    xp->d, xp->w, xp->fggc, XPOS, ypos, charBuf[line], charsPerLine);
322	ypos += height;
323	if (ypos > HEIGHT - height) {
324	    /* Wraparound to top of window */
325	    ypos = XPOS;
326	    startLine = (startLine + 17) % totalLines;
327	    line = startLine;
328	}
329	line = (line + 1) % totalLines;
330	CheckAbort ();
331    }
332}
333
334void
335DoImageText16(XParms xp, Parms p, int64_t reps)
336{
337    int     line, startLine;
338
339    startLine = 0;
340    line = 0;
341    for (int i = 0; i != reps; i++) {
342	XDrawImageString16(
343	    xp->d, xp->w, xp->fggc, XPOS, ypos, (XChar2b *)charBuf[line], charsPerLine);
344	ypos += height;
345	if (ypos > HEIGHT - height) {
346	    /* Wraparound to top of window */
347	    ypos = XPOS;
348	    startLine = (startLine + 17) % totalLines;
349	    line = startLine;
350	}
351	line = (line + 1) % totalLines;
352	CheckAbort ();
353    }
354}
355
356void
357ClearTextWin(XParms xp, Parms p)
358{
359    XClearWindow(xp->d, xp->w);
360}
361
362void
363EndText(XParms xp, Parms p)
364{
365    if(font==NULL)return;
366    for (int i = 0; i != totalLines; i++)
367	free(charBuf[i]);
368    free(charBuf);
369    if (p->special)
370	free(items);
371    XFreeFont(xp->d, font);
372    if (bfont != NULL)
373	XFreeFont(xp->d, bfont);
374}
375
376void
377EndText16(XParms xp, Parms p)
378{
379    if(font==NULL)return;
380    if (p->special) {
381	for (int i = 0; i < totalLines; i++) {
382	    free(items[i*SEGS+0].chars);
383	    free(items[i*SEGS+1].chars);
384	    free(items[i*SEGS+2].chars);
385	}
386	free(items);
387    } else {
388	for (int i = 0; i < totalLines; i++) {
389	    free(charBuf[i]);
390	}
391	free(charBuf);
392    }
393    XFreeFont(xp->d, font);
394    if(bfont != NULL) {
395	XFreeFont(xp->d, bfont);
396    }
397}
398
399#ifdef XFT
400#include <X11/extensions/Xrender.h>
401#include <X11/Xft/Xft.h>
402
403static XftFont	*aafont;
404static XftDraw	*aadraw;
405static XftColor	aacolor;
406
407int
408InitAAText(XParms xp, Parms p, int64_t reps)
409{
410    char		ch;
411    XRenderColor	color;
412    FcValue             value;
413    int                 v_len;
414    FcPattern		*pat;
415    FcPattern		*match;
416    FcResult		result;
417
418    pat = FcNameParse((FcChar8 *) p->font);
419    match = XftFontMatch(xp->d, DefaultScreen(xp->d), pat, &result);
420    FcPatternDestroy(pat);
421    if (p->bfont) {
422	    FcPatternDel(match, XFT_RENDER);
423	    FcPatternAddBool(match, XFT_RENDER, False);
424    }
425
426    aafont = XftFontOpenPattern (xp->d, match);
427
428    if (aafont == NULL)
429    {
430	printf("Could not load font '%s', benchmark omitted\n",
431	       p->font);
432	return 0;
433    }
434    if (FcPatternGet(aafont->pattern, FC_FAMILY, 0, &value) != FcResultMatch ||
435        value.type != FcTypeString)
436    {
437	printf("Could not load font '%s', benchmark omitted\n",
438	       p->font);
439	XftFontClose (xp->d, aafont);
440	return 0;
441    }
442    v_len = strlen((char *) value.u.s);
443    if (strncmp((char *) value.u.s, p->font, v_len) != 0 || p->font[v_len] != ':') {
444	printf("Could not load font '%s' (found %s), benchmark omitted\n",
445	       p->font,
446               (char *) value.u.s);
447	XftFontClose (xp->d, aafont);
448	return 0;
449    }
450
451    aadraw = XftDrawCreate (xp->d, xp->w,
452			    xp->vinfo.visual,
453			    xp->cmap);
454
455    if (!aadraw)
456    {
457	printf ("Cannot create XftDraw object\n");
458	XftFontClose (xp->d, aafont);
459	return 0;
460    }
461    color.red = 0;
462    color.green = 0;
463    color.blue = 0;
464    color.alpha = 0xffff;
465    if (!XftColorAllocValue (xp->d,
466			     xp->vinfo.visual,
467			     xp->cmap,
468			     &color, &aacolor))
469    {
470	printf ("Cannot allocate black\n");
471	XftFontClose (xp->d, aafont);
472	XftDrawDestroy (aadraw);
473	aafont = NULL;
474	aadraw = NULL;
475	return 0;
476    }
477
478    ypos = XPOS;
479    height = aafont->height;
480
481    charsPerLine = p->objects;
482    charsPerLine = (charsPerLine + 3) & ~3;
483    p->objects = charsPerLine;
484
485    totalLines = '\177' - ' ' + 1;
486    if (totalLines > reps) totalLines = reps;
487
488    charBuf = malloc(totalLines * sizeof (char *));
489
490    for (int i = 0; i != totalLines; i++) {
491	charBuf[i] = malloc (sizeof (char) * charsPerLine);
492	ch = i + ' ';
493	for (int j = 0; j != charsPerLine; j++) {
494	    charBuf[i][j] = ch;
495	    if (ch == '\177') ch = ' '; else ch++;
496	}
497    }
498    return reps;
499}
500
501void
502DoAAText(XParms xp, Parms p, int64_t reps)
503{
504    int     line, startLine;
505
506    startLine = 0;
507    line = 0;
508    for (int i = 0; i != reps; i++) {
509	XftDrawString8 (aadraw, &aacolor, aafont,
510		       XPOS, ypos, (unsigned char *) charBuf[line], charsPerLine);
511	ypos += height;
512	if (ypos > HEIGHT - height) {
513	    /* Wraparound to top of window */
514	    ypos = XPOS;
515	    line = startLine;
516	    startLine = (startLine + 1) % totalLines;
517	}
518	line = (line + 1) % totalLines;
519	CheckAbort ();
520    }
521}
522
523void
524EndAAText(XParms xp, Parms p)
525{
526    if(!aadraw)return;
527    for (int i = 0; i != totalLines; i++)
528	free(charBuf[i]);
529    free(charBuf);
530    XftDrawDestroy (aadraw);
531    XftFontClose (xp->d, aafont);
532    XftColorFree (xp->d,
533		  xp->vinfo.visual,
534		  xp->cmap,
535		  &aacolor);
536}
537
538#endif
539