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*4 - 1;
74 float inv_rw = 1/(rb-ra);
76 for(i = 0; i < numPixels; i++)
77 data[i] = src[i] / 255.0f;
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++)
151 #define MAX_FONT_LINK_ENTRIES 10
153 static HB_Script theCurrentScript;
155 static unichar UTF16GetChar(const uint16 *string, int * nw)
158 if(HB_IsHighSurrogate(string[0]) && HB_IsLowSurrogate(string[1]))
160 ch = HB_SurrogateToUcs4(string[0], string[1]);
171 static HB_Bool hb_stringToGlyphs(HB_Font font, const uint16 * string, uint length, HB_Glyph *glyphs, uint *numGlyphs, HB_Bool rightToLeft)
173 FT_Face face = ((FontEntry)font->userData).face;
177 if (length > *numGlyphs)
180 for (c = 0; c < length; c += nw)
182 unichar ch = UTF16GetChar(string + c, &nw);
183 glyphs[glyph_pos++] = FT_Get_Char_Index(face, ch);
185 *numGlyphs = glyph_pos;
189 static void hb_getAdvances(HB_Font font, const HB_Glyph * glyphs, uint numGlyphs, HB_Fixed *advances, int flags)
191 FontEntry entry = font->userData;
192 Font glFont = entry.font;
195 GlyphPack pack = glFont.asciiPack;
197 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
199 if(glFont.fontEntries[fontEntryNum] == entry)
203 for(c = 0; c < numGlyphs; c++)
206 uint glyphNo = glyphs[c] | 0x80000000 | (theCurrentScript << 24);
207 uint packNo = glyphNo & 0xFFFFFF80;
208 if(packNo != lastPack)
210 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
213 glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
214 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
215 pack.bitmap.alphaBlend = true;
219 glyph = &pack.glyphs[glyphNo & 0x7F];
220 advances[c] = glyph->ax;
224 static HB_Bool hb_canRender(HB_Font font, const uint16 * string, uint length)
226 FT_Face face = ((FontEntry)font->userData).face;
229 for (c = 0; c < length; c += nw)
231 unichar ch = UTF16GetChar(string + c, &nw);
232 if(!FT_Get_Char_Index(face, ch))
238 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
240 FT_Face face = (FT_Face)font;
241 FT_ULong ftlen = *length;
244 if (!FT_IS_SFNT(face))
245 return HB_Err_Invalid_Argument;
247 error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
248 *length = (uint)ftlen;
249 return (HB_Error)error;
252 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)
254 HB_Error error = HB_Err_Ok;
255 FT_Face face = (FT_Face)font->userData;
257 int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
259 if ((error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags)))
262 if (face->glyph->format != ft_glyph_format_outline)
263 return (HB_Error)HB_Err_Invalid_SubTable;
265 *nPoints = face->glyph->outline.n_points;
269 if (point > *nPoints)
270 return (HB_Error)HB_Err_Invalid_SubTable;
272 *xpos = (int)face->glyph->outline.points[point].x;
273 *ypos = (int)face->glyph->outline.points[point].y;
278 static void hb_getGlyphMetrics(HB_Font font, HB_Glyph theGlyph, HB_GlyphMetrics *metrics)
280 FontEntry entry = font->userData;
281 Font glFont = entry.font;
283 GlyphPack pack = glFont.asciiPack;
285 for(fontEntryNum = 0; fontEntryNum < MAX_FONT_LINK_ENTRIES; fontEntryNum++)
287 if(glFont.fontEntries[fontEntryNum] == entry)
292 uint glyphNo = theGlyph | 0x80000000 | (theCurrentScript << 24);
293 uint packNo = glyphNo & 0xFFFFFF80;
294 if(packNo != lastPack)
296 pack = (GlyphPack)glFont.glyphPacks.Find((uintptr)packNo);
299 pack = { key = (uintptr)packNo };
300 glFont.glyphPacks.Add(pack);
301 pack.Render(glFont, fontEntryNum, glFont.displaySystem);
302 pack.bitmap.alphaBlend = true;
306 glyph = &pack.glyphs[glyphNo & 0x7F];
308 metrics->x = glyph->ax;
310 metrics->width = glyph->w;
311 metrics->height = glyph->h;
312 metrics->xOffset = glyph->bx;
313 metrics->yOffset = glyph->by;
317 static HB_Fixed hb_getFontMetric(HB_Font font, HB_FontMetric metric)
319 FontEntry entry = font->userData;
320 FT_Face face = entry.face;
322 // Note that we aren't scanning the VDMX table which we probably would in
324 if(metric == HB_FontAscent)
325 return face->ascender;
329 static HB_FontClass hb_fontClass =
331 hb_stringToGlyphs, hb_getAdvances, hb_canRender,
332 hb_getPointInOutline, hb_getGlyphMetrics, hb_getFontMetric
335 static uint FT_stream_load(FT_Stream stream, long offset, byte * buffer, long count)
337 File f = stream->descriptor.pointer;
338 f.Seek((int)offset, start);
339 return count ? f.Read(buffer, 1, (uint)count) : 0;
342 static void FT_stream_close(FT_Stream stream)
344 File f = stream->descriptor.pointer;
349 static FT_Library ftLibrary;
352 static BinaryTree loadedFonts
354 CompareKey = (void *)BinaryTree::CompareString
357 class FontEntry : BTNode
366 //If we don't save the FT_Stream before sacrificing it to FreeType, the garbage collector (if one is used) will destroy it prematurely
383 FT_Done_FreeType(ftLibrary);
390 static float FaceSetCharSize(FT_Face face, float size)
393 if(FT_Set_Char_Size(face, (int)(size * 64), (int)(size * 64), 96, 96))
395 if(face->num_fixed_sizes)
398 int bestDiff = MAXINT, best = 0;
399 FT_Bitmap_Size * sizes = face->available_sizes;
400 int wishedHeight = (int)(size * 96 / 72);
401 for(c = 0; c < face->num_fixed_sizes; c++)
403 int diff = abs(sizes[c].height - wishedHeight);
410 FT_Set_Pixel_Sizes(face, sizes[best].width, sizes[best].height);
413 face->ascender = sizes[best].height;
414 scale = (float)wishedHeight / sizes[best].height;
433 class GlyphPack : BTNode
435 GlyphInfo glyphs[256];
437 BinaryTree outlines { };
438 int cellWidth, cellHeight;
440 void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
442 #if !defined(ECERE_NOTRUETYPE)
444 int maxWidth, maxHeight;
445 int cellWidth, cellHeight;
447 FontEntry fontEntry = null;
450 bool isGlyph = ((uint)key & 0x80000000) != 0;
451 //int curScript = ((uint)key & 0x7F000000) >> 24;
452 unichar testChar = 0;
458 case HB_Script_Arabic:
460 // printf("\nRendering arabic in %s (%d)\n", font.faceName, key & 0xFFFFFF);
462 case HB_Script_Devanagari:
465 case 60: testChar = 'あ'; break;
466 case 61: testChar = 0x3400; break;
473 FT_Vector pen = { 0, 0 };
476 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
477 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
478 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
479 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
480 FT_Set_Transform( fontEntry.face, &matrix, &pen );
482 FT_Set_Char_Size( fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
488 for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
490 fontEntry = font.fontEntries[c];
494 FT_Vector pen = { 0, 0 };
498 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
499 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
500 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
501 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
502 FT_Set_Transform(fontEntry.face, &matrix, &pen);
504 //FT_Set_Char_Size(fontEntry.face, (int)(font.size * 64), (int)(font.size * 64), 96, 96);
505 fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
507 font.scale = fontEntry.scale;
510 if(!fontEntry.face->units_per_EM)
511 font.ascent = (int)((double)fontEntry.face->ascender);
513 font.ascent = (int)((double)fontEntry.face->ascender * fontEntry.face->size->metrics.y_ppem / fontEntry.face->units_per_EM);
516 fontEntry.hbFont.x_ppem = fontEntry.face->size->metrics.x_ppem;
517 fontEntry.hbFont.y_ppem = fontEntry.face->size->metrics.y_ppem;
518 fontEntry.hbFont.x_scale = (int)fontEntry.face->size->metrics.x_scale;
519 fontEntry.hbFont.y_scale = (int)fontEntry.face->size->metrics.y_scale;
524 for(c = 0; c < 128; c++)
529 uint glyph = ((uint)key | c) & 0xFFFFFF;
530 for(entry = startFontEntry; entry < MAX_FONT_LINK_ENTRIES; entry++)
532 fontEntry = font.fontEntries[entry];
533 if(fontEntry && (FT_Get_Char_Index(fontEntry.face, testChar) || !testChar || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1]))
535 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
537 //printf("%s: Accepted entry %d ", font.faceName, entry);
545 for(entry = startFontEntry; ; entry++)
548 fontEntry = font.fontEntries[entry];
549 if((glyph = FT_Get_Char_Index(fontEntry.face, ((uint)key | c) & 0xFFFFFF)) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
551 if(!FT_Load_Glyph(fontEntry.face, glyph, FT_LOAD_DEFAULT /*FT_LOAD_NO_HINTING*/) || entry == MAX_FONT_LINK_ENTRIES-1 || !font.fontEntries[entry+1])
556 scales[c] = fontEntry.scale;
557 faces[c] = fontEntry.face;
558 maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
559 maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
560 //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
562 this.cellWidth = cellWidth = maxWidth;
563 this.cellHeight = cellHeight = maxHeight;
565 width = maxWidth * 16;
566 height = maxHeight * 8;
570 width = pow2i(height * 16);
571 height = pow2i(height * 8);
574 if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
576 Bitmap bitmap = this.bitmap;
578 bitmap.transparent = true;
580 for(c = 0; c < 128; c++)
584 int sx = (c % 16) * cellWidth;
585 int sy = (c / 16) * cellHeight;
587 byte * picture = (byte *)bitmap.picture;
588 GlyphInfo * glyph = &glyphs[c];
589 FT_GlyphSlot slot = faces[c]->glyph;
590 double em_size = 1.0 * faces[c]->units_per_EM;
591 //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
592 double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
593 double ascender = faces[c]->ascender * y_scale;
594 int glyphNo = isGlyph ? (((uint)key | c) & 0x00FFFFFF) : FT_Get_Char_Index(faces[c], (uint)key | c);
596 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
598 FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
602 //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
604 glyph->left = slot->bitmap_left;
605 // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + font.height - (faces[c]->size->metrics.height >> 6);
606 // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (font.height - maxHeight);
607 //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - font.height);
608 //glyph->top = (int)(ascender - slot->bitmap_top) + (font.height - (faces[c]->size->metrics.height >> 6));
610 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
611 //glyph->top = (int)(ascender + (font.height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
613 //glyph->top = (int)((ascender - slot->bitmap_top) + (font.height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
615 //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));
616 //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));
618 //glyph->top = (int)(ascender - slot->bitmap_top);// + (font.height - maxHeight);
619 glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
621 // 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);
622 xMax = x + slot->bitmap.width;
623 yMax = y + slot->bitmap.rows;
629 if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
631 for(j = y, q = 0; j<yMax; j++)
633 for(p = 0, i = x; i<xMax; i++)
635 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
642 q += slot->bitmap.pitch;
645 //max = numPixels ? (total / numPixels) : 1;
647 for(j = y, q = 0; j<yMax; j++)
650 for(p = 0, i = x; i<xMax; i++)
652 if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
654 picture[j * bitmap.stride + i] = (slot->bitmap.buffer[q + p] & bit) ? 255 : 0;
656 if(!bit) { bit = 0x80; p++; }
660 byte value = ((byte *)slot->bitmap.buffer)[q + p++];
661 picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
664 q += slot->bitmap.pitch;
669 glyph->w = slot->bitmap.width;
670 glyph->h = slot->bitmap.rows;
671 glyph->glyphNo = glyphNo;
672 glyph->bx = (int)faces[c]->glyph->metrics.horiBearingX;
673 glyph->by = (int)faces[c]->glyph->metrics.horiBearingY;
674 glyph->scale = scales[c];
676 glyph->ax = (int)slot->advance.x;
677 glyph->ay = (int)(slot->advance.y + (64 - slot->advance.y % 64));
684 for(c = 0; c<256; c++)
685 bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
686 bitmap.pixelFormat = pixelFormat8;
689 //strcpy(fileName, faceName);
691 strcat(fileName, "Bold");
693 sprintf(fileName, "font%d", fid++);
694 ChangeExtension(fileName, "pcx", fileName);
696 bitmap.Save(fileName, null, 0);
697 bitmap.pixelFormat = pixelFormatAlpha;
701 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
703 bitmap.keepData = true; // For outlines
704 displaySystem.Lock();
705 #if defined(__WIN32__)
706 // Is this check still required?
707 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
708 displaySystem.driver == class(Direct3D8DisplayDriver) ||
709 displaySystem.driver == class(Direct3D9DisplayDriver))
711 bitmap.MakeDD(displaySystem);
712 displaySystem.Unlock();
718 void RenderOutline(GlyphPack outline, Font font, DisplaySystem displaySystem)
720 #if !defined(ECERE_NOTRUETYPE) && !defined(ECERE_VANILLA)
722 int pCellWidth = this.cellWidth, pCellHeight = this.cellHeight;
723 int cellWidth, cellHeight;
725 uintptr key = outline.key;
726 float outlineSize = (float)(key >> 16);
727 float fade = ((uint32)key & 0xFFFF) / 255.f;
728 GlyphInfo * widest = null, * highest = null;
729 uint widestIndex = 0, highestIndex = 0;
731 int minX1 = MAXINT, minY1 = MAXINT;
732 int maxX2 = MININT, maxY2 = MININT;
734 byte * bigger = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
735 byte * field = new byte[pCellWidth * pCellHeight * timesBigger*timesBigger];
738 // Test biggest glyphs to determine cell width & height:
739 for(c = 0; c < 128; c++)
742 if(glyph->w > (widest ? widest->w : 0))
743 widest = glyph, widestIndex = c;
744 if(glyph->h > (highest ? highest->h : 0))
745 highest = glyph, highestIndex = c;
750 for(glyph = widest; glyph; glyph = (glyph == widest && glyph != highest) ? highest : null)
752 int index = (glyph == widest) ? widestIndex : highestIndex;
753 int x = (index & 0xF) * pCellWidth, y = (index >> 4) * pCellHeight;
754 int w = pCellWidth * timesBigger, h = pCellHeight * timesBigger;
757 memset(bigger, 0, w * h);
758 BlitOutline(bigger, (w - pCellWidth)/2, (h - pCellHeight)/2, w, h, bitmap.picture, x, y, pCellWidth, pCellHeight, bitmap.width);
759 ComputeOutline(field, bigger, w, h, outlineSize, fade);
760 MeasureOutline(field, w, h, &x1, &y1, &x2, &y2);
761 minX1 = Min(minX1, x1);
762 minY1 = Min(minY1, y1);
763 maxX2 = Max(maxX2, x2);
764 maxY2 = Max(maxY2, y2);
767 int x1 = (timesBigger*pCellWidth - pCellWidth) / 2, x2 = x1 + pCellWidth-1;
768 int y1 = (timesBigger*pCellHeight - pCellHeight) / 2, y2 = y1 + pCellHeight-1;
769 ox = -Max(0, x1 - minX1);
770 oy = -Max(0, y1 - minY1);
771 cellWidth = pCellWidth - ox + Max(0, (maxX2 > x2) ? (maxX2 - x2) : 0);
772 cellHeight = pCellHeight - oy + Max(0, (maxY2 > y2) ? (maxY2 - y2) : 0);
775 width = cellWidth * 16;
776 height = cellHeight * 8;
777 if(true) //TEXTURES_MUST_BE_POWER_OF_2)
779 width = pow2i(width);
780 height = pow2i(height);
783 if(outline.bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false))
785 Bitmap bitmap = outline.bitmap;
786 byte * picture = (byte *)bitmap.picture;
787 memset(picture, 0, width * height);
789 for(c = 0; c < 128; c++)
791 GlyphInfo * glyph = &outline.glyphs[c];
792 int x1 = MAXINT, y1 = MAXINT, x2 = MININT, y2 = MININT;
794 memset(bigger, 0, cellWidth * cellHeight);
795 BlitOutline(bigger, -ox, -oy, cellWidth, cellHeight,
797 (c & 0xF) * pCellWidth, (c >> 4) * pCellHeight,
798 pCellWidth, pCellHeight,
801 // Don't waste time on empty glyphs
804 ComputeOutline(field, bigger, cellWidth, cellHeight, outlineSize, fade);
805 MeasureOutline(field, cellWidth, cellHeight, &x1, &y1, &x2, &y2);
806 if(x2 > x1) w = x2-x1+1;
807 if(y2 > y1) h = y2-y1+1;
810 memset(field, 0, cellWidth * cellHeight);
812 glyph->x = (c & 0xF) * cellWidth;
813 glyph->y = (c >> 4) * cellHeight;
814 BlitOutline(picture, glyph->x, glyph->y, width, height, field, 0, 0, cellWidth, cellHeight, cellWidth);
816 glyph->glyphNo = glyphs[c].glyphNo;
817 glyph->scale = glyphs[c].scale;
818 glyph->left = glyphs[c].left + ox;
819 glyph->top = glyphs[c].top + oy;
820 if(w) { glyph->x += x1; glyph->left += x1; }
821 if(h) { glyph->y += y1; glyph->top += y1; }
824 glyph->bx = glyphs[c].bx;
825 glyph->by = glyphs[c].by;
826 glyph->ax = glyphs[c].ax;
827 glyph->ay = glyphs[c].ay;
835 for(c = 0; c<256; c++)
836 outline.bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
837 outline.bitmap.pixelFormat = pixelFormat8;
840 //strcpy(fileName, faceName);
842 strcat(fileName, "Bold");
844 sprintf(fileName, "outline%d", fid++);
845 ChangeExtension(fileName, "pcx", fileName);
847 outline.bitmap.Save(fileName, null, 0);
848 outline.bitmap.pixelFormat = pixelFormatAlpha;
853 char fileName[MAX_LOCATION];
855 sprintf(fileName, "template%03d.png", num);
856 bitmap.Save(fileName, null, 0);
857 sprintf(fileName, "outline%03d.png", num++);
858 outline.bitmap.Save(fileName, null, 0);
861 if(displaySystem && displaySystem.pixelFormat != pixelFormat4) // TODO: Add none PixelFormat
863 displaySystem.Lock();
864 #if defined(__WIN32__)
865 // Is this check still required?
866 if(displaySystem.driver == class(OpenGLDisplayDriver) ||
867 displaySystem.driver == class(Direct3D8DisplayDriver) ||
868 displaySystem.driver == class(Direct3D9DisplayDriver))
870 bitmap.MakeDD(displaySystem);
871 displaySystem.Unlock();
880 #if !defined(ECERE_NOTRUETYPE)
881 static HB_ShaperItem shaper_item;
883 static uint * shaping(FontEntry entry, uint16 * string, int len, HB_Script script, int *numGlyphs, bool * rightToLeft)
885 static uint maxGlyphs = 0;
886 HB_Glyph * glyphs = shaper_item.glyphs;
888 shaper_item.kerning_applied = 0;
889 shaper_item.string = string;
890 shaper_item.stringLength = len;
891 shaper_item.item.script = script;
892 shaper_item.item.pos = 0;
893 shaper_item.item.length = shaper_item.stringLength;
894 if(script == HB_Script_Arabic || script == HB_Script_Hebrew || script == HB_Script_Thaana || script == HB_Script_Syriac)
895 shaper_item.item.bidiLevel = 1;
897 shaper_item.item.bidiLevel = 0;
898 shaper_item.shaperFlags = 0;
899 shaper_item.font = &entry.hbFont;
900 shaper_item.face = entry.hbFace;
901 shaper_item.num_glyphs = shaper_item.item.length;
902 shaper_item.glyphIndicesPresent = 0;
903 shaper_item.initialGlyphCount = 0;
904 shaper_item.num_glyphs = 0;
905 shaper_item.glyphs = null;
907 while(!HB_ShapeItem(&shaper_item))
909 if(shaper_item.num_glyphs > maxGlyphs)
911 maxGlyphs = shaper_item.num_glyphs;
912 glyphs = shaper_item.glyphs = renew0 glyphs HB_Glyph[maxGlyphs];
913 shaper_item.attributes = renew0 shaper_item.attributes HB_GlyphAttributes[maxGlyphs];
914 shaper_item.advances = renew0 shaper_item.advances HB_Fixed[maxGlyphs];
915 shaper_item.offsets = renew0 shaper_item.offsets HB_FixedPoint[maxGlyphs];
916 shaper_item.log_clusters = renew0 shaper_item.log_clusters unsigned short[maxGlyphs];
920 shaper_item.glyphs = glyphs;
921 shaper_item.num_glyphs = maxGlyphs;
925 *numGlyphs = shaper_item.num_glyphs;
926 *rightToLeft = (bool)(shaper_item.item.bidiLevel % 2);
927 return shaper_item.glyphs;
931 delete shaper_item.glyphs;
932 delete shaper_item.attributes;
933 delete shaper_item.advances;
934 delete shaper_item.offsets;
935 delete shaper_item.log_clusters;
939 public class Font : struct
941 BinaryTree glyphPacks { };
942 GlyphPack asciiPack { };
943 #if !defined(ECERE_NOTRUETYPE)
944 FontEntry fontEntries[MAX_FONT_LINK_ENTRIES];
951 DisplaySystem displaySystem;
957 #if !defined(ECERE_NOTRUETYPE)
959 while((pack = (GlyphPack)glyphPacks.root))
961 glyphPacks.Remove(pack);
966 public property int ascent
968 get { return (int)(this ? ascent * scale : 0); }
972 public class LFBDisplay : struct
976 byte rgbLookup[32768];
977 byte lightTable[256][LIGHTSTEPS];
981 void (* displayCallback)(Display display, Box updateBox);
984 public class LFBSystem : struct
988 ColorAlpha * palette;
989 byte rgbLookup[32768];
996 ColorAlpha * palette = GetDefaultPalette();
997 for(c = 16; c < 232; c++)
999 Color555 color = palette[c].color;
1000 for(r = Max(0, color.r - 2); r <= Min(31, color.r + 4); r++)
1001 for(g = Max(0, color.g - 2); g <= Min(31, color.g + 4); g++)
1002 for(b = Max(0, color.b - 2); b <= Min(31, color.b + 4); b++)
1003 defaultRGBLookup[r * 32 * 32 + g * 32 + b] = (byte)c;
1005 for(c = 232; c < 246; c++)
1007 Color555 color = palette[c].color;
1008 defaultRGBLookup[color] = (byte)c;
1011 for(c = 246; c < 256; c++)
1013 Color555 color = palette[c].color;
1014 defaultRGBLookup[color] = (byte)c;
1016 for(c = 0; c < 16; c++)
1018 Color555 color = palette[c].color;
1019 defaultRGBLookup[color] = (byte)c;
1022 for(c = 0; c<32768; c++)
1024 Color color = (Color)(Color555)c;
1025 defaultRGBLookup[c] = 16 + (color.r * 5 / 255) * 36 + (color.g * 5 / 255) * 6 + (color.b * 5 / 255);
1026 // defaultRGBLookup[c] = (byte)BestColorMatch(palette, 0, 255, (Color)(Color555)c);
1029 rgbLookupSet = true;
1034 public class LFBSurface : struct
1037 // For compatibility with 3D drivers as well
1042 bool writingOutline;
1046 // Drawing attributes
1047 uint foreground, background;
1048 ColorAlpha foregroundRgb;
1051 byte * paletteShades;
1056 static int CompareHit(GLHitRecord * recordA, GLHitRecord * recordB, const void * nothing)
1058 if(recordA->zMin > recordB->zMin)
1060 else if(recordA->zMin < recordB->zMin)
1062 else if(recordA > recordB)
1064 else if(recordA < recordB)
1071 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
1074 char fileName[MAX_FILENAME];
1079 static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam)
1081 //if(fontType == TRUETYPE_FONTTYPE)
1083 FontData * fontData = (FontData *) lParam;
1084 char * fileName = (char *)lParam;
1086 int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL;
1087 int italic = (fontData->flags.italic) ? 1 : 0;
1088 if((fontData->forgive || weight == font->elfLogFont.lfWeight) && italic == (font->elfLogFont.lfItalic != 0))
1090 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",0,KEY_READ,&key) ||
1091 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts",0,KEY_READ,&key))
1096 char entryName[1024];
1097 char fontFileName[1024];
1100 DWORD sizeFileName = 1024;
1102 if(RegEnumValue(key, value++, entryName, &size, null, (PDWORD)&type, (LPBYTE)fontFileName, &sizeFileName) != ERROR_SUCCESS)
1104 if((occurence = SearchString(entryName, 0, (const char *)font->elfFullName, false, false)))
1107 for(c = (int)(occurence - entryName) - 1; c >= 0; c--)
1109 char ch = entryName[c];
1110 if(ch == '&') { c = -1; break; }
1111 else if(ch != ' ') break;
1113 if(c >= 0) continue;
1114 for(c = (int)(occurence - entryName) + strlen((char *)font->elfFullName); ; c++)
1116 char ch = entryName[c];
1117 if(ch == 0 || ch == '&' || ch == '(') { c = -1; break; }
1118 else if(ch != ' ') break;
1121 if(atoi(entryName + c))
1123 if(c >= 0) continue;
1125 strcpy(fileName, fontFileName);
1139 #if !defined(ECERE_NOTRUETYPE)
1140 static int utf16BufferSize = 0;
1141 static uint16 * utf16 = null;
1144 public class LFBDisplayDriver : DisplayDriver
1146 class_property(name) = "LFB";
1148 bool CreateDisplaySystem(DisplaySystem displaySystem)
1150 displaySystem.flags.memBackBuffer = true;
1151 // displaySystem.pixelFormat = pixelFormat888;
1155 void DestroyDisplaySystem(DisplaySystem displaySystem)
1159 void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1161 delete bitmap.picture;
1162 if(bitmap.allocatePalette)
1163 delete bitmap.palette;
1166 bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1168 bool result = false;
1171 switch(GetColorDepthShifts(format))
1173 case 0: stride = (width + 3) & 0xFFFFFFFC; break;
1174 case 1: stride = (width + 1) & 0xFFFFFFFE; break;
1175 case 2: stride = width; break;
1178 bitmap.stride = stride;
1179 bitmap.width = width;
1180 bitmap.height = height;
1181 bitmap.size = (uint32) stride * (uint32)height;
1182 bitmap.sizeBytes = bitmap.size << GetColorDepthShifts(format);
1183 bitmap.pixelFormat = format;
1184 bitmap.transparent = false;
1186 surface.box.left = surface.box.top = 0;
1187 surface.box.right = width - 1;
1188 surface.box.bottom = height - 1;
1190 bitmap.picture = new0 byte[bitmap.sizeBytes];
1193 bitmap.allocatePalette = allocatePalette;
1196 bitmap.palette = new ColorAlpha[256];
1199 CopyBytesBy4(bitmap.palette, GetDefaultPalette(), 256);
1205 bitmap.palette = GetDefaultPalette();
1210 FreeBitmap(displaySystem, bitmap);
1214 bool ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
1216 bool result = false;
1217 LFBSystem lfbSystem = displaySystem ? displaySystem.driverData : null;
1221 if((src.pixelFormat == format) && (format != pixelFormat8 || !palette))
1223 if(src.transparent && src.pixelFormat == pixelFormat888)
1227 DWORD * picture = (DWORD *)src.picture;
1229 for(c = 0; c<src.size; c++, picture++)
1231 if(*picture & 0xFFFFFF)
1232 *picture = *picture | 0xFF000000;
1234 *picture = *picture & 0xFFFFFF;
1243 if(bitmap.Allocate(null, src.width, src.height, 0, format, false))
1245 if(format == pixelFormat8)
1248 bitmap.palette = palette;
1249 else if(lfbSystem && lfbSystem.palette)
1250 bitmap.palette = lfbSystem.palette;
1252 bitmap.palette = src.palette;
1255 if(converters_table[src.pixelFormat][bitmap.pixelFormat])
1257 converters_table[src.pixelFormat][bitmap.pixelFormat](lfbSystem, src, bitmap);
1258 bitmap.transparent = src.transparent;
1259 bitmap.alphaBlend = src.alphaBlend && format != pixelFormat8;
1261 if(src.palette != bitmap.palette)
1263 if(src.allocatePalette)
1265 src.allocatePalette = false;
1267 src.picture = bitmap.picture;
1268 src.palette = bitmap.palette;
1269 src.stride = bitmap.stride;
1270 src.size = bitmap.size;
1271 src.sizeBytes = bitmap.sizeBytes;
1272 src.pixelFormat = bitmap.pixelFormat;
1277 bitmap.palette = null;
1278 bitmap.picture = null;
1286 void DestroyDisplay(Display display)
1288 LFBDisplay lfbDisplay = display.driverData;
1289 delete lfbDisplay.bitmap.palette;
1292 bool CreateDisplay(Display display)
1294 bool result = false;
1295 LFBDisplay lfbDisplay = display.driverData;
1298 lfbDisplay = display.driverData = LFBDisplay { };
1299 lfbDisplay.selfManaged = true;
1300 lfbDisplay.bitmap.pixelFormat = pixelFormatRGBA;
1303 if((lfbDisplay.bitmap.palette = new ColorAlpha[256]))
1305 CopyBytesBy4(lfbDisplay.bitmap.palette, GetDefaultPalette(), 256);
1311 bool DisplaySize(Display display, int width, int height)
1313 LFBDisplay lfbDisplay = display.driverData;
1314 //display.width = width;
1315 //display.height = height;
1316 lfbDisplay.bitmap.width = width;
1317 lfbDisplay.bitmap.height = height;
1319 lfbDisplay.updateBox.left = display.width;
1320 lfbDisplay.updateBox.top = display.height;
1321 lfbDisplay.updateBox.right = 0;
1322 lfbDisplay.updateBox.bottom = 0;
1325 if(lfbDisplay.selfManaged)
1327 lfbDisplay.bitmap.picture = (byte *)renew lfbDisplay.bitmap.picture int[width * height];
1328 lfbDisplay.bitmap.stride = width;
1330 lfbDisplay.bitmap.size = lfbDisplay.bitmap.stride * lfbDisplay.bitmap.height;
1334 void DisplayPosition(Display display, int x, int y)
1336 LFBDisplay lfbDisplay = display.driverData;
1341 void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1343 LFBDisplay lfbDisplay = display.driverData;
1350 LFBSystem lfbSystem = display.displaySystem ? display.displaySystem.driverData : null;
1351 palette = lfbSystem ? lfbSystem.palette : GetDefaultPalette();
1352 CopyBytes(lfbDisplay.rgbLookup, defaultRGBLookup, 32768);
1355 for(c = 0; c<32768; c++)
1356 lfbDisplay.rgbLookup[c] = (byte)BestColorMatch(palette, 1, 255, (Color)(Color555)c);
1358 for(c=0; c<256; c++)
1361 for(i=0; i<LIGHTSTEPS; i++)
1363 lfbDisplay.lightTable[c][i] = lfbDisplay.rgbLookup[(uint16)(Color555) Color {
1364 (byte)(((uint16)palette[c].color.r * i) >> LIGHTSHIFT),
1365 (byte)(((uint16)palette[c].color.g * i) >> LIGHTSHIFT),
1366 (byte)(((uint16)palette[c].color.b * i) >> LIGHTSHIFT) }];
1370 if(lfbDisplay.bitmap.palette)
1371 CopyBytesBy4(lfbDisplay.bitmap.palette, palette ? palette : GetDefaultPalette(), 256);
1374 void Update(Display display, Box updateBox)
1376 LFBDisplay lfbDisplay = display.driverData;
1377 if(lfbDisplay.displayCallback)
1379 if(updateBox == null)
1381 Box box { 0,0, display.width,display.height };
1382 lfbDisplay.displayCallback(display, box);
1385 lfbDisplay.displayCallback(display, updateBox);
1389 bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1391 if(bitmap.pixelFormat != pixelFormatAlpha)
1393 if(!ConvertBitmap(displaySystem, bitmap, /*bitmap.alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat, null))
1395 FreeBitmap(displaySystem, bitmap);
1402 void ReleaseSurface(Display display, Surface surface)
1404 LFBSurface lfbSurface = surface.driverData;
1406 surface.driverData = null;
1409 bool GetSurface(Display display, Surface surface, int x, int y, Box clip)
1411 LFBDisplay lfbDisplay = display.driverData;
1412 LFBSurface lfbSurface = surface.driverData;
1415 lfbSurface = surface.driverData = LFBSurface { };
1418 lfbSurface.bitmap = lfbDisplay.bitmap;
1420 surface.offset.x = x;
1421 surface.offset.y = y;
1423 if(lfbDisplay.bitmap.pixelFormat == pixelFormatText)
1425 surface.offset.x /= textCellW;
1426 surface.offset.y /= textCellH;
1427 surface.box.left /= textCellW;
1428 surface.box.top /= textCellH;
1429 surface.box.right /= textCellW;
1430 surface.box.bottom /= textCellH;
1434 lfbDisplay.updateBox.left = Min(x + clip.left, lfbDisplay.updateBox.left);
1435 lfbDisplay.updateBox.top = Min(y + clip.top, lfbDisplay.updateBox.top);
1436 lfbDisplay.updateBox.right = Max(x + clip.right, lfbDisplay.updateBox.right);
1437 lfbDisplay.updateBox.bottom = Max(y + clip.bottom, lfbDisplay.updateBox.bottom);
1440 surface.unclippedBox = surface.box;
1441 lfbSurface.drawingChar = 219;
1445 bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x,int y, Box clip)
1447 bool result = false;
1448 LFBSurface lfbSurface = surface.driverData;
1449 if(lfbSurface || (surface.driverData = lfbSurface = LFBSurface { }))
1451 lfbSurface.bitmap = bitmap;
1453 surface.offset.x = x;
1454 surface.offset.y = y;
1456 if(bitmap.pixelFormat == pixelFormatText)
1458 surface.offset.x /= textCellW;
1459 surface.offset.y /= textCellH;
1460 surface.box.left /= textCellW;
1461 surface.box.top /= textCellH;
1462 surface.box.right /= textCellW;
1463 surface.box.bottom /= textCellH;
1466 surface.unclippedBox = *&surface.box;
1467 lfbSurface.drawingChar = 219;
1474 void Clip(Display display, Surface surface, Box clip)
1476 LFBSurface lfbSurface = surface.driverData;
1481 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1483 box.left /= textCellW;
1484 box.top /= textCellH;
1485 box.right /= textCellW;
1486 box.bottom /= textCellH;
1488 box.Clip(surface.unclippedBox);
1492 surface.box = surface.unclippedBox;
1495 void SetForeground(Display display, Surface surface, ColorAlpha color)
1497 LFBDisplay lfbDisplay = display ? display.driverData : null;
1498 LFBSurface lfbSurface = surface.driverData;
1500 //if(display) color = color & 0xFFFFFF;
1501 lfbSurface.foregroundRgb = color;
1503 if(lfbSurface.font && lfbDisplay)
1505 index = lfbDisplay.rgbLookup[(uint16)(Color555)lfbSurface.foregroundRgb];
1506 lfbSurface.paletteShades = lfbDisplay.lightTable[index];
1509 switch(lfbSurface.bitmap.pixelFormat)
1513 lfbSurface.foreground = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1515 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1517 case pixelFormat444: lfbSurface.foreground = (Color444)color; break;
1518 case pixelFormat555: lfbSurface.foreground = (Color555)color; break;
1519 case pixelFormat565: lfbSurface.foreground = (Color565)color; break;
1520 case pixelFormat888: lfbSurface.foreground = color; break;
1521 case pixelFormatRGBA: lfbSurface.foreground = (ColorRGBA)color; break;
1522 case pixelFormatText:
1524 lfbSurface.foreground = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 8;
1526 lfbSurface.foreground = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 8;
1531 void SetBackground(Display display, Surface surface, ColorAlpha color)
1533 LFBDisplay lfbDisplay = display ? display.driverData : null;
1534 LFBSurface lfbSurface = surface.driverData;
1535 //color = color & 0xFFFFFF;
1536 switch(lfbSurface.bitmap.pixelFormat)
1540 lfbSurface.background = lfbDisplay.rgbLookup[(uint16)(Color555)color];
1542 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,255,color);
1544 case pixelFormat444: lfbSurface.background = (Color444)color; break;
1545 case pixelFormat555: lfbSurface.background = (Color555)color; break;
1546 case pixelFormat565: lfbSurface.background = (Color565)color; break;
1547 case pixelFormat888: lfbSurface.background = color; break;
1548 case pixelFormatRGBA: lfbSurface.background = (ColorRGBA)color; break;
1549 case pixelFormatText:
1551 lfbSurface.background = BestColorMatch(lfbDisplay.bitmap.palette,0,15,color) << 12;
1553 lfbSurface.background = BestColorMatch(lfbSurface.bitmap.palette,0,15,color) << 12;
1558 ColorAlpha GetPixel(Display display, Surface surface, int x, int y)
1560 LFBSurface lfbSurface = surface.driverData;
1561 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1566 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1568 x += surface.offset.x;
1569 y += surface.offset.y;
1570 if(lfbSurface.bitmap.picture)
1572 switch(lfbSurface.bitmap.pixelFormat)
1574 case pixelFormatText:
1576 if(!lfbSurface.bitmap.palette) return 0;
1577 return lfbSurface.bitmap.palette[((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x]];
1578 case pixelFormat444: return ((Color444 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1579 case pixelFormat555: return ((Color555 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1580 case pixelFormat565: return ((Color565 *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x];
1581 case pixelFormat888: return ((ColorAlpha *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride+x];
1588 void PutPixel(Display display, Surface surface,int x,int y)
1590 LFBSurface lfbSurface = surface.driverData;
1591 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1596 if((x <= surface.box.right) && (y <= surface.box.bottom) && (x >= surface.box.left) && (y >= surface.box.top))
1598 x += surface.offset.x;
1599 y += surface.offset.y;
1600 if(lfbSurface.bitmap.picture)
1602 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1605 ((byte *)lfbSurface.bitmap.picture)[(uint) y * lfbSurface.bitmap.stride + x] = (byte)lfbSurface.foreground;
1608 ((uint16 *)lfbSurface.bitmap.picture)[(uint)y * lfbSurface.bitmap.stride + x] = (uint16)lfbSurface.foreground;
1611 if(((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] != (uint32)lfbSurface.foreground)
1612 ((uint32 *)lfbSurface.bitmap.picture)[(uint32) y * lfbSurface.bitmap.stride + x] = (uint32)lfbSurface.foreground;
1619 void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
1621 LFBSurface lfbSurface = surface.driverData;
1627 uint color = lfbSurface.foreground;
1628 uint16 stipple = lfbSurface.stipple ? lfbSurface.stipple : 0xFFFF;
1629 bool invert = false;
1630 if(!lfbSurface.bitmap.picture) return;
1631 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
1637 if(surface.textOpacity)
1638 color |= lfbSurface.background;
1639 color |= lfbSurface.drawingChar;
1643 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; invert = true; }
1645 if((y1>surface.box.bottom)||(y1<surface.box.top))return;
1646 if((x1>surface.box.right)||(x2<surface.box.left))return;
1647 if(x1<surface.box.left)x1=surface.box.left;
1648 if(x2>surface.box.right)x2=surface.box.right;
1652 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1653 if(stipple != 0xFFFF)
1656 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1659 for(x=x1; x<=x2; x++, offset++)
1661 if(stipple & 0x8000)
1662 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1664 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1666 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1670 for(x=x1; x<=x2; x++, offset++)
1672 if(stipple & 0x8000)
1673 ((uint16 *)lfbSurface.bitmap.picture)[offset] = (uint16)color;
1675 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1677 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1681 for(x=x1; x<=x2; x++, offset++)
1683 if(stipple & 0x8000)
1684 ((uint32 *)lfbSurface.bitmap.picture)[offset] = color;
1686 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1688 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1695 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1697 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1699 case 0: FillBytes(((byte *)lfbSurface.bitmap.picture)+offset,(byte)color,x2-x1+1); break;
1700 case 1: FillBytesBy2(((uint16 *)lfbSurface.bitmap.picture)+offset,(uint16)color,x2-x1+1); break;
1701 case 2: FillBytesBy4(((uint32 *)lfbSurface.bitmap.picture)+offset,color,x2-x1+1); break;
1707 for(x = x1; x <= x2; x++, offset++)
1709 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1710 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1719 if(y1>y2) { int tmp = y2; y2 = y1; y1 = tmp; invert = true; }
1721 if((x1>surface.box.right)||(x1<surface.box.left))return;
1722 if((y1>surface.box.bottom)||(y2<surface.box.top))return;
1723 if(y1<surface.box.top)y1=surface.box.top;
1724 if(y2>surface.box.bottom)y2=surface.box.bottom;
1726 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1727 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1730 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1732 if(stipple & 0x8000)
1733 ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color;
1735 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1737 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1741 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1743 if(stipple & 0x8000)
1745 if(lfbSurface.bitmap.pixelFormat != pixelFormatText || surface.textOpacity)
1746 ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color;
1749 ((uint16 *)lfbSurface.bitmap.picture)[offset] =
1750 (((uint16 *)lfbSurface.bitmap.picture)[offset] & 0xF000) | (uint16)color;
1754 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1756 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1760 if(stipple != 0xFFFF)
1762 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1764 if(stipple & 0x8000)
1765 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1767 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1769 stipple = ((stipple & 0xFFFE)>>1) | ((stipple & 0x0001)<<15);
1774 for(y=y1; y<=y2; y++, offset+=lfbSurface.bitmap.stride)
1775 ((uint32*)lfbSurface.bitmap.picture)[offset]=color;
1784 if(x1 < surface.box.left)
1786 if(x2 < surface.box.left)
1788 y1 += (y2 - y1) * (surface.box.left - x1) / (x2 - x1);
1789 x1 = surface.box.left;
1791 if(x2 > surface.box.right)
1793 if(x1 > surface.box.right)
1795 y2 -= (y2 - y1) * (x2 - surface.box.right) / (x2 - x1);
1796 x2 = surface.box.right;
1800 if(y1 < surface.box.top)
1802 if(y2 < surface.box.top)
1804 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1805 y1 = surface.box.top;
1807 if(y2 > surface.box.bottom)
1809 if(y1 > surface.box.bottom)
1811 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1812 y2 = surface.box.bottom;
1817 if(y1 > surface.box.bottom)
1819 if(y2 > surface.box.bottom)
1821 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1822 y1 = surface.box.bottom;
1824 if(y2 < surface.box.top)
1826 if(y1 < surface.box.top)
1828 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1829 y2 = surface.box.top;
1835 if(x1 > surface.box.right)
1837 if(x2 > surface.box.right)
1839 y1 -= (y1 - y2) * (x1 - surface.box.right) / (x1 - x2);
1840 x1 = surface.box.right;
1842 if(x2 < surface.box.left)
1844 if(x1 < surface.box.left)
1846 y2 += (y1 - y2) * (surface.box.left - x2) / (x1 - x2);
1847 x2 = surface.box.left;
1851 if(y1 < surface.box.top)
1853 if(y2 < surface.box.top)
1855 x1 += (x2 - x1) * (surface.box.top - y1) / (y2 - y1);
1856 y1 = surface.box.top;
1858 if(y2 > surface.box.bottom)
1860 if(y1 > surface.box.bottom)
1862 x2 -= (x2 - x1) * (y2 - surface.box.bottom) / (y2 - y1);
1863 y2 = surface.box.bottom;
1868 if(y1 > surface.box.bottom)
1870 if(y2 > surface.box.bottom)
1872 x1 -= (x1 - x2) * (y1 - surface.box.bottom) / (y1 - y2);
1873 y1 = surface.box.bottom;
1875 if(y2 < surface.box.top)
1877 if(y1 < surface.box.top)
1879 x2 += (x1 - x2) * (surface.box.top - y2) / (y1 - y2);
1880 y2 = surface.box.top;
1898 yu=-(int)lfbSurface.bitmap.stride;
1901 yu=lfbSurface.bitmap.stride;
1903 offset=(y1+surface.offset.y)*lfbSurface.bitmap.stride+x1+surface.offset.x;
1909 for(i=0; i<=length; i++)
1911 if(stipple & 0x8000)
1912 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1914 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1915 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1916 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1925 stipple = ((stipple & 0x7FFF)<<1) | ((stipple & 0x8000)>>15);
1931 for(i=0; i<=length; i++)
1933 if(stipple & 0x8000)
1934 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
1936 case 0: ((byte *)lfbSurface.bitmap.picture)[offset]=(byte)color; break;
1937 case 1: ((uint16 *)lfbSurface.bitmap.picture)[offset]=(uint16)color; break;
1938 case 2: ((uint32*)lfbSurface.bitmap.picture)[offset]=(uint32)color; break;
1952 void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
1954 DrawLine(display, surface,x1,y1,x2,y1);
1955 DrawLine(display, surface,x2,y1,x2,y2);
1956 DrawLine(display, surface,x2,y2,x1,y2);
1957 DrawLine(display, surface,x1,y2,x1,y1);
1960 #if !defined(__GNUC__)
1962 void memset_32_aligned(void *buf, int val, int dwords)
1967 *((uint32 *)(buf)) = val;
1968 buf = ((uint32 *)(buf))+1;
1994 if (dwords & 1) *((int*)(buf)) = val;
2000 void memset_32_aligned(uint32 *buf, uint32 val, uint32 dwords)
2004 if(((uint32)buf) & 0x7F)
2006 for( ; ((uint32)buf) & 0x7F && dwords; buf++)
2032 sub edx,ebx ; edx holds # of overflow bytes
2051 movdqa [edi+16],xmm0
2052 movdqa [edi+32],xmm0
2053 movdqa [edi+48],xmm0
2054 movdqa [edi+64],xmm0
2055 movdqa [edi+80],xmm0
2056 movdqa [edi+96],xmm0
2057 movdqa [edi+112],xmm0
2081 void memset_32(void *buf, uint32 val, uint32 dwords)
2084 if ((uint32)(buf) & 3)
2089 if (((uint32)(buf) & 1))
2091 *(byte *)(buf) = (byte)(val&0xFF);
2092 buf = ((byte *)(buf))+1;
2093 val = ((val& 0xFF) << 24) || ((val& 0xFFFFFF00) >> 8);
2096 if (((uint32)(buf) & 2))
2098 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
2099 buf = ((uint16 *)(buf))+1;
2100 val = ((val& 0xFFFF) << 16) || ((val& 0xFFFF0000) >> 16);
2104 memset_32_aligned(buf,val,dwords);
2109 *(byte *)(buf) = (byte)(val&0xFF);
2113 *(uint16 *)(buf) = (uint16)(val&0xFFFF);
2114 if (align & 1) *((byte *)(buf)+2) = (byte)((val>>16)&0xFF);
2121 void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2123 LFBSurface lfbSurface = surface.driverData;
2124 uint32 color = lfbSurface.background;
2126 if(lfbSurface.bitmap.pixelFormat == pixelFormatText)
2128 color |= lfbSurface.foreground | lfbSurface.drawingChar;
2134 if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
2136 if(x1<surface.box.left) x1=surface.box.left;
2137 if(x2>surface.box.right) x2=surface.box.right;
2138 if(y1<surface.box.top) y1=surface.box.top;
2139 if(y2>surface.box.bottom) y2=surface.box.bottom;
2141 if(x2>=x1 && y2>=y1)
2149 x1 += surface.offset.x;
2150 x2 += surface.offset.x;
2151 y1 += surface.offset.y;
2152 y2 += surface.offset.y;
2153 if(lfbSurface.bitmap.picture)
2155 if(!surface.writeColor)
2157 ColorAlpha * picture = (((ColorAlpha *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2158 for(y = y1; y<= y2; y++)
2161 for(c = 0; c < w; c++, picture++)
2163 picture->a = (byte)((color & 0xFF000000) >> 24);
2164 picture += lfbSurface.bitmap.stride - w;
2169 if(!surface.blend || surface.background.a == 255 || lfbSurface.clearing)
2171 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2174 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
2175 for(y = y1; y<= y2; y++)
2177 FillBytes(theOffset,(byte)color,w);
2178 theOffset += lfbSurface.bitmap.stride;
2182 theOffset = (byte *) (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2183 for(y = y1; y<= y2; y++)
2185 FillBytesBy2((uint16 *) theOffset,(uint16)color,w);
2186 theOffset += lfbSurface.bitmap.stride * sizeof(uint16);
2190 theOffset = (byte *) (((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2191 for(y = y1; y<= y2; y++)
2193 #if defined(__GNUC__)
2194 FillBytesBy4((uint32 *) theOffset,color,w);
2196 memset_32((uint32 *) theOffset,color,w);
2198 theOffset += lfbSurface.bitmap.stride * sizeof(uint32);
2204 int bla = (lfbSurface.bitmap.stride - w) * sizeof(uint32);
2205 //memset_32((uint32 *) theOffset,color,w);
2241 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2244 theOffset = ((byte *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1;
2245 for(y = y1; y<= y2; y++)
2247 // TODO: IMPLEMENT THIS
2248 FillBytes(theOffset,(byte)color,w);
2249 theOffset += lfbSurface.bitmap.stride;
2254 uint16 * dest = (((uint16 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2255 ColorAlpha c = surface.background;
2260 PixelFormat pixelFormat = lfbSurface.bitmap.pixelFormat;
2262 for(y = y1; y <= y2; y++)
2265 for(c = 0; c < w; c++, dest++)
2267 Color destColor = 0;
2268 if(pixelFormat == pixelFormat565) { destColor = (Color)*(Color565 *)dest; }
2269 else if(pixelFormat == pixelFormat555) { destColor = (Color)*(Color555 *)dest; }
2270 else if(pixelFormat == pixelFormat444) { destColor = (Color)*(Color444 *)dest; }
2272 int r = a * cr / 255 + ((255 - a) * destColor.r / 255);
2273 int g = a * cg / 255 + ((255 - a) * destColor.g / 255);
2274 int b = a * cb / 255 + ((255 - a) * destColor.b / 255);
2276 if(r > 255) r = 255;
2277 if(g > 255) g = 255;
2278 if(b > 255) b = 255;
2280 destColor = { (byte)r, (byte)g, (byte)b };
2282 if(pixelFormat == pixelFormat565) { *dest = (Color565)destColor; }
2283 else if(pixelFormat == pixelFormat555) { *dest = (Color555)destColor; }
2284 else if(pixelFormat == pixelFormat444) { *dest = (Color444)destColor; }
2287 dest += (lfbSurface.bitmap.stride - w);
2293 ColorAlpha * dest = (ColorAlpha *)(((uint32 *)lfbSurface.bitmap.picture) + y1 * lfbSurface.bitmap.stride + x1);
2294 AlphaWriteMode alphaWrite = surface.alphaWrite;
2295 ColorAlpha c = surface.background;
2300 for(y = y1; y <= y2; y++)
2303 for(c = 0; c < w; c++, dest++)
2305 int dr = dest->color.r;
2306 int dg = dest->color.g;
2307 int db = dest->color.b;
2308 int r = a * cr / 255 + ((255 - a) * dr / 255);
2309 int g = a * cg / 255 + ((255 - a) * dg / 255);
2310 int b = a * cb / 255 + ((255 - a) * db / 255);
2312 if(r > 255) r = 255;
2313 if(g > 255) g = 255;
2314 if(b > 255) b = 255;
2315 dest->color = { (byte)r, (byte)g, (byte)b };
2317 if(alphaWrite == blend)
2319 int ca = (int)(a + ((255 - a) * dest->a / 255));
2320 if(ca > 255) ca = 255;
2326 dest += (lfbSurface.bitmap.stride - w);
2335 void Clear(Display display, Surface surface, ClearType type)
2337 LFBSurface lfbSurface = surface.driverData;
2339 lfbSurface.clearing = true;
2340 if(surface.offset.x == 0 && surface.offset.y == 0 &&
2341 surface.box.left == 0 && surface.box.top == 0 &&
2342 surface.box.right == surface.width-1 &&
2343 surface.box.bottom == surface.height-1)
2345 uint32 color = /*0xFF000000 | */lfbSurface.background;
2346 if(type != depthBuffer)
2348 if(lfbSurface.bitmap.stride != surface.width)
2349 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2352 switch(GetColorDepthShifts(lfbSurface.bitmap.pixelFormat))
2355 FillBytes(lfbSurface.bitmap.picture, (byte)color, lfbSurface.bitmap.size);
2357 case 1: FillBytesBy2((uint16 *)lfbSurface.bitmap.picture, (uint16)color, lfbSurface.bitmap.size); break;
2358 case 2: FillBytesBy4((uint32 *)lfbSurface.bitmap.picture, color, lfbSurface.bitmap.size); break;
2363 if((flags & CLEAR_Z) && zbuffer)
2364 FillBytesBy4((DWORD *)zbuffer,0,(sizeof(float)*(DWORD)display.width * display.Height)>>2);
2369 if(type != depthBuffer)
2370 Area(display, surface,surface.box.left,surface.box.top,surface.box.right,surface.box.bottom);
2372 if((flags & CLEAR_Z))
2375 uint32 w = surface.box.right-surface.box.left+1;
2376 float * offset = zbuffer + ((surface.box.top +surface.offset.y) * (DWORD)DISPLAY.Width)
2377 + surface.box.left+surface.offset.x;
2378 for(y = surface.box.top; y<= surface.box.bottom; y++)
2380 FillBytesBy4((uint32 *) offset,0,(sizeof(float)>>2)*w);
2381 offset += DISPLAY.Width;
2386 lfbSurface.clearing = false;
2389 void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2391 LFBSurface lfbSurface = surface.driverData;
2394 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2396 if(w < 0) { w = -w; flip = true; }
2398 //Clip against the edges of the source
2411 if(sx+w>src.width-1)
2412 w-=sx+w-(src.width-1)-1;
2413 if(sy+h>src.height-1)
2414 h-=sy+h-(src.height-1)-1;
2415 //Clip against the edges of the destination
2416 if(dx<surface.box.left)
2418 if(!flip) sx+=surface.box.left-dx;
2419 w-=surface.box.left-dx;
2420 dx=surface.box.left;
2422 if(dy<surface.box.top)
2424 sy+=surface.box.top-dy;
2425 h-=surface.box.top-dy;
2428 if((dx+w)>surface.box.right)
2430 if(flip) sx+=(uint32)(dx+w)-surface.box.right-1;
2431 w-=((uint32)(dx+w)-surface.box.right-1);
2433 if((dy+h)>surface.box.bottom)
2434 h-=((dy+h)-surface.box.bottom-1);
2438 dx += surface.offset.x;
2439 dy += surface.offset.y;
2441 if(lfbSurface.bitmap.picture)
2443 AlphaWriteMode alphaWrite = surface.alphaWrite;
2444 if(src.alphaBlend && surface.blend)
2447 if(src.pixelFormat == pixelFormatAlpha)
2449 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2451 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2452 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2453 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2454 for(y = 0; y < h; y++)
2456 for(x = 0; x < w; x++, picture++, source++)
2458 int a = *source * color.a;
2459 ColorAlpha dest = *picture;
2460 int r = (a * color.color.r + ((255 * 255 - a) * dest.color.r)) / (255 * 255);
2461 int g = (a * color.color.g + ((255 * 255 - a) * dest.color.g)) / (255 * 255);
2462 int b = (a * color.color.b + ((255 * 255 - a) * dest.color.b)) / (255 * 255);
2463 if(r > 255) r = 255;
2464 if(g > 255) g = 255;
2465 if(b > 255) b = 255;
2466 picture->color = { (byte)r, (byte)g, (byte)b };
2467 if(alphaWrite == blend)
2469 int ca = (a * 255 + (255 * 255 - a) * dest.a) / (255 * 255);
2470 if(ca > 255) ca = 255;
2471 picture->a = (byte)ca;
2474 picture->a = (byte)(a / 255);
2476 picture += lfbSurface.bitmap.stride - w;
2477 source += src.stride - w;
2480 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2482 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2483 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2484 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2485 for(y = 0; y < h; y++)
2487 for(x = 0; x < w; x++, picture++, source++)
2489 int a = *source * color.a;
2490 Color dest = *picture;
2491 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2492 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2493 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2494 if(r > 255) r = 255;
2495 if(g > 255) g = 255;
2496 if(b > 255) b = 255;
2497 *picture = Color { (byte)r, (byte)g, (byte)b };
2499 picture += lfbSurface.bitmap.stride - w;
2500 source += src.stride - w;
2503 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2505 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2506 byte * source = ((byte *)src.picture) + (src.stride * sy) + sx;
2507 ColorAlpha color = lfbSurface.writingText ? surface.foreground : surface.blitTint;
2508 for(y = 0; y < h; y++)
2510 for(x = 0; x < w; x++, picture++, source++)
2512 int a = *source * color.a;
2513 Color dest = *picture;
2514 int r = (a * color.color.r + ((255 * 255 - a) * dest.r)) / (255 * 255);
2515 int g = (a * color.color.g + ((255 * 255 - a) * dest.g)) / (255 * 255);
2516 int b = (a * color.color.b + ((255 * 255 - a) * dest.b)) / (255 * 255);
2517 if(r > 255) r = 255;
2518 if(g > 255) g = 255;
2519 if(b > 255) b = 255;
2520 *picture = Color { (byte)r, (byte)g, (byte)b };
2522 picture += lfbSurface.bitmap.stride - w;
2523 source += src.stride - w;
2529 ColorAlpha * source = ((ColorAlpha *)src.picture) + (src.stride * sy) + sx;
2530 if(lfbSurface.bitmap.pixelFormat == pixelFormat888)
2532 ColorAlpha * picture = ((ColorAlpha *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2533 for(y = 0; y < h; y++)
2535 for(x = 0; x < w; x++, picture++, source++)
2537 ColorAlpha src = *source;
2538 ColorAlpha dest = *picture;
2539 int r = src.a * src.color.r / 255 + ((255 - src.a) * dest.color.r / 255);
2540 int g = src.a * src.color.g / 255 + ((255 - src.a) * dest.color.g / 255);
2541 int b = src.a * src.color.b / 255 + ((255 - src.a) * dest.color.b / 255);
2542 if(r > 255) r = 255;
2543 if(g > 255) g = 255;
2544 if(b > 255) b = 255;
2545 picture->color = { (byte)r, (byte)g, (byte)b };
2546 if(alphaWrite == blend)
2548 int a = src.a + ((255 - src.a) * dest.a / 255);
2549 if(a > 255) a = 255;
2550 picture->a = (byte)a;
2555 picture += lfbSurface.bitmap.stride - w;
2556 source += src.stride - w;
2559 else if(lfbSurface.bitmap.pixelFormat == pixelFormat565)
2561 Color565 * picture = ((Color565 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2562 for(y = 0; y < h; y++)
2564 for(x = 0; x < w; x++, picture++, source++)
2566 ColorAlpha src = *source;
2567 Color565 dest = *picture;
2568 int r = src.a * src.color.r * 31 / 255 + ((255 - src.a) * dest.r);
2569 int g = src.a * src.color.g * 63 / 255 + ((255 - src.a) * dest.g);
2570 int b = src.a * src.color.b * 31 / 255 + ((255 - src.a) * dest.b);
2571 if(r > 255 * 31) r = 255 * 31;
2572 if(g > 255 * 63) g = 255 * 63;
2573 if(b > 255 * 31) b = 255 * 31;
2574 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2576 picture += lfbSurface.bitmap.stride - w;
2577 source += src.stride - w;
2580 else if(lfbSurface.bitmap.pixelFormat == pixelFormat555)
2582 Color555 * picture = ((Color555 *)lfbSurface.bitmap.picture) + (lfbSurface.bitmap.stride * dy) + dx;
2583 for(y = 0; y < h; y++)
2585 for(x = 0; x < w; x++, picture++, source++)
2587 ColorAlpha psrc = *source;
2588 Color555 dest = *picture;
2589 int r = psrc.a * psrc.color.r * 31 / 255 + ((255 - psrc.a) * dest.r);
2590 int g = psrc.a * psrc.color.g * 31 / 255 + ((255 - psrc.a) * dest.g);
2591 int b = psrc.a * psrc.color.b * 31 / 255 + ((255 - psrc.a) * dest.b);
2592 if(r > 255 * 31) r = 255 * 31;
2593 if(g > 255 * 31) g = 255 * 31;
2594 if(b > 255 * 31) b = 255 * 31;
2595 *picture = { (byte)(r / 255), (byte)(g / 255), (byte)(b / 255) };
2597 picture += lfbSurface.bitmap.stride - w;
2598 source += src.stride - w;
2603 else if(src.paletteShades)
2604 shades_blit_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2605 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2606 blits_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2607 else if(src.pixelFormat == pixelFormat8)
2608 blits_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h);
2612 bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2614 bool result = false;
2615 LFBDisplay lfbDisplay = display.driverData;
2617 if(bitmap.pixelFormat != lfbDisplay.bitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
2620 bitmap.Allocate(null, w,h,w, lfbDisplay.bitmap.pixelFormat,
2621 (lfbDisplay.bitmap.pixelFormat == pixelFormat8)?true:false);
2625 Surface surface = bitmap.GetSurface(0,0,null);
2628 Blit(display, surface, lfbDisplay.bitmap, 0,0,x,y,w,h);
2629 if(bitmap.palette && lfbDisplay.bitmap.pixelFormat == pixelFormat8 && lfbDisplay.bitmap.palette)
2630 CopyBytesBy4(bitmap.palette, lfbDisplay.bitmap.palette, 256);
2638 void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2640 LFBSurface lfbSurface = surface.driverData;
2643 float s2dw,s2dh,d2sw,d2sh;
2645 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2647 if(Sgn(w) != Sgn(sw))
2659 //Clip against the edges of the source
2662 dx+=(int)((0-sx) * s2dw);
2663 w-=(int)((0-sx) * s2dw);
2669 dy+=(int)((0-sy) * s2dh);
2670 h-=(int)((0-sy) * s2dh);
2675 if(sx+sw>src.width-1)
2677 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2678 sw-=sx+sw-(src.width-1)-1;
2680 if(sy+sh>(src.height-1))
2682 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2683 sh-=sy+sh-(src.height-1)-1;
2685 //Clip against the edges of the destination
2686 if(dx<surface.box.left)
2688 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2689 sw-=(int)((surface.box.left-dx)*d2sw);
2690 w-=surface.box.left-dx;
2691 dx=surface.box.left;
2693 if(dy<surface.box.top)
2695 sy+=(int)((surface.box.top-dy)*d2sh);
2696 sh-=(int)((surface.box.top-dy)*d2sh);
2697 h-=surface.box.top-dy;
2700 if((dx+w)>surface.box.right)
2702 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2703 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2704 w-=((dx+w)-surface.box.right-1);
2706 if((dy+h)>surface.box.bottom)
2708 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2709 h-=((dy+h)-surface.box.bottom-1);
2711 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2713 dx+=surface.offset.x;
2714 dy+=surface.offset.y;
2716 if(lfbSurface.bitmap.picture)
2718 AlphaWriteMode alphaWrite = surface.alphaWrite;
2719 if(src.alphaBlend && surface.blend)
2723 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2724 ColorAlpha * backsrc;
2725 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2726 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2727 if(flip) source += sw-1;
2745 ColorAlpha src = *source;
2746 ColorAlpha dst = *dest;
2747 int r = src.a * src.color.r / 255 + ((255 - src.a) * dst.color.r / 255);
2748 int g = src.a * src.color.g / 255 + ((255 - src.a) * dst.color.g / 255);
2749 int b = src.a * src.color.b / 255 + ((255 - src.a) * dst.color.b / 255);
2750 if(r > 255) r = 255;
2751 if(g > 255) g = 255;
2752 if(b > 255) b = 255;
2753 dest->color = { (byte)r, (byte)g, (byte)b };
2754 if(alphaWrite == blend)
2756 int a = src.a + ((255 - src.a) * dst.a / 255);
2757 if(a > 255) a = 255;
2770 source += addsource;
2773 else if(src.paletteShades)
2774 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2775 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2776 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2777 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2778 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2782 void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2784 LFBSurface lfbSurface = surface.driverData;
2787 float s2dw,s2dh,d2sw,d2sh;
2789 if(surface.box.right < surface.box.left || surface.box.bottom < surface.box.top || !src.picture) return;
2791 if(Sgn(w) != Sgn(sw))
2803 //Clip against the edges of the source
2806 dx+=(int)((0-sx) * s2dw);
2807 w-=(int)((0-sx) * s2dw);
2813 dy+=(int)((0-sy) * s2dh);
2814 h-=(int)((0-sy) * s2dh);
2819 if(sx+sw>src.width-1)
2821 w-=(int)((sx+sw-(src.width-1)-1)*s2dw);
2822 sw-=sx+sw-(src.width-1)-1;
2824 if(sy+sh>(src.height-1))
2826 h-=(int)((sy+sh-(src.height-1)-1)*s2dh);
2827 sh-=sy+sh-(src.height-1)-1;
2829 //Clip against the edges of the destination
2830 if(dx<surface.box.left)
2832 if(!flip) sx+=(int)((surface.box.left-dx)*d2sw);
2833 sw-=(int)((surface.box.left-dx)*d2sw);
2834 w-=surface.box.left-dx;
2835 dx=surface.box.left;
2837 if(dy<surface.box.top)
2839 sy+=(int)((surface.box.top-dy)*d2sh);
2840 sh-=(int)((surface.box.top-dy)*d2sh);
2841 h-=surface.box.top-dy;
2844 if((dx+w)>surface.box.right)
2846 if(flip) sx+=(int)(((dx+w)-surface.box.right-1)*d2sw);
2847 sw-=(int)(((dx+w)-surface.box.right-1)*d2sw);
2848 w-=((dx+w)-surface.box.right-1);
2850 if((dy+h)>surface.box.bottom)
2852 sh-=(int)(((dy+h)-surface.box.bottom-1)*d2sh);
2853 h-=((dy+h)-surface.box.bottom-1);
2855 if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2857 dx+=surface.offset.x;
2858 dy+=surface.offset.y;
2860 if(lfbSurface.bitmap.picture)
2862 AlphaWriteMode alphaWrite = surface.alphaWrite;
2863 if(src.alphaBlend && surface.blend)
2865 uint adddest = lfbSurface.bitmap.stride, addsource = src.stride;
2866 ColorAlpha * source = ((ColorAlpha *) src.picture) + sy * addsource + sx;
2867 ColorAlpha * dest = ((ColorAlpha *) lfbSurface.bitmap.picture) + dy * adddest + dx;
2868 float scaleX = (float)sw / w;
2869 float scaleY = (float)sh / h;
2877 if (w > sw && h > sh)
2880 for (y = 0; y < h; y++)
2882 int y0 = y * sh / h;
2883 int y1 = Min(y0 + 1, sh - 1);
2884 float alpha = y * scaleY - y0;
2886 for(x = 0; x < w; x++, dest += 1)
2888 int x0 = x * sw / w;
2889 int x1 = Min(x0 + 1, sw - 1);
2890 float beta = x * scaleX - x0;
2891 ColorAlpha src00, src01, src10, src11;
2892 float a1,r1,g1,b1,a2,r2,g2,b2;
2894 src00 = source[y0 * src.stride + x0];
2895 src01 = source[y0 * src.stride + x1];
2896 src10 = source[y1 * src.stride + x0];
2897 src11 = source[y1 * src.stride + x1];
2898 a1 = (src00.a) * (1.0f - beta) + (src01.a) * beta;
2899 r1 = (src00.color.r) * (1.0f - beta) + (src01.color.r) * beta;
2900 g1 = (src00.color.g) * (1.0f - beta) + (src01.color.g) * beta;
2901 b1 = (src00.color.b) * (1.0f - beta) + (src01.color.b) * beta;
2902 a2 = (src10.a) * (1.0f - beta) + (src11.a) * beta;
2903 r2 = (src10.color.r) * (1.0f - beta) + (src11.color.r) * beta;
2904 g2 = (src10.color.g) * (1.0f - beta) + (src11.color.g) * beta;
2905 b2 = (src10.color.b) * (1.0f - beta) + (src11.color.b) * beta;
2906 a = a1 * (1.0f - alpha) + a2 * alpha;
2907 r = r1 * (1.0f - alpha) + r2 * alpha;
2908 g = g1 * (1.0f - alpha) + g2 * alpha;
2909 b = b1 * (1.0f - alpha) + b2 * alpha;
2911 ColorAlpha dst = *dest;
2912 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2913 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2914 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2915 if(cr > 255) cr = 255;
2916 if(cg > 255) cg = 255;
2917 if(cb > 255) cb = 255;
2918 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2920 if(alphaWrite == blend)
2922 int ca = (int)(a + ((255 - a) * dst.a / 255));
2923 if(ca > 255) ca = 255;
2936 for (y = 0; y < h; y++)
2938 int y0 = Min((int)((y + 1) * scaleY), sh - 1);
2939 int y1 = Min(y0 + 1, sh - 1);
2941 for (x = 0; x < w; x++, dest += 1)
2943 int x0 = Min((int)((x + 1) * scaleX), sw - 1);
2944 int x1 = Min(x0 + 1, sw - 1);
2945 float a = 0, r = 0, g = 0, b = 0;
2948 for (i = y0; i <= y1; i++)
2949 for (j = x0; j <= x1; j++)
2951 ColorAlpha pixel = source[i * src.stride + j];
2963 ColorAlpha dst = *dest;
2964 int cr = (int)(a * r / 255 + ((255 - a) * dst.color.r / 255));
2965 int cg = (int)(a * g / 255 + ((255 - a) * dst.color.g / 255));
2966 int cb = (int)(a * b / 255 + ((255 - a) * dst.color.b / 255));
2967 if(cr > 255) cr = 255;
2968 if(cg > 255) cg = 255;
2969 if(cb > 255) cb = 255;
2970 dest->color = { (byte)cr, (byte)cg, (byte)cb };
2971 if(alphaWrite == blend)
2973 int ca = (int)(a + ((255 - a) * dst.a / 255));
2974 if(ca > 255) ca = 255;
2985 else if(!src.paletteShades && src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2986 filters_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2987 // Fail back on Stretch
2988 else if(src.paletteShades)
2989 shades_stretch_table[lfbSurface.bitmap.pixelFormat][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2990 else if(src.pixelFormat == lfbSurface.bitmap.pixelFormat)
2991 stretches_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2992 else if(src.pixelFormat == pixelFormat8 && lfbSurface.bitmap.pixelFormat != pixelFormatText)
2993 stretches_8bit_table[lfbSurface.bitmap.pixelFormat][src.transparent][flip](src,lfbSurface.bitmap,dx,dy,sx,sy,w,h,sw,sh);
2997 void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
2999 Blit(display, surface, src, dx, dy, sx, sy, w, h);
3002 void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3004 Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
3007 void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3009 Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
3012 void UnloadFont(DisplaySystem displaySystem, Font font)
3016 #if !defined(ECERE_NOTRUETYPE)
3018 for(entry = 0; entry<MAX_FONT_LINK_ENTRIES; entry++)
3020 FontEntry fontEntry = font.fontEntries[entry];
3026 loadedFonts.Remove(fontEntry);
3036 Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
3038 void * result = null;
3040 #if !defined(ECERE_NOTRUETYPE)
3041 Font font = Font { };
3044 char fileName[MAX_LOCATION];
3045 bool fakeItalic = flags.italic;
3047 #if !defined(__WIN32__)
3050 const char * ecereFonts = getenv("ECERE_FONTS");
3051 if(!ecereFonts) ecereFonts = "<:ecere>";
3052 #if !defined(__WIN32__)
3054 char linkCfgPath[MAX_LOCATION];
3056 strcpy(linkCfgPath, ecereFonts);
3057 PathCat(linkCfgPath, "linking.cfg");
3058 linkCfg = FileOpen(linkCfgPath, read);
3061 strcpy(fileName, faceName);
3062 strcpy(font.faceName, faceName);
3064 font.displaySystem = displaySystem;
3066 if(!FileExists(fileName))
3068 strcpy(fileName, ecereFonts);
3069 PathCat(fileName, faceName);
3070 if(flags.bold && flags.italic) strcat(fileName, "bi");
3071 else if(flags.bold) strcat(fileName, "bd");
3072 else if(flags.italic) strcat(fileName, "i");
3073 strcat(fileName, ".ttf");
3077 if(flags.italic && !FileExists(fileName))
3079 strcpy(fileName, ecereFonts);
3080 PathCat(fileName, faceName);
3081 if(flags.bold) strcat(fileName, "bd");
3082 strcat(fileName, ".ttf");
3087 // Search in current working directory
3088 if(!FileExists(fileName))
3090 strcpy(fileName, faceName);
3091 if(flags.bold && flags.italic) strcat(fileName, "bi");
3092 else if(flags.bold) strcat(fileName, "bd");
3093 else if(flags.italic) strcat(fileName, "i");
3094 strcat(fileName, ".ttf");
3098 if(flags.italic && !FileExists(fileName))
3100 strcpy(fileName, faceName);
3101 if(flags.bold) strcat(fileName, "bd");
3102 strcat(fileName, ".ttf");
3108 #if defined(__WIN32__)
3109 if(!FileExists(fileName))
3111 FontData fontData = { { 0 } };
3112 LOGFONT logFont = { 0 };
3117 logFont.lfCharSet = DEFAULT_CHARSET;
3118 strcpy(logFont.lfFaceName, faceName);
3119 fontData.flags = flags;
3121 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3122 if(!fontData.fileName[0] && flags.bold)
3124 fontData.forgive = true;
3125 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3127 if(!fontData.fileName[0])
3130 fontData.flags.italic = false;
3131 EnumFontFamiliesEx(hdc, &logFont, (void *)MyFontProc, (LPARAM)&fontData, 0);
3135 if(fontData.fileName[0])
3137 GetWindowsDirectory(fileName, MAX_LOCATION);
3138 PathCat(fileName, "fonts");
3139 PathCat(fileName, fontData.fileName);
3143 #elif !defined(ECERE_NOFONTCONFIG)
3146 FcResult result = 0;
3147 FcPattern * pattern;
3148 FcPattern * matched;
3150 unichar testChar = 0;
3151 FcCharSet * charSet;
3153 fcConfig = FcInitLoadConfigAndFonts();
3155 charSet = FcCharSetCreate();
3157 if(!strcmpi(faceName, "Mangal"))
3163 FcCharSetAddChar(charSet, testChar);
3165 pattern = FcPatternBuild(null,
3166 //FC_SOURCE, FcTypeString, "freetype",
3167 FC_FAMILY, FcTypeString, faceName,
3168 //FC_SCALABLE, FcTypeBool, 1,
3169 FC_SIZE, FcTypeDouble, (double)size,
3170 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3171 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3172 testChar ? FC_CHARSET : 0,FcTypeCharSet, charSet,
3174 FcDefaultSubstitute(pattern);
3175 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3177 matched = FcFontMatch (0, pattern, &result);
3178 // printf("Locating %s\n", faceName);
3181 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3182 //printf("Fontconfig returned %s\n", family);
3184 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) /*&& !strcmpi(family, faceName)*/)
3187 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3188 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3189 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3190 strcpy(fileName, fileName2);
3191 // size = (float)fontSize;
3193 //printf("Matched to %s, %f\n", fileName, size);
3197 //printf("Could not find a match for %s, %f, %s %s (%d)\n", faceName, size, flags.bold ? "bold" : "", flags.italic ? "italic" : "", (int)result);
3199 if(pattern) FcPatternDestroy(pattern);
3200 if(matched) FcPatternDestroy(matched);
3201 if(charSet) FcCharSetDestroy(charSet);
3206 if(!FileExists(fileName))
3207 ChangeExtension(fileName, "otf", fileName);
3208 if(!FileExists(fileName))
3209 ChangeExtension(fileName, "ttc", fileName);
3211 //if(FileExists(fileName))
3214 char links[1024] = "";
3216 #if defined(__WIN32__)
3219 if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key) ||
3220 !RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\FontLink\\SystemLink",0,KEY_READ,&key))
3225 RegQueryValueEx(key, faceName, null, &type, (LPBYTE)links, &size);
3226 memset(links + size, 0, 1024 - size);
3234 while(linkCfg.GetLine(line, sizeof(line)))
3236 int len = strlen(faceName);
3237 if(line[0] == '[' && !strncasecmp(line + 1, faceName, len) && line[len + 1] == ']')
3239 while(linkCfg.GetLine(line, sizeof(line)))
3241 TrimLSpaces(line, line);
3242 if(!line[0] || line[0] == '[')
3245 memcpy(links + linksPos, line, len);
3247 links[linksPos] = 0;
3255 while(entry < MAX_FONT_LINK_ENTRIES)
3257 FontEntry fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3260 File file = FileOpen/*Buffered*/(fileName, read);
3263 FileSize fileSize = file.GetSize();
3264 FT_Open_Args args = { 0 };
3265 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3266 FT_Stream stream = new0 FT_StreamRec[1];
3269 FT_Init_FreeType( &ftLibrary );
3271 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3272 fontEntry.stream = stream;
3275 fontEntry.buffer = new byte[fileSize];
3276 file.Read(fontEntry.buffer, 1, fileSize);
3279 //args.num_params = 1;
3280 args.params = ¶m;
3282 stream->size = fileSize;
3283 stream->descriptor.pointer = file;
3284 stream->read = FT_stream_load;
3285 stream->close = FT_stream_close;
3287 args.flags = /*FT_OPEN_PATHNAME|*//*FT_OPEN_MEMORY|*/FT_OPEN_STREAM/*|FT_OPEN_PARAMS*/;
3288 args.stream = stream;
3289 //args.pathname = fileName;
3290 //args.memory_base = fontEntry.buffer;
3291 //args.memory_size = fileSize;
3293 // printf("Opening: %s\n", fileName);
3294 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3299 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3300 fontEntry.hbFont.klass = &hb_fontClass;
3301 fontEntry.hbFont.userData = fontEntry; //.face;
3304 loadedFonts.Add(fontEntry);
3309 // printf("Error opening font %s\n", fileName);
3318 FT_Vector pen = { 0, 0 };
3321 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3322 matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
3323 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3324 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3328 matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
3329 matrix.xy = (FT_Fixed)( 0.0 * 0x10000L );
3330 matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
3331 matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
3333 FT_Set_Transform(fontEntry.face, &matrix, &pen );
3334 FaceSetCharSize(fontEntry.face, size);
3335 font.height = (int)((fontEntry.face->size->metrics.height) >> 6); //* y_scale;
3336 // printf("Font height is %d\n", font.height);
3337 font.fakeItalic = fakeItalic;
3341 font.fontEntries[entry++] = fontEntry;
3348 char fontName[1024];
3349 if(!links[linksPos]) break;
3350 for(c = 0; (ch = links[linksPos + c]); c++)
3353 if(ch == ',') break;
3356 if(fontName[0] || ch == ',')
3358 #if defined(__WIN32__)
3359 GetWindowsDirectory(fileName, MAX_LOCATION);
3360 PathCat(fileName, "fonts");
3361 PathCat(fileName, fontName);
3362 #elif !defined(ECERE_NOFONTCONFIG)
3363 if(getenv("ECERE_FONTS"))
3365 strcpy(fileName, ecereFonts);
3366 PathCat(fileName, fontName);
3372 FcResult result = 0;
3373 FcPattern * pattern;
3374 FcPattern * matched;
3376 pattern = FcPatternBuild(null,
3377 //FC_SOURCE, FcTypeString, "freetype",
3378 //FC_SCALABLE, FcTypeBool, 1,
3379 FC_FAMILY, FcTypeString, links + linksPos + c + 1,
3380 FC_SIZE, FcTypeDouble, (double)size,
3381 FC_WEIGHT, FcTypeInteger, flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM /*FC_WEIGHT_LIGHT*/,
3382 FC_SLANT, FcTypeInteger, flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3384 FcDefaultSubstitute(pattern);
3385 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3387 //printf("Locating %s\n", links + linksPos + c + 1);
3388 matched = FcFontMatch (0, pattern, &result);
3391 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3392 // printf("Fontconfig returned %s\n", family);
3394 if(matched && (result == FcResultMatch /*|| result == FcResultNoId*/) &&
3395 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch /*&& !strcmpi(family, links + linksPos + c + 1)*/)
3398 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName2);
3399 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3400 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3401 strcpy(fileName, fileName2);
3402 //size = (float)fontSize;
3403 // printf("Matched to %s, %f\n", fileName, size);
3407 // 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);
3409 if(pattern) FcPatternDestroy(pattern);
3410 if(matched) FcPatternDestroy(matched);
3417 while(links[linksPos] && links[linksPos] != ',') linksPos++;
3424 UnloadFont(displaySystem, font);
3427 font.asciiPack.Render(font, 0, displaySystem);
3429 #if !defined(__WIN32__)
3437 #if !defined(ECERE_NOTRUETYPE)
3438 void ::ProcessString(Font font, DisplaySystem displaySystem, const byte * text, int len,
3439 void (* callback)(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap),
3440 Surface surface, Display display, int * x, int y)
3442 if(font && font.fontEntries && font.fontEntries[0])
3444 LFBSurface lfbSurface = surface ? surface.driverData : null;
3445 int previousGlyph = 0;
3446 FT_Face previousFace = 0;
3447 int c, nb, glyphIndex = 0;
3448 unichar lastPack = lfbSurface && lfbSurface.writingOutline ? -1 : 0;
3449 GlyphPack pack = font.asciiPack, outline = null;
3451 uint * glyphs = null;
3453 bool rightToLeft = false;
3454 int fontEntryNum = 0;
3455 int glyphScript = 0;
3456 FontEntry curFontEntry;
3457 GlyphInfo * lastGlyph = null;
3460 pack.bitmap.alphaBlend = true;
3462 for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
3466 if(numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)))
3468 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3469 rightToLeft ? glyphIndex-- : glyphIndex++;
3473 HB_Script curScript = HB_Script_Common;
3474 const byte * scriptStart = text + c;
3475 //unichar nonASCIIch = 0;
3478 unichar testChar = 0;
3479 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3480 const char * testLang = null;
3485 HB_Script script = HB_Script_Common;
3486 ch = UTF8GetChar((const char *)text + c, &nb);
3487 //if(ch > 127) nonASCIIch = ch;
3489 if(ch == 32 && curScript)
3496 for(a = c + 1; a < c + len; a++)
3504 unichar ahead = UTF8GetChar((const char *)text + a, &nb);
3505 if((ahead >= 0x590 && ahead <= 0x7C0) || (ahead >= 0xFB1D && ahead <= 0xFB4F) || (ahead >= 0xFB50 && ahead <= 0xFDFF))
3513 script = HB_Script_Common;
3514 else if(ch <= 0x11FF)
3518 case 0x300: script = HB_Script_Greek; break;
3519 case 0x400: script = HB_Script_Cyrillic; break;
3520 case 0x500: script = (ch < 0x530) ? HB_Script_Cyrillic : ((ch < 0x590) ? HB_Script_Armenian : HB_Script_Hebrew); break;
3521 case 0x600: script = HB_Script_Arabic; break;
3522 case 0x700: script = (ch < 0x750) ? HB_Script_Syriac : ((ch < 0x780) ? HB_Script_Arabic : ((ch < 0x7C0) ? HB_Script_Thaana : HB_Script_Common)); break;
3523 case 0x800: script = HB_Script_Common; break; // NO CHARACTERS ASSIGNED BETWEEN 0x7C0 and 0x8FF?
3524 case 0x900: script = (ch < 0x980) ? HB_Script_Devanagari : HB_Script_Bengali; break;
3525 case 0xA00: script = (ch < 0xA80) ? HB_Script_Gurmukhi : HB_Script_Gujarati; break;
3526 case 0xB00: script = (ch < 0xB80) ? HB_Script_Oriya : HB_Script_Tamil; break;
3527 case 0xC00: script = (ch < 0xC80) ? HB_Script_Telugu : HB_Script_Kannada; break;
3528 case 0xD00: script = (ch < 0xD80) ? HB_Script_Malayalam : HB_Script_Sinhala; break;
3529 case 0xE00: script = (ch < 0xE80) ? HB_Script_Thai : HB_Script_Lao; break;
3530 case 0xF00: script = HB_Script_Tibetan; break;
3531 case 0x1000: script = (ch < 0x10A0) ? HB_Script_Myanmar : HB_Script_Georgian; break;
3532 case 0x1100: script = HB_Script_Hangul; break;
3535 else if(ch >= 0x1F00 && ch <= 0x1FFF) script = HB_Script_Greek;
3536 else if((ch >= 0x2D00 && ch <= 0x2D2F) || (ch >= 0x3130 && ch <= 0x318F) || (ch >= 0xAC00 && ch <= 0xD7AF) || (ch >= 0xFFA0 && ch <= 0xFFDC))
3537 script = HB_Script_Hangul;
3538 else if(ch >= 0x1680 && ch <= 0x169F) script = HB_Script_Ogham;
3539 else if(ch >= 0x16A0 && ch <= 0x16FF) script = HB_Script_Runic;
3540 else if((ch >= 0x1780 && ch <= 0x17FF) || (ch >= 0x19E0 && ch <= 0x19FF)) script = HB_Script_Khmer;
3541 else if(ch >= 0x3040 && ch <= 0x309F) script = 60;
3542 else if(ch >= 0x3400 && ch <= 0x9FBF) script = 61;
3543 //else if(ch >= 0x4E00 && ch <= 0x9FBF) script = 61;
3544 else if(ch >= 0xFB13 && ch <= 0xFB17) script = HB_Script_Armenian;
3545 else if(ch >= 0xFB1D && ch <= 0xFB4F) script = HB_Script_Hebrew;
3546 else if(ch >= 0xFB50 && ch <= 0xFDFF) script = HB_Script_Arabic;
3549 if(!script || (script != curScript))
3557 if(!script || script > HB_ScriptCount) { c += nb; if(script > HB_ScriptCount) curScript = script; break; }
3558 if(!script) { c += nb; break; }
3565 if(curScript == HB_Script_Common || curScript > HB_ScriptCount)
3567 rightToLeft = false;
3569 theCurrentScript = 0;
3573 int len = c - (int)(scriptStart - text);
3574 int max = len * 2 + 1;
3575 if(max > utf16BufferSize)
3577 utf16 = renew utf16 uint16[max];
3578 utf16BufferSize = max;
3580 wc = UTF8toUTF16BufferLen((const char *)scriptStart, utf16, max, len);
3581 theCurrentScript = glyphScript = curScript;
3585 case HB_Script_Arabic: testChar = 0x621; /*testLang = "ar"; */
3586 //printf("Arabic ");
3588 case HB_Script_Devanagari: testChar = 0x905;
3589 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3592 //printf("Devanagari ");
3594 case HB_Script_Hebrew: testChar = 0x05EA /*'ת'*/; /*testLang = "he"; */
3595 //printf("Hebrew ");
3598 testChar = (ch == '\t') ? ' ' : ch;
3600 case 60: testChar = 'あ'; break;
3601 case 61: testChar = 0x3400; break; //'愛'; break;
3607 // printf("Testing for char %x\n", testChar);
3608 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3610 if(font.fontEntries[fontEntryNum] && FT_Get_Char_Index(font.fontEntries[fontEntryNum].face, testChar))
3612 /*if(font.fontEntries[fontEntryNum])
3613 printf("Not found in %s\n", (char *)font.fontEntries[fontEntryNum].key);*/
3617 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3619 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3621 double fontSize = font.size;
3622 FcResult result = 0;
3623 FcPattern * pattern;
3624 FcPattern * matched;
3625 FcCharSet * charSet;
3627 FontEntry fontEntry;
3628 char * fileName = null;
3629 for(fontEntryNum = 0; fontEntryNum<MAX_FONT_LINK_ENTRIES; fontEntryNum++)
3630 if(!font.fontEntries[fontEntryNum])
3632 if(fontEntryNum == MAX_FONT_LINK_ENTRIES)
3636 #if !defined(__WIN32__) && !defined(ECERE_NOFONTCONFIG)
3638 charSet = FcCharSetCreate();
3639 FcCharSetAddChar(charSet, testChar);
3640 //printf("Loading with char %x\n", testChar);
3642 pattern = FcPatternBuild(null,
3643 //FC_SOURCE, FcTypeString, "freetype",
3644 //FC_SCALABLE, FcTypeBool, 1,
3645 FC_FAMILY, FcTypeString, font.faceName,
3646 FC_SIZE, FcTypeDouble, (double)font.size,
3647 FC_WEIGHT, FcTypeInteger, font.flags.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM,
3648 FC_SLANT, FcTypeInteger, font.flags.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN,
3649 FC_CHARSET,FcTypeCharSet, charSet,
3650 testLang ? FC_LANG : 0, FcTypeString,testLang,
3652 FcDefaultSubstitute(pattern);
3653 FcConfigSubstitute(fcConfig, pattern, FcMatchPattern); //FcMatchFont);
3655 //printf("Locating %s for script %d\n", font.faceName, curScript);
3656 matched = FcFontMatch (0, pattern, &result);
3659 FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family);
3660 //printf("Fontconfig returned %s\n", family);
3662 if(matched && (result == FcResultMatch) && FcPatternGetString(matched, FC_FAMILY, 0, (FcChar8 **)&family) == FcResultMatch)
3664 FcPatternGetString (matched, FC_FILE, 0, (FcChar8 **)&fileName);
3665 FcPatternGetInteger(matched, FC_INDEX, 0, &fontID);
3666 FcPatternGetDouble(matched, FC_SIZE, 0, &fontSize);
3667 // printf("\nMatched to %s, %f\n", fileName, fontSize);
3671 //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);
3676 fontEntry = (FontEntry)loadedFonts.FindString(fileName);
3679 File file = FileOpen(fileName, read);
3682 FileSize fileSize = file.GetSize();
3683 FT_Open_Args args = { 0 };
3684 FT_Parameter param = { FT_PARAM_TAG_UNPATENTED_HINTING };
3685 FT_Stream stream = new0 FT_StreamRec[1];
3688 FT_Init_FreeType( &ftLibrary );
3690 fontEntry = FontEntry { key = (uintptr)CopyString(fileName) };
3691 fontEntry.stream = stream;
3693 //args.num_params = 1;
3694 args.params = ¶m;
3696 stream->size = fileSize;
3697 stream->descriptor.pointer = file;
3698 stream->read = FT_stream_load;
3699 stream->close = FT_stream_close;
3701 args.flags = FT_OPEN_STREAM;
3702 args.stream = stream;
3703 //args.pathname = fileName;
3704 //args.memory_base = fontEntry.buffer;
3705 //args.memory_size = fileSize;
3707 // printf("Opening: %s\n", fileName);
3708 FT_Open_Face( ftLibrary, &args, fontID, &fontEntry.face );
3713 fontEntry.hbFace = HB_NewFace(fontEntry.face, hb_getSFntTable);
3714 fontEntry.hbFont.klass = &hb_fontClass;
3715 fontEntry.hbFont.userData = fontEntry; //.face;
3718 loadedFonts.Add(fontEntry);
3723 // printf("Error opening font %s\n", fileName);
3729 FaceSetCharSize(fontEntry.face, font.size);
3731 font.fontEntries[fontEntryNum] = fontEntry;
3735 if(pattern) FcPatternDestroy(pattern);
3736 if(matched) FcPatternDestroy(matched);
3737 if(charSet) FcCharSetDestroy(charSet);
3740 if(curScript > HB_ScriptCount) curScript = HB_Script_Common;
3741 if(curScript != HB_Script_Common && curScript < HB_ScriptCount)
3743 font.fontEntries[fontEntryNum].font = font;
3744 glyphs = shaping(font.fontEntries[fontEntryNum], utf16, wc, curScript, &numGlyphs, &rightToLeft);
3748 glyphIndex = rightToLeft ? (numGlyphs - 1) : 0;
3749 glyphNo = glyphs[glyphIndex] | 0x80000000 | (glyphScript << 24);
3750 rightToLeft ? glyphIndex-- : glyphIndex++;
3754 curFontEntry = font.fontEntries[fontEntryNum];
3756 packNo = glyphNo & 0xFFFFFF80;
3758 if(packNo != lastPack)
3761 pack = font.asciiPack;
3764 pack = (GlyphPack)font.glyphPacks.Find((uintptr)packNo);
3767 pack = GlyphPack { key = (uintptr)packNo };
3768 font.glyphPacks.Add(pack);
3769 pack.Render(font, fontEntryNum, displaySystem);
3772 pack.bitmap.alphaBlend = true;
3774 #if !defined(ECERE_VANILLA)
3775 if(lfbSurface && lfbSurface.writingOutline)
3777 uint outlineNo = (((uint)surface.outline.size) << 16) | (uint16)(Min(surface.outline.fade, 257.0f) * 255);
3778 outline = (GlyphPack)pack.outlines.Find(outlineNo);
3781 outline = { key = outlineNo };
3782 pack.outlines.Add(outline);
3783 pack.RenderOutline(outline, font, displaySystem);
3790 int index = rightToLeft ? (glyphIndex + 1) : (glyphIndex-1);
3791 GlyphInfo * glyph = &(outline ? outline : pack).glyphs[glyphNo & 0x7F];
3793 int ax = (int)((numGlyphs ? shaper_item.advances[index] : glyph->ax) * glyph->scale);
3794 int offset = numGlyphs ? shaper_item.offsets[index].x : 0;
3795 int oy = 0;//numGlyphs ? shaper_item.offsets[index].y : 0;
3799 if(previousGlyph && curFontEntry.face == previousFace)
3801 FT_Vector delta = { 0, 0 };
3802 FT_Get_Kerning(curFontEntry.face, previousGlyph, glyph->glyphNo, FT_KERNING_UNFITTED, &delta );
3803 if(delta.x < 0) delta.x += (-delta.x) % 64;
3804 else if(delta.x) delta.x += 64 - (delta.x % 64);
3805 *x += delta.x * glyph->scale;
3808 FaceSetCharSize(curFontEntry.face, font.size);
3810 previousGlyph = glyph->glyphNo;
3811 previousFace = curFontEntry.face;
3814 callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, (outline ? outline : pack).bitmap);
3820 if(numGlyphs && (rightToLeft ? (glyphIndex < 0) : (glyphIndex == numGlyphs)))
3825 int w = (lastGlyph->w * lastGlyph->left) * (1 << 6);
3826 // Fix for advance != width + left (e.g. italic fonts)
3833 LFBSurface lfbSurface = surface.driverData;
3834 lfbSurface.xOffset = 0;
3839 void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3841 if(displaySystem && displaySystem.flags.text && len)
3846 *width = num * textCellW;
3848 if(height) *height = textCellH;
3850 else if(font && len)
3855 #if !defined(ECERE_NOTRUETYPE)
3856 ProcessString(font, displaySystem, (const byte *)text, len, null, null, null, &w, 0);
3858 //*width = (w + 64 - w % 64) >> 6;
3862 *height = font.height;
3866 if(width) *width = 0;
3867 if(height) *height = 0;
3871 #if !defined(ECERE_NOTRUETYPE)
3872 void ::OutputGlyph(Surface surface, Display display, int x, int y, GlyphInfo * glyph, Bitmap bitmap)
3874 surface.driver.Blit(display, surface, bitmap, x + glyph->left, y + glyph->top, glyph->x, glyph->y, glyph->w, glyph->h);
3878 void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3880 LFBSurface lfbSurface = surface.driverData;
3881 if(display && display.displaySystem.flags.text)
3883 LFBDisplay lfbDisplay = display.driverData;
3884 uint16 * coffset = (uint16 *)lfbDisplay.bitmap.picture;
3890 if(y > surface.box.bottom || y < surface.box.top)
3892 coffset += (y+surface.offset.y) * lfbSurface.bitmap.stride + x + surface.offset.x;
3893 for(c=0; (c<len && x < surface.box.left); c++, x++,coffset++);
3894 for(; (c<len && x <= surface.box.right); c++, x++,coffset++)
3896 if(surface.textOpacity)
3897 *coffset = (uint16) (lfbSurface.background|lfbSurface.foreground|text[c]);
3899 *coffset = (uint16) (((*coffset)&0xF000)|lfbSurface.foreground|text[c]);
3904 lfbSurface.writingText = true;
3905 #if !defined(ECERE_NOTRUETYPE)
3907 ProcessString(lfbSurface.font, surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y);
3909 lfbSurface.writingText = false;
3913 void TextFont(Display display, Surface surface, Font font)
3915 LFBSurface lfbSurface = surface.driverData;
3916 lfbSurface.font = font;
3919 void TextOpacity(Display display, Surface surface, bool opaque)
3924 void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3926 LFBSurface lfbSurface = surface.driverData;
3927 FontExtent(surface.displaySystem, lfbSurface.font, text, len, width, height);
3930 void DrawingChar(Display display, Surface surface, byte character)
3932 LFBSurface lfbSurface = surface.driverData;
3933 lfbSurface.drawingChar = character;
3936 void LineStipple(Display display, Surface surface, uint32 stipple)
3938 LFBSurface lfbSurface = surface.driverData;
3939 lfbSurface.stipple = (uint16)stipple;
3942 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
3943 void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3945 if(mesh.vertices && !mesh.flags.vertices)
3946 delete mesh.vertices;
3947 if(mesh.normals && !mesh.flags.normals)
3948 delete mesh.normals;
3949 if(mesh.texCoords && !mesh.flags.texCoords1)
3950 delete mesh.texCoords;
3953 bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3955 bool result = false;
3956 if(mesh.nVertices == nVertices)
3959 // Same number of vertices, adding features (Leaves the other features pointers alone)
3960 if(mesh.flags != flags)
3962 if(!mesh.flags.vertices && flags.vertices)
3964 if(flags.doubleVertices)
3966 mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3969 mesh.vertices = new Vector3Df[nVertices];
3971 if(!mesh.flags.normals && flags.normals)
3973 if(flags.doubleNormals)
3975 mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3978 mesh.normals = new Vector3Df[nVertices];
3980 if(!mesh.flags.texCoords1 && flags.texCoords1)
3981 mesh.texCoords = new Pointf[nVertices];
3982 if(!mesh.flags.colors && flags.colors)
3983 mesh.colors = new ColorRGBAf[nVertices];
3989 // New number of vertices, reallocate all current and new features
3990 flags |= mesh.flags;
3993 if(flags.doubleVertices)
3995 mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3998 mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
4002 if(flags.doubleNormals)
4004 mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
4007 mesh.normals = renew mesh.normals Vector3Df[nVertices];
4009 if(flags.texCoords1)
4010 mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
4012 mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
4017 bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures features)
4022 void FreeIndices(DisplaySystem displaySystem, uint16 * indices)
4027 uint16 * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
4029 return (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
4031 uint16 * LockIndices(DisplaySystem displaySystem, void * indices)