28#if defined IGRAPHICS_SKIA && !defined IGRAPHICS_NO_SKIA_SVG
33 #pragma warning( push )
34 #pragma warning( disable : 4244 )
35 #pragma warning( disable : 5030 )
36 #include "modules/svg/include/SkSVGDOM.h"
37 #include "include/core/SkCanvas.h"
38 #include "include/core/SkStream.h"
39 #include "src/xml/SkDOM.h"
40 #pragma warning( pop )
41 #pragma comment(lib, "svg.lib")
42 #pragma comment(lib, "skshaper.lib")
43 #pragma comment(lib, "skunicode_core.lib")
44 #pragma comment(lib, "skunicode_icu.lib")
51#if defined IGRAPHICS_NANOVG
52 #define BITMAP_DATA_TYPE int;
53#elif defined IGRAPHICS_SKIA
54 #pragma warning( push )
55 #pragma warning( disable : 4244 )
56 #include "include/core/SkImage.h"
57 #include "include/core/SkSurface.h"
58 #pragma warning( pop )
62 sk_sp<SkImage> mImage;
63 sk_sp<SkSurface> mSurface;
65 #define BITMAP_DATA_TYPE SkiaDrawable*
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<char16_t> utf16;
279 utf16.Resize(length /
sizeof(
char16_t));
281 for (
int j = 0; j < utf16.GetSize(); j++)
282 utf16.Get()[j] = GetUInt16(mNameLocation + stringLocation + j * 2);
285 std::string utf8Result;
286 for (
int i = 0; i < utf16.GetSize(); i++)
288 int ch = utf16.Get()[i];
290 if (ch >= 0xD800 && ch <= 0xDBFF && i + 1 < utf16.GetSize())
292 int low = utf16.Get()[i + 1];
293 if (low >= 0xDC00 && low <= 0xDFFF)
295 ch = 0x10000 + ((ch - 0xD800) << 10) + (low - 0xDC00);
300 int len = WDL_MakeUTFChar(buf, ch,
sizeof(buf));
301 utf8Result.append(buf, len);
303 return WDL_String(utf8Result.c_str());
307 return WDL_String((
const char*)(mData + mNameLocation + stringLocation), length);
315 void FindFace(uint32_t faceIdx)
317 bool singleFont = IsSingleFont();
319 if (singleFont && faceIdx == 0 )
323 if (!singleFont && MatchTag(0,
"ttcf"))
326 if (GetUInt32(4) == 0x00010000 || GetUInt32(4) == 0x00020000)
328 if (faceIdx < GetSInt32(8))
330 mData += GetUInt32(12 + faceIdx * 4);
340 char TTV1[4] = {
'1', 0, 0, 0 };
341 char OTV1[4] = { 0, 1, 0, 0 };
344 if (MatchTag(0, TTV1))
return true;
345 if (MatchTag(0,
"typ1"))
return true;
346 if (MatchTag(0,
"OTTO"))
return true;
347 if (MatchTag(0, OTV1))
return true;
352#if defined WDL_LITTLE_ENDIAN
353 uint16_t GetUInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 0]) << 8) | (uint16_t)mData[loc + 1]; }
354 int16_t GetSInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 0]) << 8) | (uint16_t)mData[loc + 1]; }
355 uint32_t GetUInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 0)) << 16) | (uint32_t)GetUInt16(loc + 2); }
356 int32_t GetSInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 0)) << 16) | (uint32_t)GetUInt16(loc + 2); }
358 uint16_t GetUInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 1]) << 8) | (uint16_t)mData[loc + 0]; }
359 int16_t GetSInt16(uint32_t loc) {
return (((uint16_t)mData[loc + 1]) << 8) | (uint16_t)mData[loc + 0]; }
360 uint32_t GetUInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 2)) << 16) | (uint32_t)GetUInt16(loc + 0); }
361 int32_t GetSInt32(uint32_t loc) {
return (((uint32_t)GetUInt16(loc + 2)) << 16) | (uint32_t)GetUInt16(loc + 0); }
365 const unsigned char* mData;
367 uint32_t mHeadLocation = 0;
368 uint32_t mNameLocation = 0;
369 uint32_t mHheaLocation = 0;
370 uint32_t mFDscLocation = 0;
375 uint16_t mMacStyle = 0;
378 uint16_t mUnitsPerEM = 0;
379 int16_t mAscender = 0;
380 int16_t mDescender = 0;
381 int16_t mLineGap = 0;
385class IFontData :
public IFontInfo,
private WDL_TypedBuf<unsigned char>
388 IFontData() : IFontInfo(nullptr, 0, -1), mFaceIdx(-1) {}
390 IFontData(
const void* data,
int size,
int faceIdx) : IFontInfo(data, size, faceIdx), mFaceIdx(faceIdx)
392 const unsigned char* src =
reinterpret_cast<const unsigned char*
>(data);
393 unsigned char* dest = ResizeOK(size);
396 std::copy(src, src + size, dest);
399 IFontData(
int size) : IFontInfo(nullptr, 0, -1), mFaceIdx(-1)
404 void SetFaceIdx(
int faceIdx)
407 static_cast<IFontData&
>(*this) = IFontData(Get(), GetSize(), mFaceIdx);
410 bool IsValid()
const {
return GetSize() && mFaceIdx >= 0 && IFontInfo::IsValid(); }
412 unsigned char* Get() {
return WDL_TypedBuf<unsigned char>::Get(); }
413 int GetSize()
const {
return WDL_TypedBuf<unsigned char>::GetSize(); }
414 int GetFaceIdx()
const {
return mFaceIdx; }
421using IFontDataPtr = std::unique_ptr<IFontData>;
427 PlatformFont(
bool system) : mSystem(system) {}
428 virtual ~PlatformFont() {}
430 PlatformFont(
const PlatformFont&) =
delete;
431 PlatformFont& operator=(
const PlatformFont&) =
delete;
433 virtual FontDescriptor GetDescriptor() {
return nullptr; }
434 virtual IFontDataPtr GetFontData() {
return IFontDataPtr(
new IFontData()); }
435 bool IsSystem() {
return mSystem; }
438 int GetFaceIdx(
const void* data,
int dataSize,
const char* styleName)
440 for (
int idx = 0; ; idx++)
442 IFontInfo fontInfo(data, dataSize, idx);
444 if (!fontInfo.IsValid())
447 const WDL_String& style = fontInfo.GetStyle();
449 if (style.GetLength() && (!styleName[0] || !strcmp(style.Get(), styleName)))
457using PlatformFontPtr = std::unique_ptr<PlatformFont>;
462 SVGHolder(sk_sp<SkSVGDOM> svgDom)
472 SVGHolder(
const SVGHolder&) =
delete;
473 SVGHolder& operator=(
const SVGHolder&) =
delete;
475 sk_sp<SkSVGDOM> mSVGDom;
481 SVGHolder(NSVGimage* pImage)
494 SVGHolder(
const SVGHolder&) =
delete;
495 SVGHolder& operator=(
const SVGHolder&) =
delete;
497 NSVGimage* mImage =
nullptr;
507 class Accessor :
private WDL_MutexLock
510 Accessor(StaticStorage& storage)
511 : WDL_MutexLock(&storage.mMutex)
515 T* Find(
const char* str,
double scale = 1.) {
return mStorage.Find(str, scale); }
516 void Add(T* pData,
const char* str,
double scale = 1.) {
return mStorage.Add(pData, str, scale); }
517 void Remove(T* pData) {
return mStorage.Remove(pData); }
518 void Clear() {
return mStorage.Clear(); }
519 void Retain() {
return mStorage.Retain(); }
520 void Release() {
return mStorage.Release(); }
523 StaticStorage& mStorage;
533 StaticStorage(
const StaticStorage&) =
delete;
534 StaticStorage& operator=(
const StaticStorage&) =
delete;
544 std::unique_ptr<T> data;
550 size_t Hash(
const char* str)
552 std::string string(str);
553 return std::hash<std::string>()(string);
560 T* Find(
const char* str,
double scale = 1.)
562 WDL_String cacheName(str);
563 cacheName.AppendFormatted((
int) strlen(str) + 6,
"-%.1fx", scale);
565 size_t hashID = Hash(cacheName.Get());
567 int i, n = mDatas.GetSize();
568 for (i = 0; i < n; ++i)
570 DataKey* pKey = mDatas.Get(i);
573 if (pKey->hashID == hashID && scale == pKey->scale && !strcmp(str, pKey->name.Get()))
574 return pKey->data.get();
583 void Add(T* pData,
const char* str,
double scale = 1.)
585 DataKey* pKey = mDatas.Add(
new DataKey);
587 WDL_String cacheName(str);
588 cacheName.AppendFormatted((
int) strlen(str) + 6,
"-%.1fx", scale);
590 pKey->hashID = Hash(cacheName.Get());
591 pKey->data = std::unique_ptr<T>(pData);
600 void Remove(T* pData)
602 for (
int i = 0; i < mDatas.GetSize(); ++i)
604 if (mDatas.Get(i)->data.get() == pData)
606 mDatas.Delete(i,
true);
633 WDL_PtrList<DataKey> mDatas;
641 IVec2(
float x,
float y) : x(x), y(y) {}
647END_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.