📄 font.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#ifdef __cplusplusextern "C" {#endif #include <windows.h>#include <ddraw.h>#include <kni.h>#include <midp_logging.h>#include <pcsl_memory.h>#include <gxapi_constants.h>#include "gxj_intern_graphics.h"#include "gxj_intern_putpixel.h"#include "gxj_intern_font_bitmap.h"#include "gx_font.h"#include "gxj_putpixel.h"#include "font_internal.h"/* * WinCE font notes: * * We use native fonts from WinCE. This makes it possible to support * localized fonts such as CJK characters. Essentially, all text output * is done via ExtTextOut(). Character widths are calculated using * GetTextExtentPoint32W(). * * However, the WinCE APIs are very slow, especially when we have to switch * between drawing to the MIDP screen and a MIDP off-screen bitmap. In order * to have good JBenchmark1 & Jbenchmark2 scores, we use the following * techniques: * * (1) We cache ASCII font bitmaps and render them directly. This * means we don't have to call getScreenBufferHDC() unless you are * drawing text outside of the ASCII range. * (2) We JIT-compile an ARM routine for each ASCII character. This routine * can be used when the text is not clipped. This routine is faster * because it can set pixels without having to read the font bitmap. * The Text test in JB2 shows a progress from 180fps to 230fps with * this optimization. On the i-mate KJAM, the JIT routines occupy about * 15KB of RAM. They may take up more space on a VGA device. * * To disable WinCE native fonts, set USE_NATIVE_FONT=0 in this * file. */#define WIN32_PLATFORM_PSPC 1//#define JWC_WINCE_USE_DIRECT_DRAW ENABLE_WINCE_DIRECT_DRAW#ifdef WIN32_PLATFORM_PSPC// comment this line to use JAVA font#define USE_NATIVE_FONT 0#else // smartphone, we use Java font now and may find a suitable font for it later.#define USE_NATIVE_FONT 0#endif#include <windows.h>#include <windowsx.h>extern HDC getScreenBufferHDC(gxj_pixel_type *buffer, int width, int height);extern LPDIRECTDRAW g_pDD;// variable used at caching hdc for fast font display// pDDS and cachedHDC must both be NULL or both be non-NULLstatic LPDIRECTDRAWSURFACE pFontDDS = NULL;static HDC cachedFontHDC = NULL;static gxj_pixel_type *cachedFontBuffer;/** Separate colors are 8 bits as in Java RGB */#define GET_RED_FROM_PIXEL(P) (((P) >> 8) & 0xF8)#define GET_GREEN_FROM_PIXEL(P) (((P) >> 3) & 0xFC)#define GET_BLUE_FROM_PIXEL(P) (((P) << 3) & 0xF8)/* convert color to 16bit color */#define RGB24TORGB16(x) (((( x ) & 0x00F80000) >> 8) + \ ((( x ) & 0x0000FC00) >> 5) + \ ((( x ) & 0x000000F8) >> 3) )/* convert color to 16bit color */#define RGB16TORGB24(x) (((( x ) << 8) & 0x00F80000) | \ ((( x ) << 5) & 0x0000FC00) | \ ((( x ) << 3) & 0x000000F8) )// pfontbitmap#define TheFontBitmap FontBitmaps[1]#define TheFontBitmapSize 2024 // IMPL_NOTE: must not be hardcoded!static int *compile_glyph(gxj_pixel_type *buf, int bufWidth, int fontWidth, int height, int *scratch_code);#define MIN_FAST_GLYPH 32 // inclusive#define MAX_FAST_GLYPH 127 // exclusive#define NUM_FAST_GLYPHS (MAX_FAST_GLYPH - MIN_FAST_GLYPH)#define FASTIDX(i) (((int)i) - MIN_FAST_GLYPH)#define IS_FAST_GLYPH(c) ((MIN_FAST_GLYPH <= (c)) && ((c) < MAX_FAST_GLYPH))typedef int (*compiled_glyph_drawer)(gxj_pixel_type *dest, int color, int linePitch);typedef struct { int ascent; int descent; int leading; int maxWidth; // If thie font is a raster font, then we can use compiled_glyph_drawer // and cache bitmaps. int is_raster; // The native FONT associated with this MIDP font. HFONT hfont; // The widths of the "fast" glyphs. unsigned char widths[NUM_FAST_GLYPHS]; // The *bit* offset of the bitmap of each glyph. int bit_offsets[NUM_FAST_GLYPHS]; // The compiled glyph drawers, for optimal font drawing speed. // Note: the default font (WinCE system font) should have all // glyphs compiled. This costs about 15KB of code. For all other // fonts, consider compiling only the glyphs for "JBenchmark". compiled_glyph_drawer drawers[NUM_FAST_GLYPHS]; // The bitmaps for the "fast" glyphs. unsigned char *bitmaps;} FastFontInfo;// Cached information about the system font. We only cache the font bitmaps// and widths of the printable ASCII characters (0x20 ~ 0x7e). We use// WinCE API to query and draw the other characters.//// FIXME: we should support other font styles, such as italic, monospace// and bold.static FastFontInfo systemFontInfo;// A counter to check the size of the JIT code.static int totalcode = 0;extern int gfFontInit = 0;static int CvtRef(int refPoint){ int v = 0; switch (refPoint & (TOP | BOTTOM | BASELINE)) { case BOTTOM: v |= TA_BOTTOM; break; case BASELINE: v |= TA_BASELINE; break; case TOP: default: v |= TA_TOP; break; } switch (refPoint & (LEFT | RIGHT | HCENTER)) { case RIGHT: v |= TA_RIGHT; break; case HCENTER: v |= TA_CENTER; break; case LEFT: default: v |= TA_LEFT; break; } return v;}#define MAX_GLYPH_WIDTH 40#define MAX_GLYPH_HEIGHT 40#define MAX_CODE 1000#define R0 0#define R1 1#define R2 2#define LR 14#define PC 15#define AL 0x0estatic int add_imm(int reg, int value) { int opcode; if (value > 0) { opcode = 0x04; // add } else { opcode = 0x02; // sub value = -value; } return (int)(AL << 28 | 1 << 25 | opcode << 21 | reg << 16 | reg << 12 | value);}static int strh(int reg_value, int reg_addr, int offset) { return (int)(AL << 28 | 1 << 24 | 1 << 23 | 2 << 21 | reg_addr << 16 | reg_value << 12 | (offset & 0xf0) << 4 | 0x0b << 4 | (offset & 0x0f));}static int strh_preindexed(int reg_value, int reg_addr, int offset) { return (int)(AL << 28 | 1 << 24 | 1 << 23 | 3 << 21 | reg_addr << 16 | reg_value << 12 | (offset & 0xf0) << 4 | 0x0b << 4 | (offset & 0x0f));}static int mov(int reg_dst, int reg_src) { return (int)(AL << 28 | 0x0d << 21 | reg_dst << 12 | reg_src);}static int mov_imm(int reg_dst, int imm) { return (int)(AL << 28 | 1 << 25 | 0x0d << 21 | reg_dst << 12 | imm);}static int add(int reg, int reg_rm) { return (int)(AL << 28 | 0x04 << 21 | reg << 16 | reg << 12 |reg_rm);}// This is a feeble attemp to deal with anti-aliased fonts. It doesn't// really work because in some cases the 'important' pixels in an anti-// aliased character may not reach the level of intensity required by// the formular below.static int is_pixel_set(gxj_pixel_type pixel) { int r = GET_RED_FROM_PIXEL(pixel); int g = GET_GREEN_FROM_PIXEL(pixel); int b = GET_BLUE_FROM_PIXEL(pixel); if ((r + g + b) < (128 * 3 + 40)) { return 1; } else { return 0; }}int cache_bitmap_and_compile(FastFontInfo* info, HFONT font, int height, int maxWidth, int totalWidth){ int buf_bytes = sizeof(gxj_pixel_type) * maxWidth * height; gxj_pixel_type *buf = (gxj_pixel_type*)pcsl_mem_malloc(buf_bytes); HDC hdc; int i, x, y, max_codes; int *scratch_code; int bitmap_bytes = (totalWidth * height + 7) / 8; unsigned char *bitmap = (unsigned char*)pcsl_mem_malloc(bitmap_bytes); unsigned int bitbyte = 0; int bits = 0; if (info == NULL) { return 0; } hdc = getScreenBufferHDC(buf, maxWidth, height); if (hdc == NULL) { pcsl_mem_free(buf); return 0; } info->bitmaps = bitmap; // In the worst case, for each scan-line we need <maxWidth> instructions // plus 2 instructions to wrap to the next line. We also need two // more instructions to return from the function. max_codes = (maxWidth + 2) * height + 2 + /*slack*/ 40; scratch_code = (int*)pcsl_mem_malloc(sizeof(int) * max_codes); SelectObject(hdc, font); SetTextColor(hdc, 0x0); SetBkMode(hdc, TRANSPARENT); for (i=MIN_FAST_GLYPH; i<MAX_FAST_GLYPH; i++) { TCHAR c = (TCHAR)i; int fontWidth; int *func; memset(buf, 0x0ff, buf_bytes); ExtTextOut(hdc, 0, 0, 0, NULL, &c, 1, NULL); fontWidth = info->widths[FASTIDX(i)]; func = compile_glyph(buf, maxWidth, fontWidth, height, scratch_code); info->drawers[FASTIDX(i)] = (compiled_glyph_drawer)func; for (y=0; y < height; y++) { gxj_pixel_type *b = &buf[y * maxWidth]; for (x=0; x<fontWidth; x++) { if (is_pixel_set(b[x])) { // the pixel is set bitbyte |= (1 << (7-bits)); } bits ++; if (bits == 8) { *bitmap++ = (unsigned char)bitbyte; bits = 0; bitbyte = 0; } } } } if (bits != 0) { *bitmap++ = (unsigned char)bitbyte; } pcsl_mem_free(scratch_code); pcsl_mem_free(buf); FlushInstructionCache(GetCurrentProcess(), 0, 0); return 1;}static int *compile_glyph(gxj_pixel_type *buf, int bufWidth, int fontWidth, int height, int *scratch_code) { int x, y, maxY; int nextcode = 0; int *func; // (1) Find the last non-empty line. This save a few instructions // for the glyphs that have no descending pixels. for (maxY = height-1; maxY >= 0; maxY --) { gxj_pixel_type *p = &buf[maxY * bufWidth]; int empty = 1; for (x=0; x<fontWidth; x++) { if (p[x] == 0) { empty = 0; break; } } if (!empty) { break; } } for (y=0; y<=maxY; y++) { int cursor = 0; gxj_pixel_type *b = &buf[y * bufWidth]; for (x=0; x<fontWidth; x++) { if (is_pixel_set(b[x])) { // this pixel is set.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -