Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/java2d/x11/X11TextRenderer_md.c
32288 views
/*1* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "GlyphImageRef.h"2627#ifdef HEADLESS28#include "SurfaceData.h"29#else30#include "X11SurfaceData.h"31#include "GraphicsPrimitiveMgr.h"32#endif /* !HEADLESS */33#include <jlong.h>3435#define TEXT_BM_WIDTH 102436#define TEXT_BM_HEIGHT 323738#ifndef HEADLESS3940static jboolean checkPixmap(JNIEnv *env, AwtGraphicsConfigDataPtr cData)41{42XImage *img;43int image_size;44Window root;4546if (cData->monoImage == NULL) {47img = XCreateImage(awt_display, NULL, 1, XYBitmap, 0, 0,48TEXT_BM_WIDTH, TEXT_BM_HEIGHT, 32, 0);49if (img != NULL) {50image_size = img->bytes_per_line * TEXT_BM_HEIGHT;51// assert(BM_W and BM_H are not large enough to overflow);52img->data = (char *) malloc(image_size);53if (img->data == NULL) {54XFree(img);55} else {56// Force same bit/byte ordering57img->bitmap_bit_order = img->byte_order;58cData->monoImage = img;59}60}61if (cData->monoImage == NULL) {62JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmap for text");63return JNI_FALSE;64}65}66if (cData->monoPixmap == 0 ||67cData->monoPixmapGC == NULL ||68cData->monoPixmapWidth != TEXT_BM_WIDTH ||69cData->monoPixmapHeight != TEXT_BM_HEIGHT)70{71if (cData->monoPixmap != 0) {72XFreePixmap(awt_display, cData->monoPixmap);73cData->monoPixmap = 0;74}75if (cData->monoPixmapGC != NULL) {76XFreeGC(awt_display, cData->monoPixmapGC);77cData->monoPixmapGC = 0;78}79root = RootWindow(awt_display, cData->awt_visInfo.screen);80cData->monoPixmap = XCreatePixmap(awt_display, root,81TEXT_BM_WIDTH, TEXT_BM_HEIGHT, 1);82if (cData->monoPixmap == 0) {83JNU_ThrowOutOfMemoryError(env, "Cannot allocate pixmap for text");84return JNI_FALSE;85}86cData->monoPixmapGC = XCreateGC(awt_display, cData->monoPixmap,870, NULL);88if (cData->monoPixmapGC == NULL) {89XFreePixmap(awt_display, cData->monoPixmap);90cData->monoPixmap = 0;91JNU_ThrowOutOfMemoryError(env, "Cannot allocate pixmap for text");92return JNI_FALSE;93}94XSetForeground(awt_display, cData->monoPixmapGC, 1);95XSetBackground(awt_display, cData->monoPixmapGC, 0);96cData->monoPixmapWidth = TEXT_BM_WIDTH;97cData->monoPixmapHeight = TEXT_BM_HEIGHT;98}99return JNI_TRUE;100}101102static void FillBitmap(XImage *theImage,103ImageRef *glyphs, jint totalGlyphs,104jint clipLeft, jint clipTop,105jint clipRight, jint clipBottom)106{107int glyphCounter;108int scan = theImage->bytes_per_line;109int y, left, top, right, bottom, width, height;110jubyte *pPix;111const jubyte *pixels;112unsigned int rowBytes;113114pPix = (jubyte *) theImage->data;115glyphCounter = ((clipRight - clipLeft) + 7) >> 3;116for (y = clipTop; y < clipBottom; y++) {117memset(pPix, 0, glyphCounter);118pPix += scan;119}120121for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) {122pixels = (const jubyte *)glyphs[glyphCounter].pixels;123if (!pixels) {124continue;125}126rowBytes = glyphs[glyphCounter].width;127left = glyphs[glyphCounter].x;128top = glyphs[glyphCounter].y;129width = glyphs[glyphCounter].width;130height = glyphs[glyphCounter].height;131132/* if any clipping required, modify parameters now */133right = left + width;134bottom = top + height;135if (left < clipLeft) {136pixels += clipLeft - left;137left = clipLeft;138}139if (top < clipTop) {140pixels += (clipTop - top) * rowBytes;141top = clipTop;142}143if (right > clipRight) {144right = clipRight;145}146if (bottom > clipBottom) {147bottom = clipBottom;148}149if (right <= left || bottom <= top) {150continue;151}152width = right - left;153height = bottom - top;154top -= clipTop;155left -= clipLeft;156pPix = ((jubyte *) theImage->data) + (left >> 3) + (intptr_t) top * scan;157left &= 0x07;158if (theImage->bitmap_bit_order == MSBFirst) {159left = 0x80 >> left;160do {161int x = 0, bx = 0;162int pix = pPix[0];163int bit = left;164do {165if (bit == 0) {166pPix[bx] = (jubyte) pix;167pix = pPix[++bx];168bit = 0x80;169}170if (pixels[x]) {171pix |= bit;172}173bit >>= 1;174} while (++x < width);175pPix[bx] = (jubyte) pix;176pPix += scan;177pixels += rowBytes;178} while (--height > 0);179} else {180left = 1 << left;181do {182int x = 0, bx = 0;183int pix = pPix[0];184int bit = left;185do {186if ((bit >> 8) != 0) {187pPix[bx] = (jubyte) pix;188pix = pPix[++bx];189bit = 1;190}191if (pixels[x]) {192pix |= bit;193}194bit <<= 1;195} while (++x < width);196pPix[bx] = (jubyte) pix;197pPix += scan;198pixels += rowBytes;199} while (--height > 0);200}201}202}203#endif /* !HEADLESS */204205JNIEXPORT void JNICALL206AWTDrawGlyphList(JNIEnv *env, jobject xtr,207jlong dstData, jlong gc,208SurfaceDataBounds *bounds, ImageRef *glyphs, jint totalGlyphs)209{210#ifndef HEADLESS211GC xgc, theGC;212XImage *theImage;213Pixmap thePixmap;214XGCValues xgcv;215int scan, screen;216AwtGraphicsConfigDataPtr cData;217X11SDOps *xsdo = (X11SDOps *)jlong_to_ptr(dstData);218jint cx1, cy1, cx2, cy2;219220if (xsdo == NULL) {221return;222}223224xgc = (GC)gc;225if (xgc == NULL) {226return;227}228229screen = xsdo->configData->awt_visInfo.screen;230cData = getDefaultConfig(screen);231if (!checkPixmap(env, cData)) {232return;233}234theImage = cData->monoImage;235thePixmap = cData->monoPixmap;236theGC = cData->monoPixmapGC;237238scan = theImage->bytes_per_line;239240xgcv.fill_style = FillStippled;241xgcv.stipple = thePixmap;242xgcv.ts_x_origin = bounds->x1;243xgcv.ts_y_origin = bounds->y1;244XChangeGC(awt_display, xgc,245GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,246&xgcv);247248cy1 = bounds->y1;249while (cy1 < bounds->y2) {250cy2 = cy1 + TEXT_BM_HEIGHT;251if (cy2 > bounds->y2) cy2 = bounds->y2;252253cx1 = bounds->x1;254while (cx1 < bounds->x2) {255cx2 = cx1 + TEXT_BM_WIDTH;256if (cx2 > bounds->x2) cx2 = bounds->x2;257258FillBitmap(theImage,259glyphs,260totalGlyphs,261cx1, cy1, cx2, cy2);262263// NOTE: Since we are tiling around by BM_W, BM_H offsets264// and thePixmap is BM_W x BM_H, we do not have to move265// the TSOrigin at each step since the stipple repeats266// every BM_W, BM_H units267XPutImage(awt_display, thePixmap, theGC, theImage,2680, 0, 0, 0, cx2 - cx1, cy2 - cy1);269/* MGA on Linux doesn't pick up the new stipple image data,270* probably because it caches the image as a hardware pixmap271* and doesn't update it when the pixmap image data is changed.272* So if the loop is executed more than once, update the GC273* which triggers the required behaviour. This extra XChangeGC274* call only happens on large or rotated text so isn't a275* significant new overhead..276* This code needs to execute on a Solaris client too, in case277* we are remote displaying to a MGA.278*/279if (cy1 != bounds->y1 || cx1 != bounds->x1) {280XChangeGC(awt_display, xgc, GCStipple, &xgcv);281}282283XFillRectangle(awt_display, xsdo->drawable, xgc,284cx1, cy1, cx2 - cx1, cy2 - cy1);285286cx1 = cx2;287}288289cy1 = cy2;290}291XSetFillStyle(awt_display, xgc, FillSolid);292293X11SD_DirectRenderNotify(env, xsdo);294#endif /* !HEADLESS */295}296297298