1 namespace gfx::drivers;
3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
10 #if !defined(ECERE_NOTRUETYPE)
12 #include FT_FREETYPE_H
13 #include FT_TRUETYPE_TABLES_H
14 #include FT_UNPATENTED_HINTING_H
15 #define property _property
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
21 #define String _String
24 #elif !defined(ECERE_NOTRUETYPE) && !defined(ECERE_NOFONTCONFIG)
26 #include <fontconfig/fontconfig.h>
27 static FcConfig * fcConfig;
36 #pragma warning(disable:4244)
37 #pragma warning(disable:4018)
43 public define LIGHTSHIFT = 5;
44 public define LIGHTSTEPS = 1<<LIGHTSHIFT;
46 /*#ifndef ECERE_VANILLA
48 static bool rgbLookupSet = true;
50 /*static */byte defaultRGBLookup[32768];
51 /*static */bool rgbLookupSet = false;
57 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) && defined(__WIN32__)
58 import "OpenGLDisplayDriver"
59 import "Direct3D8DisplayDriver"
60 import "Direct3D9DisplayDriver"
63 #if !defined(ECERE_NOTRUETYPE)
65 #if !defined(ECERE_VANILLA)
68 static void ComputeOutline(byte *out, byte *src, uint w, uint h, float size, float fade)
70 uint i, numPixels = w * h;
71 short * distx = new short[2 * numPixels], * disty = distx + numPixels;
72 float * data = new0 float[4 * numPixels], * gx = data + numPixels, * gy = gx + numPixels, * dist = gy + numPixels;
73 float rb = Max(1.5f, size), ra = rb - (rb-1)*fade - 1;
74 float inv_rw = 1/(rb-ra);
76 for(i = 0; i < numPixels; i++)
77 data[i] = src[i] / 255;
79 computegradient(data, w, h, gx, gy);
80 edtaa3(data, gx, gy, w, h, distx, disty, dist);
82 for(i = 0; i < numPixels; i++)
84 float value = 1 - Max(0.0f, Min(1.0f, (dist[i]-ra)*inv_rw));
85 out[i] = (byte)(255 * value * value);
91 static void BlitOutline(byte * dst, int dx, int dy, int w, int h, byte * src, int sx, int sy, int sw, int sh, int srcStride)
98 for(y = 0; y < sh; y++)
99 memcpy(dst + w * (dy+y) + dx, src + srcStride * (sy+y) + sx, sw);
103 static void MeasureOutline(byte * image, int w, int h, int * _x1, int * _y1, int * _x2, int * _y2)
105 int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
107 for(x = 0; x < w && x1 == MAXINT; x++)
109 for(y = 0; y < h; y++)
116 for(x = w-1; x >= 0 && x2 == MININT; x--)
118 for(y = 0; y < h; y++)
125 for(y = 0; y < h && y1 == MAXINT; y++)
127 for(x = 0; x < w; x++)
134 for(y = h-1; y >= 0 && y2 == MININT; y--)
136 for(x = 0; x < w; x++)
152 static byte * MakeDistanceMap( byte *out, byte *img, uint width, uint height, int k, int t )
154 short * xdist = new short[ width * height];
155 short * ydist = new short[ width * height];
156 float * gx = new float[ width * height];
157 float * gy = new float[ width * height];
158 float * data = new float[ width * height];
159 float * outside = new float[ width * height];
160 float * inside = new float[ width * height];
165 // Convert img into float (data)
166 float img_min = 255, img_max = -255;
167 for( i=0; i<width*height; ++i)
171 if (v > img_max) img_max = v;
172 if (v < img_min) img_min = v;
177 // Rescale image levels between 0 and 1
178 for( i=0; i<width*height; ++i)
180 data[i] = (img[i]-img_min)/img_max;
183 // Compute outside = edtaa3(bitmap); % Transform background (0's)
184 computegradient( data, width, height, gx, gy);
185 edtaa3(data, gx, gy, width, height, xdist, ydist, outside);
186 for( i=0; i<width*height; ++i)
190 // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
191 memset(gx, 0, sizeof(float)*width*height );
192 memset(gy, 0, sizeof(float)*width*height );
193 for( i=0; i<width*height; ++i)
194 data[i] = 1 - data[i];
195 computegradient( data, width, height, gx, gy);
196 edtaa3(data, gx, gy, width, height, xdist, ydist, inside);
197 for( i=0; i<width*height; ++i)
201 // distmap = outside - inside; % Bipolar distance field
202 for( i=0; i<width*height; ++i)
204 outside[i] -= inside[i];
205 outside[i] = t+outside[i]* k;
206 if( outside[i] < 0 ) outside[i] = 0;
207 if( outside[i] > 255 ) outside[i] = 255;
208 out[i] = 255 - (byte) outside[i];
209 //out[i] = (byte) outside[i];
213 memset(out, 0, width * height);
226 #define MAX_FONT_LINK_ENTRIES 10
228 static HB_Script theCurrentScript;
230 static unichar UTF16GetChar(const uint16 *string, int * nw)
233 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
235 ch = HB_SurrogateToUcs4(string[0], string[1]);
246 static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
248 FT_Face face = ((FontEntry)font->userData).face;
252 if (length > *numGlyphs)
255 for (c = 0; c < length; c += nw)
257 unichar ch = UTF16GetChar(string + c, &nw);
258 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
260 *numGlyphs = glyph_pos;
264 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
266 FontEntry entry = font->userData;
267 Font glFont = entry.font;
270 GlyphPack pack = glFont.asciiPack;
272 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
274 if(glFont.fontEntries[fontEntryNum] == entry)
278 for(c = 0; c < numGlyphs; c++)
281 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
282 uint packNo = glyphNo & 0xFFFFFF80;
283 if(packNo != lastPack)
285 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
288 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
289 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
290 pack.bitmap.alphaBlend = true;
294 glyph = &pack.glyphs[glyphNo & 0x7F];
295 advances[c] = glyph->ax;
299 static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
301 FT_Face face = ((FontEntry)font->userData).face;
304 for (c = 0; c < length; c += nw)
306 unichar ch = UTF16GetChar(string + c, &nw);
307 if(!FT_Get_Char_Index(face, ch))
313 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
315 FT_Face face = (FT_Face)font;
316 FT_ULong ftlen = *length;
319 if (!FT_IS_SFNT(face))
320 return HB_Err_Invalid_Argument;
322 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
323 *length = (uint)ftlen;
324 return (HB_Error)error;
327 static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
329 HB_Error error = HB_Err_Ok;
330 FT_Face face = (FT_Face)font->userData;
332 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
334 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
337 if (face->glyph->format != ft_glyph_format_outline)
338 return (HB_Error)HB_Err_Invalid_SubTable;
340 *nPoints = face->glyph->outline.n_points;
344 if (point > *nPoints)
345 return (HB_Error)HB_Err_Invalid_SubTable;
347 *xpos = (int)face->glyph->outline.points[point].x;
348 *ypos = (int)face->glyph->outline.points[point].y;
353 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
355 FontEntry entry = font->userData;
356 Font glFont = entry.font;
358 GlyphPack pack = glFont.asciiPack;
360 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
362 if(glFont.fontEntries[fontEntryNum] == entry)
367 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
368 uint packNo = glyphNo & 0xFFFFFF80;
369 if(packNo != lastPack)
371 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
374 pack = { key = (uintptr)packNo };
375 glFont.glyphPacks.Add(pack);
376 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
377 pack.bitmap.alphaBlend = true;
381 glyph = &pack.glyphs[glyphNo & 0x7F];
383 metrics->x = glyph->ax;
385 metrics->width = glyph->w;
386 metrics->height = glyph->h;
387 metrics->xOffset = glyph->bx;
388 metrics->yOffset = glyph->by;
392 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
394 FontEntry entry = font->userData;
395 FT_Face face = entry.face;
397 // Note that we aren't scanning the VDMX table which we probably would in
399 if(metric == HB_FontAscent)
400 return face->ascender;
404 static HB_FontClass hb_fontClass =
406 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
407 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
410 static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
412 File f = stream->descriptor.pointer;
413 f.Seek((int)offset, start);
414 return count ? f.Read(buffer, 1, (uint)count) : 0;
417 static void FT_stream_close(FT_Stream stream)
419 File f = stream->descriptor.pointer;
424 static FT_Library ftLibrary;
427 static BinaryTree loadedFonts
429 CompareKey = (void *)BinaryTree::CompareString
432 class FontEntry : BTNode
441 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
458 FT_Done_FreeType(ftLibrary);
465 static float FaceSetCharSize(FT_Face face, float size)
468 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
470 if(face->num_fixed_sizes)
473 int bestDiff = MAXINT, best = 0;
474 FT_Bitmap_Size * sizes = face->available_sizes;
475 int wishedHeight = (int)(size * 96 / 72);
476 for(c = 0; c < face->num_fixed_sizes; c++)
478 int diff = abs(sizes[c].height - wishedHeight);
485 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
488 face->ascender = sizes[best].height;
489 scale = (float)wishedHeight / sizes[best].height;
508 class GlyphPack : BTNode
510 GlyphInfo glyphs[256];
512 BinaryTree outlines { };
513 int cellWidth, cellHeight;
515 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
517 #if !defined(ECERE_NOTRUETYPE)
519 int maxWidth, maxHeight;
520 int cellWidth, cellHeight;
522 FontEntry fontEntry = null;
525 bool isGlyph = ((uint)key & 0x80000000) != 0;
526 //int curScript = ((uint)key & 0x7F000000) >> 24;
527 unichar testChar = 0;
533 case HB_Script_Arabic:
535 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
537 case HB_Script_Devanagari:
540 case 60: testChar = 'あ'; break;
541 case 61: testChar = 0x3400; break;
548 FT_Vector pen = { 0, 0 };
551 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
552 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
553 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
554 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
555 FT_Set_Transform( fontEntry.face, &matrix, &pen );
557 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
563 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
565 fontEntry = font.fontEntries[c];
569 FT_Vector pen = { 0, 0 };
573 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
574 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
575 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
576 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
577 FT_Set_Transform(fontEntry.face, &matrix, &pen);
579 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
580 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
582 font.scale = fontEntry.scale;
585 if(!fontEntry.face->units_per_EM)
586 font.ascent = (int)((double)fontEntry.face->ascender);
588 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
591 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
592 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
593 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
594 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
599 for(c = 0; c < 128; c++)
604 uint glyph = ((uint)key | c) & 0xFFFFFF;
605 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
607 fontEntry = font.fontEntries[entry];
608 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
610 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
612 //printf("%s: Accepted entry %d ", font.faceName, entry);
620 for(entry = startFontEntry; ; entry++)
623 fontEntry = font.fontEntries[entry];
624 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
626 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
631 scales[c] = fontEntry.scale;
632 faces[c] = fontEntry.face;
633 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
634 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
635 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
637 this.cellWidth = cellWidth = maxWidth;
638 this.cellHeight = cellHeight = maxHeight;
640 width = maxWidth * 16;
641 height = maxHeight * 8;
645 width = pow2i(height * 16);
646 height = pow2i(height * 8);
649 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
651 Bitmap bitmap = this.bitmap;
653 bitmap.transparent = true;
655 for(c = 0; c < 128; c++)
659 int sx = (c % 16) * cellWidth;
660 int sy = (c / 16) * cellHeight;
662 byte * picture = (byte *)bitmap.picture;
663 GlyphInfo * glyph = &glyphs[c];
664 FT_GlyphSlot slot = faces[c]->glyph;
665 double em_size = 1.0 * faces[c]->units_per_EM;
666 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
667 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
668 double ascender = faces[c]->ascender * y_scale;
669 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
671 FT_Load_Glyph(faces[c], glyphNo, /*FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT*/ FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/); // FT_LOAD_RENDER // FT_LOAD_NO_HINTING
673 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
677 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
679 glyph->left = slot->bitmap_left;
680 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
681 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
682 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
683 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
685 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
686 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
688 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
690 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
691 //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (font.height - (faces[c]->size->metrics.height >> 6));
693 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
694 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
696 // printf("[char: %d] mode: %d, width: %d, height: %d, pitch: %d\n", key + c, slot->bitmap.pixel_mode, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
697 xMax = x + slot->bitmap.width;
698 yMax = y + slot->bitmap.rows;
704 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
706 for(j = y, q = 0; j<yMax; j++)
708 for(p = 0, i = x; i<xMax; i++)
710 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
717 q += slot->bitmap.pitch;
720 //max = numPixels ? (total / numPixels) : 1;
722 for(j = y, q = 0; j<yMax; j++)
725 for(p = 0, i = x; i<xMax; i++)
727 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
729 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
731 if(!bit) { bit = 0x80; p++; }
735 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
736 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
739 q += slot->bitmap.pitch;
744 glyph->w = slot->bitmap.width;
745 glyph->h = slot->bitmap.rows;
746 glyph->glyphNo = glyphNo;
747 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
748 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
749 glyph->scale = scales[c];
751 glyph->ax = (int)slot->advance.x;
752 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
759 for(c = 0; c<256; c++)
760 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
761 bitmap.pixelFormat = pixelFormat8;
764 //strcpy(fileName, faceName);
766 strcat(fileName, "Bold");
768 sprintf(fileName, "font%d", fid++);
769 ChangeExtension(fileName, "pcx", fileName);
771 bitmap.Save(fileName, null, 0);
772 bitmap.pixelFormat = pixelFormatAlpha;
776 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
778 bitmap.keepData = true; // For outlines
779 displaySystem.Lock();
780 #if defined(__WIN32__)
781 // Is this check still required?
782 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
783 displaySystem.driver == class(Direct3D8DisplayDriver) ||
784 displaySystem.driver == class(Direct3D9DisplayDriver))
786 bitmap.MakeDD(displaySystem);
787 displaySystem.Unlock();
793 void RenderOutline(GlyphPack outline, Font font, DisplaySystem displaySystem)
795 #if !defined(ECERE_NOTRUETYPE) && !defined(ECERE_VANILLA)
797 int pCellWidth = this.cellWidth, pCellHeight = this.cellHeight;
798 int cellWidth, cellHeight;
800 uintptr key = outline.key;
801 float outlineSize = (float)(key >> 16);
802 float fade = ((uint32)key & 0xFFFF) / 255.f;
803 GlyphInfo * widest = null, * highest = null;
804 uint widestIndex = 0, highestIndex = 0;
806 int minX1 = MAXINT, minY1 = MAXINT;
807 int maxX2 = MININT, maxY2 = MININT;
809 byte * bigger = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
810 byte * field = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
813 // Test biggest glyphs to determine cell width & height:
814 for(c = 0; c < 128; c++)
817 if(glyph->w > (widest ? widest->w : 0))
818 widest = glyph, widestIndex = c;
819 if(glyph->h > (highest ? highest->h : 0))
820 highest = glyph, highestIndex = c;
825 for(glyph = widest; glyph; glyph = (glyph == widest && glyph != highest) ? highest : null)
827 int index = (glyph == widest) ? widestIndex : highestIndex;
828 int x = (index & 0xF) * pCellWidth, y = (index >> 4) * pCellHeight;
829 int w = pCellWidth * timesBigger, h = pCellHeight * timesBigger;
832 memset(bigger, 0, w * h);
833 BlitOutline(bigger, (w - pCellWidth)/2, (h - pCellHeight)/2, w, h, bitmap.picture, x, y, pCellWidth, pCellHeight, bitmap.width);
834 ComputeOutline(field, bigger, w, h, outlineSize, fade);
835 MeasureOutline(field, w, h, &x1, &y1, &x2, &y2);
836 minX1 = Min(minX1, x1);
837 minY1 = Min(minY1, y1);
838 maxX2 = Max(maxX2, x2);
839 maxY2 = Max(maxY2, y2);
842 int x1 = (timesBigger*pCellWidth - pCellWidth) / 2, x2 = x1 + pCellWidth-1;
843 int y1 = (timesBigger*pCellHeight - pCellHeight) / 2, y2 = y1 + pCellHeight-1;
844 ox = -Max(0, x1 - minX1);
845 oy = -Max(0, y1 - minY1);
846 cellWidth = pCellWidth - ox + Max(0, (maxX2 > x2) ? (maxX2 - x2) : 0);
847 cellHeight = pCellHeight - oy + Max(0, (maxY2 > y2) ? (maxY2 - y2) : 0);
850 width = cellWidth * 16;
851 height = cellHeight * 8;
852 if(true) //TEXTURES_MUST_BE_POWER_OF_2)
854 width = pow2i(width);
855 height = pow2i(height);
858 if(outline.bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false))
860 Bitmap bitmap = outline.bitmap;
861 byte * picture = (byte *)bitmap.picture;
862 memset(picture, 0, width * height);
864 for(c = 0; c < 128; c++)
866 GlyphInfo * glyph = &outline.glyphs[c];
867 int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
869 memset(bigger, 0, cellWidth * cellHeight);
870 BlitOutline(bigger, -ox, -oy, cellWidth, cellHeight,
872 (c & 0xF) * pCellWidth, (c >> 4) * pCellHeight,
873 pCellWidth, pCellHeight,
876 // Don't waste time on empty glyphs
879 ComputeOutline(field, bigger, cellWidth, cellHeight, outlineSize, fade);
880 MeasureOutline(field, cellWidth, cellHeight, &x1, &y1, &x2, &y2);
881 if(x2 > x1) w = x2-x1+1;
882 if(y2 > y1) h = y2-y1+1;
885 memset(field, 0, cellWidth * cellHeight);
887 glyph->x = (c & 0xF) * cellWidth;
888 glyph->y = (c >> 4) * cellHeight;
889 BlitOutline(picture, glyph->x, glyph->y, width, height, field, 0, 0, cellWidth, cellHeight, cellWidth);
891 glyph->glyphNo = glyphs[c].glyphNo;
892 glyph->scale = glyphs[c].scale;
893 glyph->left = glyphs[c].left + ox;
894 glyph->top = glyphs[c].top + oy;
895 if(w) { glyph->x += x1; glyph->left += x1; }
896 if(h) { glyph->y += y1; glyph->top += y1; }
899 glyph->bx = glyphs[c].bx;
900 glyph->by = glyphs[c].by;
901 glyph->ax = glyphs[c].ax;
902 glyph->ay = glyphs[c].ay;
910 for(c = 0; c<256; c++)
911 outline.bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
912 outline.bitmap.pixelFormat = pixelFormat8;
915 //strcpy(fileName, faceName);
917 strcat(fileName, "Bold");
919 sprintf(fileName, "font%d", fid++);
920 ChangeExtension(fileName, "pcx", fileName);
922 outline.bitmap.Save(fileName, null, 0);
923 outline.bitmap.pixelFormat = pixelFormatAlpha;
928 char fileName[MAX_LOCATION];
930 sprintf(fileName, "template%03d.png", num);
931 bitmap.Save(fileName, null, 0);
932 sprintf(fileName, "outline%03d.png", num++);
933 outline.bitmap.Save(fileName, null, 0);
936 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
938 displaySystem.Lock();
939 #if defined(__WIN32__)
940 // Is this check still required?
941 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
942 displaySystem.driver == class(Direct3D8DisplayDriver) ||
943 displaySystem.driver == class(Direct3D9DisplayDriver))
945 bitmap.MakeDD(displaySystem);
946 displaySystem.Unlock();
955 #if !defined(ECERE_NOTRUETYPE)
956 static HB_ShaperItem shaper_item;
958 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
960 static uint maxGlyphs = 0;
961 HB_Glyph * glyphs = shaper_item.glyphs;
963 shaper_item.kerning_applied = 0;
964 shaper_item.string = string;
965 shaper_item.stringLength = len;
966 shaper_item.item.script = script;
967 shaper_item.item.pos = 0;
968 shaper_item.item.length = shaper_item.stringLength;
969 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
970 shaper_item.item.bidiLevel = 1;
972 shaper_item.item.bidiLevel = 0;
973 shaper_item.shaperFlags = 0;
974 shaper_item.font = &entry.hbFont;
975 shaper_item.face = entry.hbFace;
976 shaper_item.num_glyphs = shaper_item.item.length;
977 shaper_item.glyphIndicesPresent = 0;
978 shaper_item.initialGlyphCount = 0;
979 shaper_item.num_glyphs = 0;
980 shaper_item.glyphs = null;
982 while(!HB_ShapeItem(&shaper_item))
984 if(shaper_item.num_glyphs > maxGlyphs)
986 maxGlyphs = shaper_item.num_glyphs;
987 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
988 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
989 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
990 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
991 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
995 shaper_item.glyphs = glyphs;
996 shaper_item.num_glyphs = maxGlyphs;
1000 *numGlyphs = shaper_item.num_glyphs;
1001 *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
1002 return shaper_item.glyphs;
1006 delete shaper_item.glyphs;
1007 delete shaper_item.attributes;
1008 delete shaper_item.advances;
1009 delete shaper_item.offsets;
1010 delete shaper_item.log_clusters;
1014 public class Font : struct
1016 BinaryTree glyphPacks { };
1017 GlyphPack asciiPack { };
1018 #if !defined(ECERE_NOTRUETYPE)
1019 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
1026 DisplaySystem displaySystem;
1032 #if !defined(ECERE_NOTRUETYPE)
1034 while((pack = (GlyphPack)glyphPacks.root))
1036 glyphPacks.Remove(pack);
1041 public property int ascent
1043 get { return (int)(this ? ascent * scale : 0); }
1047 public class LFBDisplay : struct
1051 byte rgbLookup[32768];
1052 byte lightTable[256][LIGHTSTEPS];
1053 OldList updateBoxes;
1056 void (* displayCallback)(Display display, Box updateBox);
1059 public class LFBSystem : struct
1063 ColorAlpha * palette;
1064 byte rgbLookup[32768];
1071 ColorAlpha * palette = GetDefaultPalette();
1072 for(c = 16; c < 232; c++)
1074 Color555 color = palette[c].color;
1075 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
1076 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
1077 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
1078 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
1080 for(c = 232; c < 246; c++)
1082 Color555 color = palette[c].color;
1083 defaultRGBLookup[color] = (byte)c;
1086 for(c = 246; c < 256; c++)
1088 Color555 color = palette[c].color;
1089 defaultRGBLookup[color] = (byte)c;
1091 for(c = 0; c < 16; c++)
1093 Color555 color = palette[c].color;
1094 defaultRGBLookup[color] = (byte)c;
1097 for(c = 0; c<32768; c++)
1099 Color color = (Color)(Color555)c;
1100 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
1101 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
1104 rgbLookupSet = true;
1109 public class LFBSurface : struct
1112 // For compatibility with 3D drivers as well
1117 bool writingOutline;
1121 // Drawing attributes
1122 uint foreground, background;
1123 ColorAlpha foregroundRgb;
1126 byte * paletteShades;
1131 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
1133 if(recordA->zMin > recordB->zMin)
1135 else if(recordA->zMin < recordB->zMin)
1137 else if(recordA > recordB)
1139 else if(recordA < recordB)
1146 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
1149 char fileName[MAX_FILENAME];
1154 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
1156 //if(fontType == TRUETYPE_FONTTYPE)
1158 FontData * fontData = (FontData *) lParam;
1159 char * fileName = (char *)lParam;
1161 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
1162 int italic = (fontData->flags.italic) ? 1 : 0;
1163 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
1165 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
1166 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
1171 char entryName[1024];
1172 char fontFileName[1024];
1175 DWORD sizeFileName = 1024;
1177 if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
1179 if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
1182 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
1184 char ch = entryName[c];
1185 if(ch == '&') { c = -1; break; }
1186 else if(ch != ' ') break;
1188 if(c >= 0) continue;
1189 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
1191 char ch = entryName[c];
1192 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
1193 else if(ch != ' ') break;
1196 if(atoi(entryName + c))
1198 if(c >= 0) continue;
1200 strcpy(fileName, fontFileName);
1214 #if !defined(ECERE_NOTRUETYPE)
1215 static int utf16BufferSize = 0;
1216 static uint16 * utf16 = null;
1219 public class LFBDisplayDriver : DisplayDriver
1221 class_property(name) = "LFB";
1223 bool CreateDisplaySystem(DisplaySystem displaySystem)
1225 displaySystem.flags.memBackBuffer = true;
1226 // displaySystem.pixelFormat = pixelFormat888;
1230 void DestroyDisplaySystem(DisplaySystem displaySystem)
1234 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1236 delete bitmap.picture;
1237 if(bitmap.allocatePalette)
1238 delete bitmap.palette;
1241 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1243 bool result = false;
1246 switch(GetColorDepthShifts(format))
1248 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1249 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1250 case 2: stride = width; break;
1253 bitmap.stride = stride;
1254 bitmap.width = width;
1255 bitmap.height = height;
1256 bitmap.size = (uint32) stride * (uint32)height;
1257 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
1258 bitmap.pixelFormat = format;
1259 bitmap.transparent = false;
1261 surface.box.left = surface.box.top = 0;
1262 surface.box.right = width - 1;
1263 surface.box.bottom = height - 1;
1265 bitmap.picture = new0 byte[bitmap.sizeBytes];
1268 bitmap.allocatePalette = allocatePalette;
1271 bitmap.palette = new ColorAlpha[256];
1274 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1280 bitmap.palette = GetDefaultPalette();
1285 FreeBitmap(displaySystem, bitmap);
1289 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1291 bool result = false;
1292 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
1296 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
1298 if(src.transparent && src.pixelFormat == pixelFormat888)
1302 DWORD * picture = (DWORD *)src.picture;
1304 for(c = 0; c<src.size; c++, picture++)
1306 if(*picture & 0xFFFFFF)
1307 *picture = *picture | 0xFF000000;
1309 *picture = *picture & 0xFFFFFF;
1318 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
1320 if(format == pixelFormat8)
1323 bitmap.palette = palette;
1324 else if(lfbSystem && lfbSystem.palette)
1325 bitmap.palette = lfbSystem.palette;
1327 bitmap.palette = src.palette;
1330 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
1332 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
1333 bitmap.transparent = src.transparent;
1334 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
1336 if(src.palette != bitmap.palette)
1338 if(src.allocatePalette)
1340 src.allocatePalette = false;
1342 src.picture = bitmap.picture;
1343 src.palette = bitmap.palette;
1344 src.stride = bitmap.stride;
1345 src.size = bitmap.size;
1346 src.sizeBytes = bitmap.sizeBytes;
1347 src.pixelFormat = bitmap.pixelFormat;
1352 bitmap.palette = null;
1353 bitmap.picture = null;
1361 void DestroyDisplay(Display display)
1363 LFBDisplay lfbDisplay = display.driverData;
1364 delete lfbDisplay.bitmap.palette;
1367 bool CreateDisplay(Display display)
1369 bool result = false;
1370 LFBDisplay lfbDisplay = display.driverData;
1373 lfbDisplay = display.driverData = LFBDisplay { };
1374 lfbDisplay.selfManaged = true;
1375 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1378 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1380 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1386 bool DisplaySize(Display display, int width, int height)
1388 LFBDisplay lfbDisplay = display.driverData;
1389 //display.width = width;
1390 //display.height = height;
1391 lfbDisplay.bitmap.width = width;
1392 lfbDisplay.bitmap.height = height;
1394 lfbDisplay.updateBox.left = display.width;
1395 lfbDisplay.updateBox.top = display.height;
1396 lfbDisplay.updateBox.right = 0;
1397 lfbDisplay.updateBox.bottom = 0;
1400 if(lfbDisplay.selfManaged)
1402 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1403 lfbDisplay.bitmap.stride = width;
1405 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1409 void DisplayPosition(Display display, int x, int y)
1411 LFBDisplay lfbDisplay = display.driverData;
1416 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1418 LFBDisplay lfbDisplay = display.driverData;
1425 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1426 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1427 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1430 for(c = 0; c<32768; c++)
1431 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1433 for(c=0; c<256; c++)
1436 for(i=0; i<LIGHTSTEPS; i++)
1438 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1439 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1440 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1441 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1445 if(lfbDisplay.bitmap.palette)
1446 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1449 void Update(Display display, Box updateBox)
1451 LFBDisplay lfbDisplay = display.driverData;
1452 if(lfbDisplay.displayCallback)
1454 if(updateBox == null)
1456 Box box { 0,0, display.width,display.height };
1457 lfbDisplay.displayCallback(display, box);
1460 lfbDisplay.displayCallback(display, updateBox);
1464 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1466 if(bitmap.pixelFormat != pixelFormatAlpha)
1468 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1470 FreeBitmap(displaySystem, bitmap);
1477 void ReleaseSurface(Display display, Surface surface)
1479 LFBSurface lfbSurface = surface.driverData;
1481 surface.driverData = null;
1484 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1486 LFBDisplay lfbDisplay = display.driverData;
1487 LFBSurface lfbSurface = surface.driverData;
1490 lfbSurface = surface.driverData = LFBSurface { };
1493 lfbSurface.bitmap = lfbDisplay.bitmap;
1495 surface.offset.x = x;
1496 surface.offset.y = y;
1498 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1500 surface.offset.x /= textCellW;
1501 surface.offset.y /= textCellH;
1502 surface.box.left /= textCellW;
1503 surface.box.top /= textCellH;
1504 surface.box.right /= textCellW;
1505 surface.box.bottom /= textCellH;
1509 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1510 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1511 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1512 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1515 surface.unclippedBox = surface.box;
1516 lfbSurface.drawingChar = 219;
1520 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1522 bool result = false;
1523 LFBSurface lfbSurface = surface.driverData;
1524 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1526 lfbSurface.bitmap = bitmap;
1528 surface.offset.x = x;
1529 surface.offset.y = y;
1531 if(bitmap.pixelFormat == pixelFormatText)
1533 surface.offset.x /= textCellW;
1534 surface.offset.y /= textCellH;
1535 surface.box.left /= textCellW;
1536 surface.box.top /= textCellH;
1537 surface.box.right /= textCellW;
1538 surface.box.bottom /= textCellH;
1541 surface.unclippedBox = *&surface.box;
1542 lfbSurface.drawingChar = 219;
1549 void Clip(Display display, Surface surface, Box clip)
1551 LFBSurface lfbSurface = surface.driverData;
1556 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1558 box.left /= textCellW;
1559 box.top /= textCellH;
1560 box.right /= textCellW;
1561 box.bottom /= textCellH;
1563 box.Clip(surface.unclippedBox);
1567 surface.box = surface.unclippedBox;
1570 void SetForeground(Display display, Surface surface, ColorAlpha color)
1572 LFBDisplay lfbDisplay = display ? display.driverData : null;
1573 LFBSurface lfbSurface = surface.driverData;
1575 //if(display) color = color & 0xFFFFFF;
1576 lfbSurface.foregroundRgb = color;
1578 if(lfbSurface.font && lfbDisplay)
1580 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1581 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1584 switch(lfbSurface.bitmap.pixelFormat)
1588 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1590 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1592 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1593 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1594 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1595 case pixelFormat888: lfbSurface.foreground = color; break;
1596 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1597 case pixelFormatText:
1599 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1601 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1606 void SetBackground(Display display, Surface surface, ColorAlpha color)
1608 LFBDisplay lfbDisplay = display ? display.driverData : null;
1609 LFBSurface lfbSurface = surface.driverData;
1610 //color = color & 0xFFFFFF;
1611 switch(lfbSurface.bitmap.pixelFormat)
1615 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1617 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1619 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1620 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1621 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1622 case pixelFormat888: lfbSurface.background = color; break;
1623 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1624 case pixelFormatText:
1626 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1628 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1633 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1635 LFBSurface lfbSurface = surface.driverData;
1636 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1641 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1643 x += surface.offset.x;
1644 y += surface.offset.y;
1645 if(lfbSurface.bitmap.picture)
1647 switch(lfbSurface.bitmap.pixelFormat)
1649 case pixelFormatText:
1651 if(!lfbSurface.bitmap.palette) return 0;
1652 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1653 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1654 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1655 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1656 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1663 void PutPixel(Display display, Surface surface,int x,int y)
1665 LFBSurface lfbSurface = surface.driverData;
1666 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1671 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1673 x += surface.offset.x;
1674 y += surface.offset.y;
1675 if(lfbSurface.bitmap.picture)
1677 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1680 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1683 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1686 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1687 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1694 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1696 LFBSurface lfbSurface = surface.driverData;
1702 uint color = lfbSurface.foreground;
1703 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1704 bool invert = false;
1705 if(!lfbSurface.bitmap.picture) return;
1706 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1712 if(surface.textOpacity)
1713 color |= lfbSurface.background;
1714 color |= lfbSurface.drawingChar;
1718 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1720 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1721 if((x1>surface.box.right)||(x2<surface.box.left))return;
1722 if(x1<surface.box.left)x1=surface.box.left;
1723 if(x2>surface.box.right)x2=surface.box.right;
1727 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1728 if(stipple != 0xFFFF)
1731 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1734 for(x=x1; x<=x2; x++, offset++)
1736 if(stipple & 0x8000)
1737 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1739 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1741 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1745 for(x=x1; x<=x2; x++, offset++)
1747 if(stipple & 0x8000)
1748 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1750 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1752 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1756 for(x=x1; x<=x2; x++, offset++)
1758 if(stipple & 0x8000)
1759 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1761 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1763 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1770 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1772 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1774 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1775 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1776 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1782 for(x = x1; x <= x2; x++, offset++)
1784 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1785 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1794 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1796 if((x1>surface.box.right)||(x1<surface.box.left))return;
1797 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1798 if(y1<surface.box.top)y1=surface.box.top;
1799 if(y2>surface.box.bottom)y2=surface.box.bottom;
1801 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1802 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1805 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1807 if(stipple & 0x8000)
1808 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1810 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1812 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1816 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1818 if(stipple & 0x8000)
1820 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1821 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1824 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1825 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1829 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1831 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1835 if(stipple != 0xFFFF)
1837 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1839 if(stipple & 0x8000)
1840 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1842 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1844 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1849 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1850 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1859 if(x1 < surface.box.left)
1861 if(x2 < surface.box.left)
1863 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1864 x1 = surface.box.left;
1866 if(x2 > surface.box.right)
1868 if(x1 > surface.box.right)
1870 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1871 x2 = surface.box.right;
1875 if(y1 < surface.box.top)
1877 if(y2 < surface.box.top)
1879 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1880 y1 = surface.box.top;
1882 if(y2 > surface.box.bottom)
1884 if(y1 > surface.box.bottom)
1886 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1887 y2 = surface.box.bottom;
1892 if(y1 > surface.box.bottom)
1894 if(y2 > surface.box.bottom)
1896 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1897 y1 = surface.box.bottom;
1899 if(y2 < surface.box.top)
1901 if(y1 < surface.box.top)
1903 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1904 y2 = surface.box.top;
1910 if(x1 > surface.box.right)
1912 if(x2 > surface.box.right)
1914 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1915 x1 = surface.box.right;
1917 if(x2 < surface.box.left)
1919 if(x1 < surface.box.left)
1921 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1922 x2 = surface.box.left;
1926 if(y1 < surface.box.top)
1928 if(y2 < surface.box.top)
1930 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1931 y1 = surface.box.top;
1933 if(y2 > surface.box.bottom)
1935 if(y1 > surface.box.bottom)
1937 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1938 y2 = surface.box.bottom;
1943 if(y1 > surface.box.bottom)
1945 if(y2 > surface.box.bottom)
1947 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1948 y1 = surface.box.bottom;
1950 if(y2 < surface.box.top)
1952 if(y1 < surface.box.top)
1954 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1955 y2 = surface.box.top;
1973 yu=-(int)lfbSurface.bitmap.stride;
1976 yu=lfbSurface.bitmap.stride;
1978 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1984 for(i=0; i<=length; i++)
1986 if(stipple & 0x8000)
1987 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1989 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1990 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1991 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
2000 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
2006 for(i=0; i<=length; i++)
2008 if(stipple & 0x8000)
2009 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2011 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
2012 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
2013 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
2027 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2029 DrawLine(display, surface,x1,y1,x2,y1);
2030 DrawLine(display, surface,x2,y1,x2,y2);
2031 DrawLine(display, surface,x2,y2,x1,y2);
2032 DrawLine(display, surface,x1,y2,x1,y1);
2035 #if !defined(__GNUC__)
2037 void memset_32_aligned(void *buf, int val, int dwords)
2042 *((uint32 *)(buf)) = val;
2043 buf = ((uint32 *)(buf))+1;
2069 if (dwords & 1) *((int*)(buf)) = val;
2075 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
2079 if(((uint32)buf) & 0x7F)
2081 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
2107 sub edx,ebx ; edx holds # of overflow bytes
2126 movdqa [edi+16],xmm0
2127 movdqa [edi+32],xmm0
2128 movdqa [edi+48],xmm0
2129 movdqa [edi+64],xmm0
2130 movdqa [edi+80],xmm0
2131 movdqa [edi+96],xmm0
2132 movdqa [edi+112],xmm0
2156 void memset_32(void *buf, uint32 val, uint32 dwords)
2159 if ((uint32)(buf) & 3)
2164 if (((uint32)(buf) & 1))
2166 *(byte *)(buf) = (byte)(val&0xFF);
2167 buf = ((byte *)(buf))+1;
2168 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
2171 if (((uint32)(buf) & 2))
2173 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
2174 buf = ((uint16 *)(buf))+1;
2175 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
2179 memset_32_aligned(buf,val,dwords);
2184 *(byte *)(buf) = (byte)(val&0xFF);
2188 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
2189 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
2196 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2198 LFBSurface lfbSurface = surface.driverData;
2199 uint32 color = lfbSurface.background;
2201 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
2203 color |= lfbSurface.foreground | lfbSurface.drawingChar;
2209 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
2211 if(x1<surface.box.left) x1=surface.box.left;
2212 if(x2>surface.box.right) x2=surface.box.right;
2213 if(y1<surface.box.top) y1=surface.box.top;
2214 if(y2>surface.box.bottom) y2=surface.box.bottom;
2216 if(x2>=x1 && y2>=y1)
2224 x1 += surface.offset.x;
2225 x2 += surface.offset.x;
2226 y1 += surface.offset.y;
2227 y2 += surface.offset.y;
2228 if(lfbSurface.bitmap.picture)
2230 if(!surface.writeColor)
2232 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2233 for(y = y1; y<= y2; y++)
2236 for(c = 0; c < w; c++, picture++)
2238 picture->a = (byte)((color & 0xFF000000) >> 24);
2239 picture += lfbSurface.bitmap.stride - w;
2244 if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
2246 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2249 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
2250 for(y = y1; y<= y2; y++)
2252 FillBytes(theOffset,(byte)color,w);
2253 theOffset += lfbSurface.bitmap.stride;
2257 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2258 for(y = y1; y<= y2; y++)
2260 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
2261 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
2265 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2266 for(y = y1; y<= y2; y++)
2268 #if defined(__GNUC__)
2269 FillBytesBy4((uint32 *) theOffset,color,w);
2271 memset_32((uint32 *) theOffset,color,w);
2273 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
2279 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
2280 //memset_32((uint32 *) theOffset,color,w);
2316 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2319 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
2320 for(y = y1; y<= y2; y++)
2322 // TODO: IMPLEMENT THIS
2323 FillBytes(theOffset,(byte)color,w);
2324 theOffset += lfbSurface.bitmap.stride;
2329 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2330 ColorAlpha c = surface.background;
2335 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
2337 for(y = y1; y <= y2; y++)
2340 for(c = 0; c < w; c++, dest++)
2342 Color destColor = 0;
2343 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2344 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2345 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2347 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2348 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2349 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2351 if(r > 255) r = 255;
2352 if(g > 255) g = 255;
2353 if(b > 255) b = 255;
2355 destColor = { (byte)r, (byte)g, (byte)b };
2357 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2358 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2359 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2362 dest += (lfbSurface.bitmap.stride - w);
2368 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2369 AlphaWriteMode alphaWrite = surface.alphaWrite;
2370 ColorAlpha c = surface.background;
2375 for(y = y1; y <= y2; y++)
2378 for(c = 0; c < w; c++, dest++)
2380 int dr = dest->color.r;
2381 int dg = dest->color.g;
2382 int db = dest->color.b;
2383 int r = a * cr / 255 + ((255 - a) * dr / 255);
2384 int g = a * cg / 255 + ((255 - a) * dg / 255);
2385 int b = a * cb / 255 + ((255 - a) * db / 255);
2387 if(r > 255) r = 255;
2388 if(g > 255) g = 255;
2389 if(b > 255) b = 255;
2390 dest->color = { (byte)r, (byte)g, (byte)b };
2392 if(alphaWrite == blend)
2394 int ca = (int)(a + ((255 - a) * dest->a / 255));
2395 if(ca > 255) ca = 255;
2401 dest += (lfbSurface.bitmap.stride - w);
2410 void Clear(Display display, Surface surface, ClearType type)
2412 LFBSurface lfbSurface = surface.driverData;
2414 lfbSurface.clearing = true;
2415 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2416 surface.box.left == 0 && surface.box.top == 0 &&
2417 surface.box.right == surface.width-1 &&
2418 surface.box.bottom == surface.height-1)
2420 uint32 color = /*0xFF000000 | */lfbSurface.background;
2421 if(type != depthBuffer)
2423 if(lfbSurface.bitmap.stride != surface.width)
2424 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2427 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2430 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2432 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2433 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2438 if((flags & CLEAR_Z) && zbuffer)
2439 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2444 if(type != depthBuffer)
2445 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2447 if((flags & CLEAR_Z))
2450 uint32 w = surface.box.right-surface.box.left+1;
2451 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2452 + surface.box.left+surface.offset.x;
2453 for(y = surface.box.top; y<= surface.box.bottom; y++)
2455 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2456 offset += DISPLAY.Width;
2461 lfbSurface.clearing = false;
2464 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2466 LFBSurface lfbSurface = surface.driverData;
2469 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2471 if(w < 0) { w = -w; flip = true; }
2473 //Clip against the edges of the source
2486 if(sx+w>src.width-1)
2487 w-=sx+w-(src.width-1)-1;
2488 if(sy+h>src.height-1)
2489 h-=sy+h-(src.height-1)-1;
2490 //Clip against the edges of the destination
2491 if(dx<surface.box.left)
2493 if(!flip) sx+=surface.box.left-dx;
2494 w-=surface.box.left-dx;
2495 dx=surface.box.left;
2497 if(dy<surface.box.top)
2499 sy+=surface.box.top-dy;
2500 h-=surface.box.top-dy;
2503 if((dx+w)>surface.box.right)
2505 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2506 w-=((uint32)(dx+w)-surface.box.right-1);
2508 if((dy+h)>surface.box.bottom)
2509 h-=((dy+h)-surface.box.bottom-1);
2513 dx += surface.offset.x;
2514 dy += surface.offset.y;
2516 if(lfbSurface.bitmap.picture)
2518 AlphaWriteMode alphaWrite = surface.alphaWrite;
2519 if(src.alphaBlend && surface.blend)
2522 if(src.pixelFormat == pixelFormatAlpha)
2524 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2526 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2527 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2528 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2529 for(y = 0; y < h; y++)
2531 for(x = 0; x < w; x++, picture++, source++)
2533 int a = *source * color.a;
2534 ColorAlpha dest = *picture;
2535 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2536 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2537 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2538 if(r > 255) r = 255;
2539 if(g > 255) g = 255;
2540 if(b > 255) b = 255;
2541 picture->color = { (byte)r, (byte)g, (byte)b };
2542 if(alphaWrite == blend)
2544 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2545 if(ca > 255) ca = 255;
2546 picture->a = (byte)ca;
2549 picture->a = (byte)(a / 255);
2551 picture += lfbSurface.bitmap.stride - w;
2552 source += src.stride - w;
2555 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2557 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2558 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2559 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2560 for(y = 0; y < h; y++)
2562 for(x = 0; x < w; x++, picture++, source++)
2564 int a = *source * color.a;
2565 Color dest = *picture;
2566 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2567 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2568 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2569 if(r > 255) r = 255;
2570 if(g > 255) g = 255;
2571 if(b > 255) b = 255;
2572 *picture = Color { (byte)r, (byte)g, (byte)b };
2574 picture += lfbSurface.bitmap.stride - w;
2575 source += src.stride - w;
2578 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2580 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2581 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2582 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2583 for(y = 0; y < h; y++)
2585 for(x = 0; x < w; x++, picture++, source++)
2587 int a = *source * color.a;
2588 Color dest = *picture;
2589 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2590 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2591 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2592 if(r > 255) r = 255;
2593 if(g > 255) g = 255;
2594 if(b > 255) b = 255;
2595 *picture = Color { (byte)r, (byte)g, (byte)b };
2597 picture += lfbSurface.bitmap.stride - w;
2598 source += src.stride - w;
2604 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2605 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2607 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2608 for(y = 0; y < h; y++)
2610 for(x = 0; x < w; x++, picture++, source++)
2612 ColorAlpha src = *source;
2613 ColorAlpha dest = *picture;
2614 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2615 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2616 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2617 if(r > 255) r = 255;
2618 if(g > 255) g = 255;
2619 if(b > 255) b = 255;
2620 picture->color = { (byte)r, (byte)g, (byte)b };
2621 if(alphaWrite == blend)
2623 int a = src.a + ((255 - src.a) * dest.a / 255);
2624 if(a > 255) a = 255;
2625 picture->a = (byte)a;
2630 picture += lfbSurface.bitmap.stride - w;
2631 source += src.stride - w;
2634 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2636 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2637 for(y = 0; y < h; y++)
2639 for(x = 0; x < w; x++, picture++, source++)
2641 ColorAlpha src = *source;
2642 Color565 dest = *picture;
2643 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2644 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2645 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2646 if(r > 255 * 31) r = 255 * 31;
2647 if(g > 255 * 63) g = 255 * 63;
2648 if(b > 255 * 31) b = 255 * 31;
2649 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2651 picture += lfbSurface.bitmap.stride - w;
2652 source += src.stride - w;
2655 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2657 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2658 for(y = 0; y < h; y++)
2660 for(x = 0; x < w; x++, picture++, source++)
2662 ColorAlpha psrc = *source;
2663 Color555 dest = *picture;
2664 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2665 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2666 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2667 if(r > 255 * 31) r = 255 * 31;
2668 if(g > 255 * 31) g = 255 * 31;
2669 if(b > 255 * 31) b = 255 * 31;
2670 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2672 picture += lfbSurface.bitmap.stride - w;
2673 source += src.stride - w;
2678 else if(src.paletteShades)
2679 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2680 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2681 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2682 else if(src.pixelFormat == pixelFormat8)
2683 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2687 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2689 bool result = false;
2690 LFBDisplay lfbDisplay = display.driverData;
2692 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2695 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2696 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2700 Surface surface = bitmap.GetSurface(0,0,null);
2703 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2704 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2705 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2713 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2715 LFBSurface lfbSurface = surface.driverData;
2718 float s2dw,s2dh,d2sw,d2sh;
2720 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2722 if(Sgn(w) != Sgn(sw))
2734 //Clip against the edges of the source
2737 dx+=(int)((0-sx) * s2dw);
2738 w-=(int)((0-sx) * s2dw);
2744 dy+=(int)((0-sy) * s2dh);
2745 h-=(int)((0-sy) * s2dh);
2750 if(sx+sw>src.width-1)
2752 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2753 sw-=sx+sw-(src.width-1)-1;
2755 if(sy+sh>(src.height-1))
2757 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2758 sh-=sy+sh-(src.height-1)-1;
2760 //Clip against the edges of the destination
2761 if(dx<surface.box.left)
2763 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2764 sw-=(int)((surface.box.left-dx)*d2sw);
2765 w-=surface.box.left-dx;
2766 dx=surface.box.left;
2768 if(dy<surface.box.top)
2770 sy+=(int)((surface.box.top-dy)*d2sh);
2771 sh-=(int)((surface.box.top-dy)*d2sh);
2772 h-=surface.box.top-dy;
2775 if((dx+w)>surface.box.right)
2777 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2778 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2779 w-=((dx+w)-surface.box.right-1);
2781 if((dy+h)>surface.box.bottom)
2783 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2784 h-=((dy+h)-surface.box.bottom-1);
2786 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2788 dx+=surface.offset.x;
2789 dy+=surface.offset.y;
2791 if(lfbSurface.bitmap.picture)
2793 AlphaWriteMode alphaWrite = surface.alphaWrite;
2794 if(src.alphaBlend && surface.blend)
2798 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2799 ColorAlpha * backsrc;
2800 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2801 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2802 if(flip) source += sw-1;
2820 ColorAlpha src = *source;
2821 ColorAlpha dst = *dest;
2822 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2823 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2824 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2825 if(r > 255) r = 255;
2826 if(g > 255) g = 255;
2827 if(b > 255) b = 255;
2828 dest->color = { (byte)r, (byte)g, (byte)b };
2829 if(alphaWrite == blend)
2831 int a = src.a + ((255 - src.a) * dst.a / 255);
2832 if(a > 255) a = 255;
2845 source += addsource;
2848 else if(src.paletteShades)
2849 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2850 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2851 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2852 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2853 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2857 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2859 LFBSurface lfbSurface = surface.driverData;
2862 float s2dw,s2dh,d2sw,d2sh;
2864 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2866 if(Sgn(w) != Sgn(sw))
2878 //Clip against the edges of the source
2881 dx+=(int)((0-sx) * s2dw);
2882 w-=(int)((0-sx) * s2dw);
2888 dy+=(int)((0-sy) * s2dh);
2889 h-=(int)((0-sy) * s2dh);
2894 if(sx+sw>src.width-1)
2896 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2897 sw-=sx+sw-(src.width-1)-1;
2899 if(sy+sh>(src.height-1))
2901 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2902 sh-=sy+sh-(src.height-1)-1;
2904 //Clip against the edges of the destination
2905 if(dx<surface.box.left)
2907 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2908 sw-=(int)((surface.box.left-dx)*d2sw);
2909 w-=surface.box.left-dx;
2910 dx=surface.box.left;
2912 if(dy<surface.box.top)
2914 sy+=(int)((surface.box.top-dy)*d2sh);
2915 sh-=(int)((surface.box.top-dy)*d2sh);
2916 h-=surface.box.top-dy;
2919 if((dx+w)>surface.box.right)
2921 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2922 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2923 w-=((dx+w)-surface.box.right-1);
2925 if((dy+h)>surface.box.bottom)
2927 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2928 h-=((dy+h)-surface.box.bottom-1);
2930 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2932 dx+=surface.offset.x;
2933 dy+=surface.offset.y;
2935 if(lfbSurface.bitmap.picture)
2937 AlphaWriteMode alphaWrite = surface.alphaWrite;
2938 if(src.alphaBlend && surface.blend)
2940 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2941 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2942 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2943 float scaleX = (float)sw / w;
2944 float scaleY = (float)sh / h;
2952 if (w > sw && h > sh)
2955 for (y = 0; y < h; y++)
2957 int y0 = y * sh / h;
2958 int y1 = Min(y0 + 1, sh - 1);
2959 float alpha = y * scaleY - y0;
2961 for(x = 0; x < w; x++, dest += 1)
2963 int x0 = x * sw / w;
2964 int x1 = Min(x0 + 1, sw - 1);
2965 float beta = x * scaleX - x0;
2966 ColorAlpha src00, src01, src10, src11;
2967 float a1,r1,g1,b1,a2,r2,g2,b2;
2969 src00 = source[y0 * src.stride + x0];
2970 src01 = source[y0 * src.stride + x1];
2971 src10 = source[y1 * src.stride + x0];
2972 src11 = source[y1 * src.stride + x1];
2973 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2974 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2975 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2976 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2977 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2978 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2979 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2980 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2981 a = a1 * (1.0f - alpha) + a2 * alpha;
2982 r = r1 * (1.0f - alpha) + r2 * alpha;
2983 g = g1 * (1.0f - alpha) + g2 * alpha;
2984 b = b1 * (1.0f - alpha) + b2 * alpha;
2986 ColorAlpha dst = *dest;
2987 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2988 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2989 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2990 if(cr > 255) cr = 255;
2991 if(cg > 255) cg = 255;
2992 if(cb > 255) cb = 255;
2993 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2995 if(alphaWrite == blend)
2997 int ca = (int)(a + ((255 - a) * dst.a / 255));
2998 if(ca > 255) ca = 255;
3011 for (y = 0; y < h; y++)
3013 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
3014 int y1 = Min(y0 + 1, sh - 1);
3016 for (x = 0; x < w; x++, dest += 1)
3018 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
3019 int x1 = Min(x0 + 1, sw - 1);
3020 float a = 0, r = 0, g = 0, b = 0;
3023 for (i = y0; i <= y1; i++)
3024 for (j = x0; j <= x1; j++)
3026 ColorAlpha pixel = source[i * src.stride + j];
3038 ColorAlpha dst = *dest;
3039 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
3040 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
3041 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
3042 if(cr > 255) cr = 255;
3043 if(cg > 255) cg = 255;
3044 if(cb > 255) cb = 255;
3045 dest->color = { (byte)cr, (byte)cg, (byte)cb };
3046 if(alphaWrite == blend)
3048 int ca = (int)(a + ((255 - a) * dst.a / 255));
3049 if(ca > 255) ca = 255;
3060 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
3061 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
3062 // Fail back on Stretch
3063 else if(src.paletteShades)
3064 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
3065 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
3066 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
3067 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
3068 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
3072 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
3074 Blit(display, surface, src, dx, dy, sx, sy, w, h);
3077 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3079 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
3082 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3084 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
3087 void UnloadFont(DisplaySystem displaySystem, Font font)
3091 #if !defined(ECERE_NOTRUETYPE)
3093 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
3095 FontEntry fontEntry = font.fontEntries[entry];
3101 loadedFonts.Remove(fontEntry);
3111 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
3113 void * result = null;
3115 #if !defined(ECERE_NOTRUETYPE)
3116 Font font = Font { };
3119 char fileName[MAX_LOCATION];
3120 bool fakeItalic = flags.italic;
3122 #if !defined(__WIN32__)
3125 const char * ecereFonts = getenv("ECERE_FONTS");
3126 if(!ecereFonts) ecereFonts = "<:ecere>";
3127 #if !defined(__WIN32__)
3129 char linkCfgPath[MAX_LOCATION];
3131 strcpy(linkCfgPath, ecereFonts);
3132 PathCat(linkCfgPath, "linking.cfg");
3133 linkCfg = FileOpen(linkCfgPath, read);
3136 strcpy(fileName, faceName);
3137 strcpy(font.faceName, faceName);
3139 font.displaySystem = displaySystem;
3141 if(!FileExists(fileName))
3143 strcpy(fileName, ecereFonts);
3144 PathCat(fileName, faceName);
3145 if(flags.bold && flags.italic) strcat(fileName, "bi");
3146 else if(flags.bold) strcat(fileName, "bd");
3147 else if(flags.italic) strcat(fileName, "i");
3148 strcat(fileName, ".ttf");
3152 if(flags.italic && !FileExists(fileName))
3154 strcpy(fileName, ecereFonts);
3155 PathCat(fileName, faceName);
3156 if(flags.bold) strcat(fileName, "bd");
3157 strcat(fileName, ".ttf");
3162 // Search in current working directory
3163 if(!FileExists(fileName))
3165 strcpy(fileName, faceName);
3166 if(flags.bold && flags.italic) strcat(fileName, "bi");
3167 else if(flags.bold) strcat(fileName, "bd");
3168 else if(flags.italic) strcat(fileName, "i");
3169 strcat(fileName, ".ttf");
3173 if(flags.italic && !FileExists(fileName))
3175 strcpy(fileName, faceName);
3176 if(flags.bold) strcat(fileName, "bd");
3177 strcat(fileName, ".ttf");
3183 #if defined(__WIN32__)
3184 if(!FileExists(fileName))
3186 FontData fontData = { { 0 } };
3187 LOGFONT logFont = { 0 };
3192 logFont.lfCharSet = DEFAULT_CHARSET;
3193 strcpy(logFont.lfFaceName, faceName);
3194 fontData.flags = flags;
3196 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3197 if(!fontData.fileName[0] && flags.bold)
3199 fontData.forgive = true;
3200 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3202 if(!fontData.fileName[0])
3205 fontData.flags.italic = false;
3206 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3210 if(fontData.fileName[0])
3212 GetWindowsDirectory(fileName, MAX_LOCATION);
3213 PathCat(fileName, "fonts");
3214 PathCat(fileName, fontData.fileName);
3218 #elif !defined(ECERE_NOFONTCONFIG)
3221 FcResult result = 0;
3222 FcPattern * pattern;
3223 FcPattern * matched;
3225 unichar testChar = 0;
3226 FcCharSet * charSet;
3228 fcConfig = FcInitLoadConfigAndFonts();
3230 charSet = FcCharSetCreate();
3232 if(!strcmpi(faceName, "Mangal"))
3238 FcCharSetAddChar(charSet, testChar);
3240 pattern = FcPatternBuild(null,
3241 //FC_SOURCE, FcTypeString, "freetype",
3242 FC_FAMILY, FcTypeString, faceName,
3243 //FC_SCALABLE, FcTypeBool, 1,
3244 FC_SIZE, FcTypeDouble, (double)size,
3245 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3246 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3247 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
3249 FcDefaultSubstitute(pattern);
3250 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3252 matched = FcFontMatch (0, pattern, &result);
3253 // printf("Locating %s\n", faceName);
3256 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3257 //printf("Fontconfig returned %s\n", family);
3259 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
3262 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3263 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3264 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3265 strcpy(fileName, fileName2);
3266 // size = (float)fontSize;
3268 //printf("Matched to %s, %f\n", fileName, size);
3272 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
3274 if(pattern) FcPatternDestroy(pattern);
3275 if(matched) FcPatternDestroy(matched);
3276 if(charSet) FcCharSetDestroy(charSet);
3281 if(!FileExists(fileName))
3282 ChangeExtension(fileName, "otf", fileName);
3283 if(!FileExists(fileName))
3284 ChangeExtension(fileName, "ttc", fileName);
3286 //if(FileExists(fileName))
3289 char links[1024] = "";
3291 #if defined(__WIN32__)
3294 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
3295 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
3300 RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
3301 memset(links + size, 0, 1024 - size);
3309 while(linkCfg.GetLine(line, sizeof(line)))
3311 int len = strlen(faceName);
3312 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
3314 while(linkCfg.GetLine(line, sizeof(line)))
3316 TrimLSpaces(line, line);
3317 if(!line[0] || line[0] == '[')
3320 memcpy(links + linksPos, line, len);
3322 links[linksPos] = 0;
3330 while(entry < MAX_FONT_LINK_ENTRIES)
3332 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3335 File file = FileOpen/*Buffered*/(fileName, read);
3338 FileSize fileSize = file.GetSize();
3339 FT_Open_Args args = { 0 };
3340 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3341 FT_Stream stream = new0 FT_StreamRec[1];
3344 FT_Init_FreeType( &ftLibrary );
3346 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3347 fontEntry.stream = stream;
3350 fontEntry.buffer = new byte[fileSize];
3351 file.Read(fontEntry.buffer, 1, fileSize);
3354 //args.num_params = 1;
3355 args.params = ¶m;
3357 stream->size = fileSize;
3358 stream->descriptor.pointer = file;
3359 stream->read = FT_stream_load;
3360 stream->close = FT_stream_close;
3362 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3363 args.stream = stream;
3364 //args.pathname = fileName;
3365 //args.memory_base = fontEntry.buffer;
3366 //args.memory_size = fileSize;
3368 // printf("Opening: %s\n", fileName);
3369 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3374 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3375 fontEntry.hbFont.klass = &hb_fontClass;
3376 fontEntry.hbFont.userData = fontEntry; //.face;
3379 loadedFonts.Add(fontEntry);
3384 // printf("Error opening font %s\n", fileName);
3393 FT_Vector pen = { 0, 0 };
3396 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3397 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3398 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3399 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3403 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3404 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3405 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3406 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3408 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3409 FaceSetCharSize(fontEntry.face, size);
3410 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3411 // printf("Font height is %d\n", font.height);
3412 font.fakeItalic = fakeItalic;
3416 font.fontEntries[entry++] = fontEntry;
3423 char fontName[1024];
3424 if(!links[linksPos]) break;
3425 for(c = 0; (ch = links[linksPos + c]); c++)
3428 if(ch == ',') break;
3431 if(fontName[0] || ch == ',')
3433 #if defined(__WIN32__)
3434 GetWindowsDirectory(fileName, MAX_LOCATION);
3435 PathCat(fileName, "fonts");
3436 PathCat(fileName, fontName);
3437 #elif !defined(ECERE_NOFONTCONFIG)
3438 if(getenv("ECERE_FONTS"))
3440 strcpy(fileName, ecereFonts);
3441 PathCat(fileName, fontName);
3447 FcResult result = 0;
3448 FcPattern * pattern;
3449 FcPattern * matched;
3451 pattern = FcPatternBuild(null,
3452 //FC_SOURCE, FcTypeString, "freetype",
3453 //FC_SCALABLE, FcTypeBool, 1,
3454 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3455 FC_SIZE, FcTypeDouble, (double)size,
3456 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3457 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3459 FcDefaultSubstitute(pattern);
3460 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3462 //printf("Locating %s\n", links + linksPos + c + 1);
3463 matched = FcFontMatch (0, pattern, &result);
3466 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3467 // printf("Fontconfig returned %s\n", family);
3469 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3470 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3473 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3474 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3475 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3476 strcpy(fileName, fileName2);
3477 //size = (float)fontSize;
3478 // printf("Matched to %s, %f\n", fileName, size);
3482 // printf("Could not find a match for %s, %f, %s %s (%d)\n", links + linksPos + c + 1, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
3484 if(pattern) FcPatternDestroy(pattern);
3485 if(matched) FcPatternDestroy(matched);
3492 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3499 UnloadFont(displaySystem, font);
3502 font.asciiPack.Render(font, 0, displaySystem);
3504 #if !defined(__WIN32__)
3512 #if !defined(ECERE_NOTRUETYPE)
3513 void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3514 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3515 Surface surface, Display display, int * x, int y)
3517 if(font && font.fontEntries && font.fontEntries[0])
3519 LFBSurface lfbSurface = surface ? surface.driverData : null;
3520 int previousGlyph = 0;
3521 FT_Face previousFace = 0;
3522 int c, nb, glyphIndex = 0;
3523 unichar lastPack = lfbSurface && lfbSurface.writingOutline ? -1 : 0;
3524 GlyphPack pack = font.asciiPack, outline = null;
3526 uint * glyphs = null;
3528 bool rightToLeft = false;
3529 int fontEntryNum = 0;
3530 int glyphScript = 0;
3531 FontEntry curFontEntry;
3533 pack.bitmap.alphaBlend = true;
3535 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3539 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3541 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3542 rightToLeft ? glyphIndex-- : glyphIndex++;
3546 HB_Script curScript = HB_Script_Common;
3547 const byte * scriptStart = text + c;
3548 //unichar nonASCIIch = 0;
3551 unichar testChar = 0;
3552 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3553 const char * testLang = null;
3558 HB_Script script = HB_Script_Common;
3559 ch = UTF8GetChar((const char *)text + c, &nb);
3560 //if(ch > 127) nonASCIIch = ch;
3562 if(ch == 32 && curScript)
3569 for(a = c + 1; a < c + len; a++)
3577 unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3578 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3586 script = HB_Script_Common;
3587 else if(ch <= 0x11FF)
3591 case 0x300: script = HB_Script_Greek; break;
3592 case 0x400: script = HB_Script_Cyrillic; break;
3593 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3594 case 0x600: script = HB_Script_Arabic; break;
3595 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3596 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3597 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3598 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3599 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3600 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3601 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3602 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3603 case 0xF00: script = HB_Script_Tibetan; break;
3604 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3605 case 0x1100: script = HB_Script_Hangul; break;
3608 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3609 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3610 script = HB_Script_Hangul;
3611 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3612 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3613 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3614 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3615 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3616 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3617 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3618 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3619 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3622 if(!script || (script != curScript))
3630 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3631 if(!script) { c += nb; break; }
3638 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3640 rightToLeft = false;
3642 theCurrentScript = 0;
3646 int len = c - (int)(scriptStart - text);
3647 int max = len * 2 + 1;
3648 if(max > utf16BufferSize)
3650 utf16 = renew utf16 uint16[max];
3651 utf16BufferSize = max;
3653 wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3654 theCurrentScript = glyphScript = curScript;
3658 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3659 //printf("Arabic ");
3661 case HB_Script_Devanagari: testChar = 0x905;
3662 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3665 //printf("Devanagari ");
3667 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3668 //printf("Hebrew ");
3671 testChar = (ch == '\t') ? ' ' : ch;
3673 case 60: testChar = 'あ'; break;
3674 case 61: testChar = 0x3400; break; //'愛'; break;
3680 // printf("Testing for char %x\n", testChar);
3681 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3683 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3685 /*if(font.fontEntries[fontEntryNum])
3686 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3690 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3692 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3694 double fontSize = font.size;
3695 FcResult result = 0;
3696 FcPattern * pattern;
3697 FcPattern * matched;
3698 FcCharSet * charSet;
3700 FontEntry fontEntry;
3701 char * fileName = null;
3702 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3703 if(!font.fontEntries[fontEntryNum])
3705 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3709 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3711 charSet = FcCharSetCreate();
3712 FcCharSetAddChar(charSet, testChar);
3713 //printf("Loading with char %x\n", testChar);
3715 pattern = FcPatternBuild(null,
3716 //FC_SOURCE, FcTypeString, "freetype",
3717 //FC_SCALABLE, FcTypeBool, 1,
3718 FC_FAMILY, FcTypeString, font.faceName,
3719 FC_SIZE, FcTypeDouble, (double)font.size,
3720 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3721 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3722 FC_CHARSET,FcTypeCharSet, charSet,
3723 testLang ? FC_LANG : 0, FcTypeString,testLang,
3725 FcDefaultSubstitute(pattern);
3726 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3728 //printf("Locating %s for script %d\n", font.faceName, curScript);
3729 matched = FcFontMatch (0, pattern, &result);
3732 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3733 //printf("Fontconfig returned %s\n", family);
3735 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
3737 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName);
3738 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3739 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3740 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3744 //printf("Could not find a match for %s, %f, %s %s (%d)\n", font.faceName, font.size, font.flags.bold ? "bold" : "", font.flags.italic ? "italic" : "", (int)result);
3749 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3752 File file = FileOpen(fileName, read);
3755 FileSize fileSize = file.GetSize();
3756 FT_Open_Args args = { 0 };
3757 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3758 FT_Stream stream = new0 FT_StreamRec[1];
3761 FT_Init_FreeType( &ftLibrary );
3763 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3764 fontEntry.stream = stream;
3766 //args.num_params = 1;
3767 args.params = ¶m;
3769 stream->size = fileSize;
3770 stream->descriptor.pointer = file;
3771 stream->read = FT_stream_load;
3772 stream->close = FT_stream_close;
3774 args.flags = FT_OPEN_STREAM;
3775 args.stream = stream;
3776 //args.pathname = fileName;
3777 //args.memory_base = fontEntry.buffer;
3778 //args.memory_size = fileSize;
3780 // printf("Opening: %s\n", fileName);
3781 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3786 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3787 fontEntry.hbFont.klass = &hb_fontClass;
3788 fontEntry.hbFont.userData = fontEntry; //.face;
3791 loadedFonts.Add(fontEntry);
3796 // printf("Error opening font %s\n", fileName);
3802 FaceSetCharSize(fontEntry.face, font.size);
3804 font.fontEntries[fontEntryNum] = fontEntry;
3808 if(pattern) FcPatternDestroy(pattern);
3809 if(matched) FcPatternDestroy(matched);
3810 if(charSet) FcCharSetDestroy(charSet);
3813 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3814 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3816 font.fontEntries[fontEntryNum].font = font;
3817 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3821 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3822 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3823 rightToLeft ? glyphIndex-- : glyphIndex++;
3827 curFontEntry = font.fontEntries[fontEntryNum];
3829 packNo = glyphNo & 0xFFFFFF80;
3831 if(packNo != lastPack)
3834 pack = font.asciiPack;
3837 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3840 pack = GlyphPack { key = (uintptr)packNo };
3841 font.glyphPacks.Add(pack);
3842 pack.Render(font, fontEntryNum, displaySystem);
3845 pack.bitmap.alphaBlend = true;
3847 #if !defined(ECERE_VANILLA)
3848 if(lfbSurface && lfbSurface.writingOutline)
3850 uint outlineNo = (((uint)surface.outline.size) << 16) | (uint16)(Min(surface.outline.fade, 257.0f) * 255);
3851 outline = (GlyphPack)pack.outlines.Find(outlineNo);
3854 outline = { key = outlineNo };
3855 pack.outlines.Add(outline);
3856 pack.RenderOutline(outline, font, displaySystem);
3863 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3864 GlyphInfo * glyph = &(outline ? outline : pack).glyphs[glyphNo & 0x7F];
3866 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3867 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3868 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3872 if(previousGlyph && curFontEntry.face == previousFace)
3874 FT_Vector delta = { 0, 0 };
3875 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3876 if(delta.x < 0) delta.x += (-delta.x) % 64;
3877 else if(delta.x) delta.x += 64 - (delta.x % 64);
3878 *x += delta.x * glyph->scale;
3881 FaceSetCharSize(curFontEntry.face, font.size);
3883 previousGlyph = glyph->glyphNo;
3884 previousFace = curFontEntry.face;
3887 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, (outline ? outline : pack).bitmap);
3890 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3896 LFBSurface lfbSurface = surface.driverData;
3897 lfbSurface.xOffset = 0;
3902 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3904 if(displaySystem && displaySystem.flags.text && len)
3909 *width = num * textCellW;
3911 if(height) *height = textCellH;
3913 else if(font && len)
3918 #if !defined(ECERE_NOTRUETYPE)
3919 ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3921 //*width = (w + 64 - w % 64) >> 6;
3925 *height = font.height;
3929 if(width) *width = 0;
3930 if(height) *height = 0;
3934 #if !defined(ECERE_NOTRUETYPE)
3935 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3937 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3941 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3943 LFBSurface lfbSurface = surface.driverData;
3944 if(display && display.displaySystem.flags.text)
3946 LFBDisplay lfbDisplay = display.driverData;
3947 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3953 if(y > surface.box.bottom || y < surface.box.top)
3955 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3956 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3957 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3959 if(surface.textOpacity)
3960 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3962 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3967 lfbSurface.writingText = true;
3968 #if !defined(ECERE_NOTRUETYPE)
3970 ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3972 lfbSurface.writingText = false;
3976 void TextFont(Display display, Surface surface, Font font)
3978 LFBSurface lfbSurface = surface.driverData;
3979 lfbSurface.font = font;
3982 void TextOpacity(Display display, Surface surface, bool opaque)
3987 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3989 LFBSurface lfbSurface = surface.driverData;
3990 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3993 void DrawingChar(Display display, Surface surface, byte character)
3995 LFBSurface lfbSurface = surface.driverData;
3996 lfbSurface.drawingChar = character;
3999 void LineStipple(Display display, Surface surface, uint32 stipple)
4001 LFBSurface lfbSurface = surface.driverData;
4002 lfbSurface.stipple = (uint16)stipple;
4005 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
4006 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
4008 if(mesh.vertices && !mesh.flags.vertices)
4009 delete mesh.vertices;
4010 if(mesh.normals && !mesh.flags.normals)
4011 delete mesh.normals;
4012 if(mesh.texCoords && !mesh.flags.texCoords1)
4013 delete mesh.texCoords;
4016 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
4018 bool result = false;
4019 if(mesh.nVertices == nVertices)
4022 // Same number of vertices, adding features (Leaves the other features pointers alone)
4023 if(mesh.flags != flags)
4025 if(!mesh.flags.vertices && flags.vertices)
4027 if(flags.doubleVertices)
4029 mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
4032 mesh.vertices = new Vector3Df[nVertices];
4034 if(!mesh.flags.normals && flags.normals)
4036 if(flags.doubleNormals)
4038 mesh.normals = (Vector3Df *)new Vector3D[nVertices];
4041 mesh.normals = new Vector3Df[nVertices];
4043 if(!mesh.flags.texCoords1 && flags.texCoords1)
4044 mesh.texCoords = new Pointf[nVertices];
4045 if(!mesh.flags.colors && flags.colors)
4046 mesh.colors = new ColorRGBAf[nVertices];
4052 // New number of vertices, reallocate all current and new features
4053 flags |= mesh.flags;
4056 if(flags.doubleVertices)
4058 mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
4061 mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
4065 if(flags.doubleNormals)
4067 mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
4070 mesh.normals = renew mesh.normals Vector3Df[nVertices];
4072 if(flags.texCoords1)
4073 mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
4075 mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
4080 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
4085 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
4090 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
4092 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
4094 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)