From 136b1e7456c54e1c990cf9aa232e70f7f023fccc Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Thu, 12 Jul 2018 17:56:49 +0200 Subject: [PATCH 1/3] Add sprite file option to force BMP encoding --- src/openrct2/CmdlineSprite.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/openrct2/CmdlineSprite.cpp b/src/openrct2/CmdlineSprite.cpp index fcc168a8ca..851949e811 100644 --- a/src/openrct2/CmdlineSprite.cpp +++ b/src/openrct2/CmdlineSprite.cpp @@ -246,12 +246,18 @@ static bool sprite_file_export(int32_t spriteIndex, const char *outPath) } } -static bool sprite_file_import(const char *path, int16_t x_offset, int16_t y_offset, bool keep_palette, rct_g1_element *outElement, uint8_t **outBuffer, int *outBufferLength, int32_t mode) +static bool sprite_file_import(const char *path, int16_t x_offset, int16_t y_offset, bool keep_palette, bool forceBmp, rct_g1_element *outElement, uint8_t **outBuffer, int *outBufferLength, int32_t mode) { try { auto format = IMAGE_FORMAT::PNG_32; - auto flags = ImageImporter::IMPORT_FLAGS::RLE; + auto flags = ImageImporter::IMPORT_FLAGS::NONE; + + if (!forceBmp) + { + flags = (ImageImporter::IMPORT_FLAGS)ImageImporter::IMPORT_FLAGS::RLE; + } + if (keep_palette) { format = IMAGE_FORMAT::PNG; @@ -464,7 +470,7 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc) uint8_t *buffer; int32_t bufferLength; - if (!sprite_file_import(imagePath, x_offset, y_offset, false, &spriteElement, &buffer, &bufferLength, gSpriteMode)) + if (!sprite_file_import(imagePath, x_offset, y_offset, false, false, &spriteElement, &buffer, &bufferLength, gSpriteMode)) return -1; if (!sprite_file_open(spriteFilePath)) { @@ -558,6 +564,14 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc) } } + // Get forcebmp option, if present + bool forceBmp = false; + json_t* forceBmpObject = json_object_get(sprite_description, "forceBmp"); + if (palette && json_is_boolean(forceBmpObject)) + { + forceBmp = json_boolean_value(forceBmpObject); + } + // Resolve absolute sprite path char *imagePath = platform_get_absolute_path(json_string_value(path), directoryPath); @@ -568,7 +582,7 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc) if (!sprite_file_import(imagePath, x_offset == nullptr ? 0 : json_integer_value(x_offset), y_offset == nullptr ? 0 : json_integer_value(y_offset), - keep_palette, &spriteElement, &buffer, &bufferLength, gSpriteMode)) + keep_palette, forceBmp, &spriteElement, &buffer, &bufferLength, gSpriteMode)) { fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath); json_decref(sprite_list); From c3ed52ffe9e99ac9129c684cbcda37e716121d02 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Fri, 20 Jul 2018 17:32:42 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Add=20sprite=20font=20glyphs=20for=20=C3=86?= =?UTF-8?q?=20and=20=C3=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/g2/font/ae-bold.png | Bin 0 -> 242 bytes resources/g2/font/ae-small.png | Bin 0 -> 185 bytes resources/g2/font/ae-tiny.png | Bin 0 -> 173 bytes resources/g2/font/ae-uc-bold.png | Bin 0 -> 205 bytes resources/g2/font/ae-uc-small.png | Bin 0 -> 194 bytes resources/g2/font/ae-uc-tiny.png | Bin 0 -> 171 bytes resources/g2/font/o-stroke-bold.png | Bin 0 -> 235 bytes resources/g2/font/o-stroke-small.png | Bin 0 -> 179 bytes resources/g2/font/o-stroke-tiny.png | Bin 0 -> 174 bytes resources/g2/font/o-stroke-uc-bold.png | Bin 0 -> 210 bytes resources/g2/font/o-stroke-uc-small.png | Bin 0 -> 195 bytes resources/g2/font/o-stroke-uc-tiny.png | Bin 0 -> 171 bytes resources/g2/sprites.json | 75 ++++++++++++++++++++++++ src/openrct2/sprites.h | 10 ++++ 14 files changed, 85 insertions(+) create mode 100644 resources/g2/font/ae-bold.png create mode 100644 resources/g2/font/ae-small.png create mode 100644 resources/g2/font/ae-tiny.png create mode 100644 resources/g2/font/ae-uc-bold.png create mode 100644 resources/g2/font/ae-uc-small.png create mode 100644 resources/g2/font/ae-uc-tiny.png create mode 100644 resources/g2/font/o-stroke-bold.png create mode 100644 resources/g2/font/o-stroke-small.png create mode 100644 resources/g2/font/o-stroke-tiny.png create mode 100644 resources/g2/font/o-stroke-uc-bold.png create mode 100644 resources/g2/font/o-stroke-uc-small.png create mode 100644 resources/g2/font/o-stroke-uc-tiny.png diff --git a/resources/g2/font/ae-bold.png b/resources/g2/font/ae-bold.png new file mode 100644 index 0000000000000000000000000000000000000000..79a5cc554c00b0f392ab8273b7c7961464bf4336 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^+(691!VDzuib?DSQv3lvA+8Jz%pDB>|1)$L8~+Ca zTdgWZpcG?CkY6x^!?PP{AWo9Ey9+}HtE>l*!&%@FSqwBx7=#%aX3dcR3bL1Y`ns|| zV&~yE5`7Ziq6QR_%?ybsan8@pP0cF-av2z$i&7IyQd1PlGfOfQ+&z5*QuI>Uf#SxV zE{-7_*JZm7@-irJ9MO`Vqod&CaOmIe&TrSZM9i}hxK*@a%4!2%*ByJ}e{WMe>l7|7 Xp2xu=8)~y)Kge89S3j3^P6_!@hljQC0!qCAg>jC6&7I;J!Gca%qgD@k*tT_@uLG}_)Usv`= z>^#B}#y+gmp96)|JY5_^IIbsOxRj7E!>YH@arHNb=ByWtZ9l*A@O*ZB^O}d}j~Nd` Y8xu#uA(s2^fI1jFUHx3vIVCg!06AGRrvLx| literal 0 HcmV?d00001 diff --git a/resources/g2/font/ae-tiny.png b/resources/g2/font/ae-tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..c90853e58f610f5529b4a218bf2bc68b27655056 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*#0(^xv&}Pr6i3p^r=85p>QL70(Y)*K0-AbW|YuPgf_ zb{=6FWz&03?LZ+ZPZ!4!j_b(}E+quaJ!fD(Cozw=`Bf=foiu~;Sr+GzQ@hRpRWW$F L`njxgN@xNA!-6en literal 0 HcmV?d00001 diff --git a/resources/g2/font/ae-uc-bold.png b/resources/g2/font/ae-uc-bold.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d1110ab17cd3e16255779de0fea7a54ded3725 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp@K+MI$3?%0sIQbn&@dx;XxH2#>cQE|_&(L9P{2vHx zwW<_>Qj8@*e!&b5&u*lFI7!~_E({&4vK~MVXMsm#F#`j)FbFd;%$g$s6l5>)^mS!_ z#LmU3Z0)tJb2?DS+|$J|gyXtt*KJM)1%bm&eg!2>#Y_u-zkl}gl)s{;0oMXoL&g7E rZ`R5#oL>6*o96uZRrB8pPmjO-p7n3U1JN@;BN#kg{an^LB{Ts5O5i^s literal 0 HcmV?d00001 diff --git a/resources/g2/font/ae-uc-small.png b/resources/g2/font/ae-uc-small.png new file mode 100644 index 0000000000000000000000000000000000000000..6250b063c32b5afab1533b3c6294ff5bcbc39f7e GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2hGm!icqpk;}cmjMvT>t<7-@)+zKSPJH@&A@6 zJ~yB^V@Z%-FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-JcqUD+S8 z^9ZXlzO(AP2^7-zba4#fxSpI4arM9fk*EU)D*rPy|Egtcvkc}p@aauYm{HGuVqQJN g3H=0v4fYHSOb2;SpM9nB4ycvE)78&qol`;+0AG$bY5)KL literal 0 HcmV?d00001 diff --git a/resources/g2/font/ae-uc-tiny.png b/resources/g2/font/ae-uc-tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3f73adf7cb3c78ca6a3897a40964802e5a4ff7 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^>>$j<3?z5j>~{cCJOMr-uK)l4?_l`?NMQuI!K4 zd4x5&uEt8l0)-?zT^vI=t|woJI$&VhmiUfc!_vI%;16a7zi;f1Uq8>;4phV7>FVdQ I&MBb@0GE#~tN;K2 literal 0 HcmV?d00001 diff --git a/resources/g2/font/o-stroke-bold.png b/resources/g2/font/o-stroke-bold.png new file mode 100644 index 0000000000000000000000000000000000000000..77280b6c91f3a250707cffa2306b13f61f1a0668 GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRM!VDyDK0eU~r1%4TLR=Xbm^&E$|7YkhHvSI; zwpvw+Kq21s zKVs+N6g3E`IG6<#lFbZ>C~?lu%}vcK0dg4_oQqNuOHxx5$}>wc6x=<115)%-*@5CZ zo-U3d9M_W*5`vPF5)uMLLQE18giJ(OCLiK)2nvu;;YreNYLT2VvsY4r!Oe#0zw*Iv Q>p%v2y85}Sb4q9e02gXK2mk;8 literal 0 HcmV?d00001 diff --git a/resources/g2/font/o-stroke-small.png b/resources/g2/font/o-stroke-small.png new file mode 100644 index 0000000000000000000000000000000000000000..31740371ce16142bfde90f41b31408cd62617aad GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^93afZ3?z3ZhDiV^o&cW^*Z=?jcQE|_&(L9P{J$lN z&kZQfSQ6wH%;50sMjD8dxG~48)W&wqyJzX3_IIbr@NJt1sPMA^MkobyGAoJXT1BV$H^iH!hZZ1o_2UN!3 M>FVdQ&MBb@0AD^X#{d8T literal 0 HcmV?d00001 diff --git a/resources/g2/font/o-stroke-uc-bold.png b/resources/g2/font/o-stroke-uc-bold.png new file mode 100644 index 0000000000000000000000000000000000000000..d19aca65cdb60784a4297579ef70b09088205984 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=%3?!FCJ6-`&`~f~8t_%#!9Sr~fGjtdm{|5qF zttv&J6k|z{UoeBivm0q3PLj8~3quF1tOt<8S>O>_%)r1c48n{Iv*t(u1=&kHeO=if zv2$^1@=ts_bp=q!#?!?ygyXtz&qYoK2M(vDvmK%yWHl}NTfY0%YnDn4C4*hL<$(?! w*%BvTEZC_LoAOuH(s{0;&Z=LJ-`r-tzMeH<-CwVnKyw&8UHx3vIVCg!0PCSZ6951J literal 0 HcmV?d00001 diff --git a/resources/g2/font/o-stroke-uc-small.png b/resources/g2/font/o-stroke-uc-small.png new file mode 100644 index 0000000000000000000000000000000000000000..2f412bf075fc3e3264a9d2eaa6574281295c4759 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CF#0(_=I)!I~1Oj|QT>t<7-@)+zKSPJH@&A@6 zJ~yB^V@Z%-FoVOh8)+a;lDE4HLkFv@2av;A;1OBOz`!jG!i)^F=12eq*-JcqUD+S8 z^9Y+Vdwu)61Sn+S>Eal|aXmTVLPA2qjAI86gzTQv__>CM`T1ogwsSw2*sl7s@_csY iH;{;7KXu!Hfnlo{=hdyhJAr01FnGH9xvX>$j<3?z5j>~{cCJOMr-uK)l4?_l`?NMQuI!K4 zc|?SHv+uhy0fi(yT^vI=t|vdpN(j(R2OV literal 0 HcmV?d00001 diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index 4aa9db09d1..1079216d19 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -439,5 +439,80 @@ "path": "icons/eyedropper.png", "x_offset": 5, "y_offset": 5 + }, + { + "path": "font/ae-uc-small.png", + "y_offset": 0, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/ae-small.png", + "y_offset": 2, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-uc-small.png", + "x_offset": -1, + "y_offset": 0, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-small.png", + "y_offset": 2, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/ae-uc-bold.png", + "y_offset": 0, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/ae-bold.png", + "y_offset": 2, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-uc-bold.png", + "x_offset": -1, + "y_offset": -1, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-bold.png", + "x_offset": 0, + "y_offset": 2, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/ae-uc-tiny.png", + "y_offset": 0, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/ae-tiny.png", + "y_offset": 1, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-uc-tiny.png", + "y_offset": 0, + "palette": "keep", + "forceBmp": true + }, + { + "path": "font/o-stroke-tiny.png", + "y_offset": 1, + "palette": "keep", + "forceBmp": true } ] diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index 9acec846ed..16111d66b5 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -840,6 +840,16 @@ enum { SPR_G2_EYEDROPPER = SPR_G2_BEGIN + 123, + SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 124, + + SPR_G2_AE_UPPER = SPR_G2_CHAR_BEGIN, + SPR_G2_AE_LOWER = SPR_G2_CHAR_BEGIN + 1, + SPR_G2_O_STROKE_UPPER = SPR_G2_CHAR_BEGIN + 2, + SPR_G2_O_STROKE_LOWER = SPR_G2_CHAR_BEGIN + 3, + + SPR_G2_CHAR_END = SPR_G2_O_STROKE_LOWER, + SPR_G2_GLYPH_COUNT = (SPR_G2_CHAR_END - SPR_G2_CHAR_BEGIN) + 1, + // 0x60000, chosen because it's a round hex number // of the last possible range of image ID values that is large enough to fit all csg1 sprites. SPR_CSG_BEGIN = 393216, From 5fdc4637cd357cd9333d9f2b11168275e6481f1e Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Fri, 20 Jul 2018 17:33:20 +0200 Subject: [PATCH 3/3] Add drawing code for new sprite glyphs --- src/openrct2/drawing/Font.cpp | 47 +++++++++++++++++++++++-- src/openrct2/drawing/ScrollingText.cpp | 29 +++++++++++++-- src/openrct2/localisation/FormatCodes.h | 8 +++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/openrct2/drawing/Font.cpp b/src/openrct2/drawing/Font.cpp index 708aab58fe..b7d206f6ae 100644 --- a/src/openrct2/drawing/Font.cpp +++ b/src/openrct2/drawing/Font.cpp @@ -19,6 +19,7 @@ static constexpr const int32_t SpriteFontLineHeight[FONT_SIZE_COUNT] = { 6, 10, 10 }; static uint8_t _spriteFontCharacterWidths[FONT_SIZE_COUNT][FONT_SPRITE_GLYPH_COUNT]; +static uint8_t _additionalSpriteFontCharacterWidth[FONT_SIZE_COUNT][SPR_G2_GLYPH_COUNT] = {}; #ifndef NO_TTF TTFFontSetDescriptor *gCurrentTTFFontSet; @@ -46,6 +47,22 @@ void font_sprite_initialise_characters() } } + for (uint8_t fontSize : { FONT_SIZE_SMALL, FONT_SIZE_MEDIUM, FONT_SIZE_TINY }) + { + int32_t glyphOffset = fontSize * SPR_G2_GLYPH_COUNT; + for (int32_t glyphIndex = 0; glyphIndex < SPR_G2_GLYPH_COUNT; glyphIndex++) + { + const rct_g1_element * g1 = gfx_get_g1_element(glyphIndex + SPR_G2_CHAR_BEGIN + glyphOffset); + int32_t width = 0; + if (g1 != nullptr) + { + width = g1->width + (2 * g1->x_offset) - 1; + } + + _additionalSpriteFontCharacterWidth[fontSize][glyphIndex] = (uint8_t)width; + } + } + scrolling_text_initialise_bitmaps(); } @@ -107,6 +124,15 @@ int32_t font_sprite_get_codepoint_offset(int32_t codepoint) // Render capital sharp-S (ẞ) with lowercase sprite (ß) case UNICODE_CAPITAL_SHARP_S: return 223 - 32; + case UNICODE_AE_UC: + return SPR_G2_AE_UPPER - SPR_CHAR_START; + case UNICODE_O_STROKE_UC: + return SPR_G2_O_STROKE_UPPER - SPR_CHAR_START; + case UNICODE_AE: + return SPR_G2_AE_LOWER - SPR_CHAR_START; + case UNICODE_O_STROKE: + return SPR_G2_O_STROKE_LOWER - SPR_CHAR_START; + case UNICODE_DINGBATS_PLUS: return 11; case UNICODE_DINGBATS_MINUS: return 13; @@ -126,7 +152,18 @@ int32_t font_sprite_get_codepoint_width(uint16_t fontSpriteBase, int32_t codepoi int32_t glyphIndex = font_sprite_get_codepoint_offset(codepoint); int32_t baseFontIndex = font_get_font_index_from_sprite_base(fontSpriteBase); - if (glyphIndex < 0 || glyphIndex >= (int32_t)FONT_SPRITE_GLYPH_COUNT) + if (glyphIndex >= FONT_SPRITE_GLYPH_COUNT) + { + glyphIndex = (SPR_CHAR_START + glyphIndex) - SPR_G2_CHAR_BEGIN; + + if (glyphIndex >= (int32_t)Util::CountOf(_additionalSpriteFontCharacterWidth[baseFontIndex])) + { + log_warning("Invalid glyph index %u", glyphIndex); + glyphIndex = 0; + } + return _additionalSpriteFontCharacterWidth[baseFontIndex][glyphIndex]; + } + else if (glyphIndex < 0 || glyphIndex >= (int32_t)FONT_SPRITE_GLYPH_COUNT) { log_warning("Invalid glyph index %u", glyphIndex); glyphIndex = 0; @@ -136,7 +173,13 @@ int32_t font_sprite_get_codepoint_width(uint16_t fontSpriteBase, int32_t codepoi int32_t font_sprite_get_codepoint_sprite(int32_t fontSpriteBase, int32_t codepoint) { - return SPR_CHAR_START + (IMAGE_TYPE_REMAP | (fontSpriteBase + font_sprite_get_codepoint_offset(codepoint))); + auto codePointOffset = font_sprite_get_codepoint_offset(codepoint); + if (codePointOffset > FONT_SPRITE_GLYPH_COUNT) + { + fontSpriteBase = font_get_font_index_from_sprite_base(fontSpriteBase) * SPR_G2_GLYPH_COUNT; + } + + return SPR_CHAR_START + (IMAGE_TYPE_REMAP | (fontSpriteBase + codePointOffset)); } int32_t font_get_font_index_from_sprite_base(uint16_t spriteBase) diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index 270c336268..b0974ff116 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -34,7 +34,7 @@ assert_struct_size(rct_draw_scroll_text, 0xA12); #define MAX_SCROLLING_TEXT_ENTRIES 32 static rct_draw_scroll_text _drawScrollTextList[MAX_SCROLLING_TEXT_ENTRIES]; -static uint8_t _characterBitmaps[FONT_SPRITE_GLYPH_COUNT][8]; +static uint8_t _characterBitmaps[FONT_SPRITE_GLYPH_COUNT + SPR_G2_GLYPH_COUNT][8]; static uint32_t _drawSCrollNextIndex = 0; static void scrolling_text_set_bitmap_for_sprite(utf8 *text, int32_t scroll, uint8_t *bitmap, const int16_t *scrollPositionOffsets); @@ -71,6 +71,23 @@ void scrolling_text_initialise_bitmaps() } } + for (int32_t i = 0; i < SPR_G2_GLYPH_COUNT; i++) { + memset(drawingSurface, 0, sizeof(drawingSurface)); + gfx_draw_sprite_software(&dpi, SPR_G2_CHAR_BEGIN + (FONT_SIZE_TINY * SPR_G2_GLYPH_COUNT) + i, -1, 0, 0); + + for (int32_t x = 0; x < 8; x++) { + uint8_t val = 0; + for (int32_t y = 0; y < 8; y++) { + val >>= 1; + uint8_t pixel = dpi.bits[x + y * 8]; + if (pixel == 1 || (gTinyFontAntiAliased && pixel == 2)) { + val |= 0x80; + } + } + _characterBitmaps[FONT_SPRITE_GLYPH_COUNT + i][x] = val; + } + } + for (int32_t i = 0; i < MAX_SCROLLING_TEXT_ENTRIES; i++) { int32_t imageId = SPR_SCROLLING_TEXT_START + i; @@ -94,7 +111,15 @@ void scrolling_text_initialise_bitmaps() static uint8_t *font_sprite_get_codepoint_bitmap(int32_t codepoint) { - return _characterBitmaps[font_sprite_get_codepoint_offset(codepoint)]; + auto offset = font_sprite_get_codepoint_offset(codepoint); + if (offset >= FONT_SPRITE_GLYPH_COUNT) + { + return _characterBitmaps[offset - (SPR_G2_CHAR_BEGIN - SPR_CHAR_START) + FONT_SPRITE_GLYPH_COUNT]; + } + else + { + return _characterBitmaps[offset]; + } } diff --git a/src/openrct2/localisation/FormatCodes.h b/src/openrct2/localisation/FormatCodes.h index 8b785c56ea..96e113e45f 100644 --- a/src/openrct2/localisation/FormatCodes.h +++ b/src/openrct2/localisation/FormatCodes.h @@ -179,6 +179,14 @@ enum UnicodeGerman UNICODE_CAPITAL_SHARP_S = 0x1E9E, }; +enum UnicodeNorwegianDanish +{ + UNICODE_AE_UC = 198, + UNICODE_O_STROKE_UC = 216, + UNICODE_AE = 230, + UNICODE_O_STROKE = 248, +}; + enum UnicodeDingbats { UNICODE_DINGBATS_PLUS = 0x2795,