28#if defined IGRAPHICS_SKIA && !defined IGRAPHICS_NO_SKIA_SVG
33 #pragma warning( push )
34 #pragma warning( disable : 4244 )
35 #pragma warning( disable : 5030 )
37 #include "include/core/SkCanvas.h"
38 #include "include/core/SkStream.h"
39 #include "src/xml/SkDOM.h"
40 #pragma warning( pop )
47#if defined IGRAPHICS_NANOVG
48 #define BITMAP_DATA_TYPE int;
49#elif defined IGRAPHICS_SKIA
50 #pragma warning( push )
51 #pragma warning( disable : 4244 )
53 #include "SkSurface.h"
54 #pragma warning( pop )
58 sk_sp<SkImage> mImage;
59 sk_sp<SkSurface> mSurface;
61 #define BITMAP_DATA_TYPE SkiaDrawable*
62#elif defined IGRAPHICS_CANVAS
63 #include <emscripten.h>
64 #include <emscripten/val.h>
65 #define BITMAP_DATA_TYPE emscripten::val*
67 #define BITMAP_DATA_TYPE void*;
70#if defined OS_MAC || defined OS_IOS
71 #include <CoreText/CoreText.h>
72 #define FONT_DESCRIPTOR_TYPE CTFontDescriptorRef
75 #define FONT_DESCRIPTOR_TYPE HFONT
77 #define FONT_DESCRIPTOR_TYPE std::pair<WDL_String, WDL_String>*
83BEGIN_IGRAPHICS_NAMESPACE
84using BitmapData = BITMAP_DATA_TYPE;
85using FontDescriptor = FONT_DESCRIPTOR_TYPE;
86using RawBitmapData = WDL_TypedBuf<uint8_t>;
101 APIBitmap(BitmapData pBitmap,
int w,
int h,
float scale,
float drawScale)
106 , mDrawScale(drawScale)
128 void SetBitmap(BitmapData pBitmap,
int w,
int h,
float scale,
float drawScale)
134 mDrawScale = drawScale;
164 IFontInfo(
const void* data, uint32_t dataSize, uint32_t faceIdx)
165 : mData(reinterpret_cast<const unsigned char*>(data))
172 mHeadLocation = LocateTable(
"head");
173 mNameLocation = LocateTable(
"name");
174 mHheaLocation = LocateTable(
"hhea");
175 mFDscLocation = LocateTable(
"fdsc");
179 mUnitsPerEM = GetUInt16(mHeadLocation + 18);
180 mMacStyle = GetUInt16(mHeadLocation + 44);
181 mFamily = SearchFontString(1);
182 mStyle = SearchFontString(2);
183 mAscender = GetSInt16(mHheaLocation + 4);
184 mDescender = GetSInt16(mHheaLocation + 6);
185 mLineGap = GetSInt16(mHheaLocation + 8);
190 bool IsValid()
const {
return mData && mHeadLocation && mNameLocation && mHheaLocation; }
192 const WDL_String& GetFamily()
const {
return mFamily; }
193 const WDL_String& GetStyle()
const {
return mStyle; }
195 bool IsBold()
const {
return mMacStyle & (1 << 0); }
196 bool IsItalic()
const {
return mMacStyle & (1 << 1); }
197 bool IsUnderline()
const {
return mMacStyle & (1 << 2); }
198 bool IsOutline()
const {
return mMacStyle & (1 << 3); }
199 bool IsShadow()
const {
return mMacStyle & (1 << 4); }
200 bool IsCondensed()
const {
return mMacStyle & (1 << 5); }
201 bool IsExpanded()
const {
return mMacStyle & (1 << 6); }
203 double GetHeightEMRatio()
const {
return mUnitsPerEM /
static_cast<double>(mAscender - mDescender); }
205 uint16_t GetUnitsPerEM()
const {
return mUnitsPerEM; }
206 int16_t GetAscender()
const {
return mAscender; }
207 int16_t GetDescender()
const {
return mDescender; }
208 int16_t GetLineGap()
const {
return mLineGap; }
209 int16_t GetLineHeight()
const {
return (mAscender - mDescender) + mLineGap; }
213 enum class EStringID { Mac, Windows };
215 bool MatchTag(uint32_t loc,
const char* tag)
217 return mData[loc+0] == tag[0] && mData[loc+1] == tag[1] && mData[loc+2] == tag[2] && mData[loc+3] == tag[3];
220 uint32_t LocateTable(
const char *tag)
222 uint16_t numTables = GetUInt16(4);
224 for (uint16_t i = 0; i < numTables; ++i)
226 uint32_t tableLocation = 12 + (16 * i);
227 if (MatchTag(tableLocation, tag))
228 return GetUInt32(tableLocation + 8);
234 WDL_String SearchFontString(
int nameID)
236 WDL_String str = GetFontString(nameID, EStringID::Windows);
241 return GetFontString(nameID, EStringID::Mac);
244 WDL_String GetFontString(
int nameID, EStringID stringID)
250 int languageID = 0x409;
260 case EStringID::Windows:
264 for (uint16_t i = 0; i < GetUInt16(mNameLocation + 2); ++i)
266 uint32_t loc = mNameLocation + 6 + (12 * i);
268 if (platformID == GetUInt16(loc + 0) && encodingID == GetUInt16(loc + 2)
269 && languageID == GetUInt16(loc + 4) && nameID == GetUInt16(loc + 6))
271 uint32_t stringLocation = GetUInt16(mNameLocation + 4) + GetUInt16(loc + 10);
272 uint16_t length = GetUInt16(loc + 8);
276 case EStringID::Windows:
278 WDL_TypedBuf<char> utf8;
279 WDL_TypedBuf<char16_t> utf16;
280 utf8.Resize((length * 3) / 2);
281 utf16.Resize(length /
sizeof(
char16_t));
283 for (
int j = 0; j < length; j++)
284 utf16.Get()[j] = GetUInt16(mNameLocation + stringLocation + j * 2);
286 std::codecvt_utf8_utf16<char16_t> conv;
290 memset(&mbs, 0,
sizeof(mbs));
291 conv.out(mbs, utf16.Get(), utf16.Get() + utf16.GetSize(), a, utf8.Get(), utf8.Get() + utf8.GetSize(), b);
293 return WDL_String(utf8.Get(), (
int) (b - utf8.Get()));
297 return WDL_String((
const char*)(mData + mNameLocation + stringLocation), length);
305 void FindFace(uint32_t faceIdx)
307 bool singleFont = IsSingleFont();
309 if (singleFont && faceIdx == 0 )
313 if (!singleFont && MatchTag(0,
"ttcf"))
316 if (GetUInt32(4) == 0x00010000 || GetUInt32(4) == 0x00020000)
318 if (faceIdx < GetSInt32(8))
320 mData += GetUInt32(12 + faceIdx * 4);
330 char TTV1[4] = {
'1', 0, 0, 0 };
331 char OTV1[4] = { 0, 1, 0, 0 };
334 if (MatchTag(0, TTV1))
return true;
335 if (MatchTag(0,
"typ1"))
return true;
336 if (MatchTag(0,
"OTTO"))
return true;
337 if (MatchTag(0, OTV1))
return true;
342#if defined WDL_LITTLE_ENDIAN
343 uint16_t GetUInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 0]) << 8) | (uint16_t)mData[loc + 1]; }
344 int16_t GetSInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 0]) << 8) | (uint16_t)mData[loc + 1]; }
345 uint32_t GetUInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 0)) << 16) | (uint32_t)GetUInt16(loc + 2); }
346 int32_t GetSInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 0)) << 16) | (uint32_t)GetUInt16(loc + 2); }
348 uint16_t GetUInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 1]) << 8) | (uint16_t)mData[loc + 0]; }
349 int16_t GetSInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 1]) << 8) | (uint16_t)mData[loc + 0]; }
350 uint32_t GetUInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 2)) << 16) | (uint32_t)GetUInt16(loc + 0); }
351 int32_t GetSInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 2)) << 16) | (uint32_t)GetUInt16(loc + 0); }
355 const unsigned char* mData;
357 uint32_t mHeadLocation = 0;
358 uint32_t mNameLocation = 0;
359 uint32_t mHheaLocation = 0;
360 uint32_t mFDscLocation = 0;
365 uint16_t mMacStyle = 0;
368 uint16_t mUnitsPerEM = 0;
369 int16_t mAscender = 0;
370 int16_t mDescender = 0;
371 int16_t mLineGap = 0;
375class IFontData :
public IFontInfo,
private WDL_TypedBuf<unsigned char>
378 IFontData() : IFontInfo(nullptr, 0, -1), mFaceIdx(-1) {}
380 IFontData(
const void* data,
int size,
int faceIdx) : IFontInfo(data, size, faceIdx), mFaceIdx(faceIdx)
382 const unsigned char* src =
reinterpret_cast<const unsigned char*
>(data);
383 unsigned char* dest = ResizeOK(size);
386 std::copy(src, src + size, dest);
389 IFontData(
int size) : IFontInfo(nullptr, 0, -1), mFaceIdx(-1)
394 void SetFaceIdx(
int faceIdx)
397 static_cast<IFontData&
>(*this) = IFontData(Get(), GetSize(), mFaceIdx);
400 bool IsValid()
const {
return GetSize() && mFaceIdx >= 0 && IFontInfo::IsValid(); }
402 unsigned char* Get() {
return WDL_TypedBuf<unsigned char>::Get(); }
403 int GetSize()
const {
return WDL_TypedBuf<unsigned char>::GetSize(); }
404 int GetFaceIdx()
const {
return mFaceIdx; }
411using IFontDataPtr = std::unique_ptr<IFontData>;
417 PlatformFont(
bool system) : mSystem(system) {}
418 virtual ~PlatformFont() {}
420 PlatformFont(
const PlatformFont&) =
delete;
421 PlatformFont& operator=(
const PlatformFont&) =
delete;
423 virtual FontDescriptor GetDescriptor() {
return nullptr; }
424 virtual IFontDataPtr GetFontData() {
return IFontDataPtr(
new IFontData()); }
425 bool IsSystem() {
return mSystem; }
428 int GetFaceIdx(
const void* data,
int dataSize,
const char* styleName)
430 for (
int idx = 0; ; idx++)
432 IFontInfo fontInfo(data, dataSize, idx);
434 if (!fontInfo.IsValid())
437 const WDL_String& style = fontInfo.GetStyle();
439 if (style.GetLength() && (!styleName[0] || !strcmp(style.Get(), styleName)))
447using PlatformFontPtr = std::unique_ptr<PlatformFont>;
452 SVGHolder(sk_sp<SkSVGDOM> svgDom)
462 SVGHolder(
const SVGHolder&) =
delete;
463 SVGHolder& operator=(
const SVGHolder&) =
delete;
465 sk_sp<SkSVGDOM> mSVGDom;
471 SVGHolder(NSVGimage* pImage)
484 SVGHolder(
const SVGHolder&) =
delete;
485 SVGHolder& operator=(
const SVGHolder&) =
delete;
487 NSVGimage* mImage =
nullptr;
497 class Accessor :
private WDL_MutexLock
500 Accessor(StaticStorage& storage)
501 : WDL_MutexLock(&storage.mMutex)
505 T* Find(
const char* str,
double scale = 1.) {
return mStorage.Find(str, scale); }
506 void Add(T* pData,
const char* str,
double scale = 1.) {
return mStorage.Add(pData, str, scale); }
507 void Remove(T* pData) {
return mStorage.Remove(pData); }
508 void Clear() {
return mStorage.Clear(); }
509 void Retain() {
return mStorage.Retain(); }
510 void Release() {
return mStorage.Release(); }
513 StaticStorage& mStorage;
523 StaticStorage(
const StaticStorage&) =
delete;
524 StaticStorage& operator=(
const StaticStorage&) =
delete;
534 std::unique_ptr<T> data;
540 size_t Hash(
const char* str)
542 std::string string(str);
543 return std::hash<std::string>()(string);
550 T* Find(
const char* str,
double scale = 1.)
552 WDL_String cacheName(str);
553 cacheName.AppendFormatted((
int) strlen(str) + 6,
"-%.1fx", scale);
555 size_t hashID = Hash(cacheName.Get());
557 int i, n = mDatas.GetSize();
558 for (i = 0; i < n; ++i)
560 DataKey* pKey = mDatas.Get(i);
563 if (pKey->hashID == hashID && scale == pKey->scale && !strcmp(str, pKey->name.Get()))
564 return pKey->data.get();
573 void Add(T* pData,
const char* str,
double scale = 1.)
575 DataKey* pKey = mDatas.Add(
new DataKey);
577 WDL_String cacheName(str);
578 cacheName.AppendFormatted((
int) strlen(str) + 6,
"-%.1fx", scale);
580 pKey->hashID = Hash(cacheName.Get());
581 pKey->data = std::unique_ptr<T>(pData);
589 void Remove(T* pData)
591 for (
int i = 0; i < mDatas.GetSize(); ++i)
593 if (mDatas.Get(i)->data.get() == pData)
595 mDatas.Delete(i,
true);
622 WDL_PtrList<DataKey> mDatas;
630 IVec2(
float x,
float y) : x(x), y(y) {}
636END_IGRAPHICS_NAMESPACE
A base class interface for a bitmap abstraction around the different drawing back end bitmap represen...
APIBitmap(BitmapData pBitmap, int w, int h, float scale, float drawScale)
APIBitmap constructor.
BitmapData GetBitmap() const
void SetBitmap(BitmapData pBitmap, int w, int h, float scale, float drawScale)
Used to initialise the members after construction.
float GetDrawScale() const
Encapsulate an xy point in one struct.