1. 程式人生 > >Skia簡介以及在Windows下編譯操作步驟

Skia簡介以及在Windows下編譯操作步驟

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

Skia是一個C++的開源2D向量圖形處理函式庫(Cairo是一個向量庫),包括字型、座標轉換、點陣圖等等,相當於輕量級的Cairo,目前主要用於Google的Android和Chrome平臺,Skia搭配OpenGL/ES與特定的硬體特徵,強化顯示的效果。另外,Skia是WebKit支援的眾多圖形平臺之一,在WebKit的GraphicsContext.h/.c中有相關實現。

Android與Chrome的原始碼庫中都有一份Skia的複製,因需求不同,做了部分的修改。

Skia需要的底層庫有:freetype2,expat,tinyxml。

可以用svn從Google下載原始碼:svncheckout http://skia.googlecode.com/svn

Skia的標頭檔案以及庫函式介面是以C++實現的。

程式碼結構,src目錄下:

(1)、animator目錄:用來實現Skia的動畫效果,Android不支援;

(2)、core目錄:Skia的核心,基本都是一些圖形繪製函式;

(3)、effects目錄:實現一些圖形影象的特效效果,包括遮罩、浮雕、模糊、濾鏡、漸變色、離散、透明等,並且實現了PATH的各種特效;

(4)gl目錄:實現了Skia的圖形庫,Skia呼叫OpenGL或OpenGL ES來實現一些簡單的3D效果;

(5)、images目錄:用來處理images的,支援常見影象的解碼、部分影象的編碼和動畫。Skia能處理的影象型別包括:BMP、JPEG/PVJPEG、PNG、ICO、SkMovie處理gif動畫;

(6)、ports目錄:是Skia的一些介面在不同系統上的實現,平臺相關的程式碼,比如字型、執行緒、時間等。這些與Skia的介面,需要針對不同的作業系統實現;

(7)、svg目錄:實現了Skia對向量圖SVG的支援,Android不支援;

(8)、utils目錄:一些輔助工具類;

(9)、views目錄:Skia構建了一套介面UI庫;

(10)、xml目錄:處理xml的資料,Skia在這裡只是對xml解析器做了一層包裝,具體的xml解析器的實現需要根據不同的作業系統及宿主程式來實現;

(11)、opts目錄:效能優化的程式碼;

(12)、pdf目錄:處理PDF文件,用了一個fpdfemb庫;

Skia主要使用的第三方庫:Zlib、Jpeglib、Pnglib、giflib、fpdfemb(處理pdf文件)。

Skia引擎在android原始碼當中的位置:(1)、標頭檔案:android/external/skia/include,其中還包含幾個子目錄:animotor,core,effects,images,views,…;(2)、原始檔位於:android/external/skia/src目錄,子目錄結構和標頭檔案目錄相同;(3)、封裝層:android對Skia引擎進行了封裝,以便讓java程式碼方便的呼叫,對Skia封裝的程式碼存在於android/framework/base/core/jni以及android/framework/base/core/jni/android/graphics目錄下面。在Android中Skia以擴充套件庫的形式存在,目錄為external/skia。

Skia本身是一個opensource的project,集成於android系統中。所以Skia不是android框架的一部分,不需要實現框架的api來支援Skia。不過Skia同樣可以掛接其它的第3方編碼解碼庫或者硬體編解碼庫。

Android版本不同,Skia版本也不太相同,介面有些細微的差別。

Skia主要包含三個庫:(1)、libcorecg.so:包含/skia/src/core的部分內容,比如其中的Region,Rect是在SurfaceFlinger裡面用來計算可視區域的;(2)、libsgl.so:包含/skia/src/core|effects|images|ports|utils的部分和全部內容,這個實現了skia大部分的圖形效果,以及圖形格式的編解碼;(3)、libskiagl.so:包含/skia/src/gl裡面的內容,主要用來呼叫opengl實現部分效果。

Skia對上層的介面:Skia的原始檔及部分標頭檔案都在external/skia/src目錄下,匯出的標頭檔案在external/skia/include目錄下。最主要的是SKCanvas類,幾乎整個AndroidGUI系統的底層繪製都是由這個類來完成的。SKCanvas類主要有三種繪製功能:(1)、基本圖形繪製(如drawARGB,drawLine函式);(2)、影象檔案繪製(如drawBitmap函式);(3)、文字繪製(drawText函式)。

Skia的影象編解碼部分:(1)、/include/image/SKImageDecoder.h:把影象檔案或者流解碼到skia的內部記憶體SKBitmap中;(2)、/include/image/SKImageEncoder.h :把skia內部記憶體SKBitmap編碼成檔案或流的形式。這些介面需要具體的類實現,主要程式碼在src/image檔案中。

Skia引擎重要類:(1)、SkCanvas:Skia引擎的一個核心類,它封裝了所有對裝置進行的畫圖操作.

Skia中用到的硬體加速技術:(1)、OpenGL/OpenGLES;(2)、SIMD:SSE2/SSSE3,NEON.

 

Skia在Windows下的編譯:

1、   從https://www.python.org/download/releases/2.7.8/下載python-2.7.8.amd64.msi並安裝;安裝到D:\ProgramFiles\Python27目錄下,並將D:\ProgramFiles\Python27新增到環境變數Path中,重啟電腦;

2、    從 https://cygwin.com/install.html 下載setup-x86_64.exe 並安裝;

3、   使用svn,下載gyp: http://gyp.googlecode.com/svn/trunk, 將整個gyp資料夾存放到/trunk_no_commit/third_party/externals資料夾下;

4、   在其它分支中將jsoncpp、jsoncpp-chromium、libjpeg、libwebp四個資料夾內容全部拷貝到/trunk_no_commit/third_party/externals資料夾下;

5、   開啟Cygwin,將其切換到Skia的trunk_no_commit目錄下,執行 python gyp_skia,會生成一個out資料夾,裡面有生成的skia.sln工程;

6、   如果在執行python gyp_skia命令過程中,提示/third_party/externals/libwebp/src/dec/frame.c 等檔案丟失,則從相關網站下載最新程式碼替換之即可。

7、   (1)、如果出現errorC2220:warning treated as error -no ‘object’ file generated,則將相應工程中的C/C++->General:Treat Warning As Errors,由原來的Level3(/W3)改為No(/WX-),如effects、gm工程;(2)、選中gm/verttext.cpp檔案->File->AdvancedSave Options->Encoding:由原來的Unicode(UTF-8 without signature)-Codepage 65001改為ChineseSimplified(GB2312)-Codepage 936;(3)、如果third_party/extternal中的第三方庫檔案編譯時與其它原始碼不匹配,可以通過改動gyp資料夾下的相應.gyp檔案來做相應的調整;

8、   通過svn http://skia.googlecode.com/svn下載所有相應的Skia原始碼,包括branchestrunk,下載後發現沒有trunk,只有trunk_no_commit

9、   開啟Cygwin,將其定位到trunk_no_commit資料夾,執行 python gyp_skia 命令,如果出現Warning: Missing input files相關資訊,說明缺少相關檔案,則根據提示查詢原因,否則在後期編譯時會報錯;

10、 正確執行完pythongyp_skia命令後,會在trunk_no_commit目錄下生成out資料夾,開啟裡面的skia.sln,編譯SampleApp工程,會生成SampleApp.exe和其它相應靜態庫。

11、仿照tests工程新建立一個TestSkia工程,工程設定及程式碼如下:

 (1)、Debug和Release下,Character Set:Use Unicode Character Set;

 (2)、C/C++ ->Additional Include Directories:

 

E:\Skia\code\google\trunk_no_commit\includeE:\Skia\code\google\trunk_no_commit\include\animatorE:\Skia\code\google\trunk_no_commit\include\configE:\Skia\code\google\trunk_no_commit\include\coreE:\Skia\code\google\trunk_no_commit\include\device\xpsE:\Skia\code\google\trunk_no_commit\include\effectsE:\Skia\code\google\trunk_no_commit\include\gpuE:\Skia\code\google\trunk_no_commit\include\gpu\glE:\Skia\code\google\trunk_no_commit\include\imagesE:\Skia\code\google\trunk_no_commit\include\pathopsE:\Skia\code\google\trunk_no_commit\include\pdfE:\Skia\code\google\trunk_no_commit\include\pipeE:\Skia\code\google\trunk_no_commit\include\portsE:\Skia\code\google\trunk_no_commit\include\recordE:\Skia\code\google\trunk_no_commit\include\svgE:\Skia\code\google\trunk_no_commit\include\textE:\Skia\code\google\trunk_no_commit\include\utilsE:\Skia\code\google\trunk_no_commit\include\utils\winE:\Skia\code\google\trunk_no_commit\include\viewsE:\Skia\code\google\trunk_no_commit\include\views\animatedE:\Skia\code\google\trunk_no_commit\include\xmlE:\Skia\code\google\trunk_no_commit\tools
 (3)、C/C++ -> Preprocessor: 

  Debug:

WIN32_DEBUG_CONSOLESK_INTERNALSK_GAMMA_SRGBSK_GAMMA_APPLY_TO_A8SK_SCALAR_TO_FLOAT_EXCLUDEDSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1SK_SUPPORT_GPU=1SK_SUPPORT_OPENCL=0SK_FORCE_DISTANCEFIELD_FONTS=0SK_SCALAR_IS_FLOATSK_CAN_USE_FLOATSK_BUILD_FOR_WIN32_CRT_SECURE_NO_WARNINGSGR_GL_FUNCTION_TYPE=__stdcallSK_BUILD_JSON_WRITERSK_SUPPORT_PDFSK_DEBUGSK_DEVELOPER=1

  Release:

WIN32NDEBUG_CONSOLESK_INTERNALSK_GAMMA_SRGBSK_GAMMA_APPLY_TO_A8SK_SCALAR_TO_FLOAT_EXCLUDEDSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1SK_SUPPORT_GPU=1SK_SUPPORT_OPENCL=0SK_FORCE_DISTANCEFIELD_FONTS=0SK_SCALAR_IS_FLOATSK_CAN_USE_FLOATSK_BUILD_FOR_WIN32_CRT_SECURE_NO_WARNINGSGR_GL_FUNCTION_TYPE=__stdcallSK_BUILD_JSON_WRITERSK_SUPPORT_PDFSK_RELEASE

 (4)、Linker -> Input -> Additional Dependencies:

OpenGL32.libusp10.libDelayImp.libwindowscodecs.lib

 (5)、將trunk_no_commit->tools->flags中的SkCommandLineFlags兩個檔案拷貝到此測試工程下並加入到工程中;

 (6)、stdafx.h:

#pragma once#include "targetver.h"#include <stdio.h>#include "SkCanvas.h"#include "SkData.h"#include "SkDocument.h"#include "SkForceLinking.h"#include "SkGraphics.h"#include "SkSurface.h"#include "SkImage.h"#include "SkStream.h"#include "SkString.h"#include "SkCommandLineFlags.h"

 (7)、stdafx.cpp:

#include "stdafx.h"// TODO: reference any additional headers you need in STDAFX.H// and not in this file#ifdef _DEBUG #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/experimental.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libetc1.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libjpeg.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_dec.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_dsp.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_enc.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/libwebp_utils.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/lua.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/skflate.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/lib/views_animated.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_animator.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_core.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_effects.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_images.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_opts.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_opts_ssse3.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_pdf.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_ports.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_sfnt.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_skgpu.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_skgputest.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_utils.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_views.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Debug/skia_xml.lib")#else #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/experimental.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libetc1.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libjpeg.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_dec.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_dsp.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_enc.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/libwebp_utils.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/lua.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/skflate.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/lib/views_animated.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_animator.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_core.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_effects.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_images.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_opts.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_opts_ssse3.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_pdf.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_ports.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_sfnt.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_skgpu.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_skgputest.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_utils.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_views.lib") #pragma comment(lib, "E:/Skia/code/google/trunk_no_commit/out/Release/skia_xml.lib")#endif

 (8)、TestSkia.cpp:

#include "stdafx.h"#include <iostream>using namespace std;__SK_FORCE_IMAGE_DECODER_LINKING;DEFINE_string2(outFile, o, "skhello", "The filename to write the image.");DEFINE_string2(text, t, "Hello", "The string to write.");static void doDraw(SkCanvas* canvas, const SkPaint& paint, const char text[]) { SkRect bounds; canvas->getClipBounds(&bounds); canvas->drawColor(SK_ColorWHITE); canvas->drawText(text, strlen(text), bounds.centerX(), bounds.centerY(), paint);}static bool do_surface(int w, int h, const char path[], const char text[], const SkPaint& paint) { SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(w, h)); doDraw(surface->getCanvas(), paint, text); SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); SkAutoDataUnref data(image->encode())if (NULL == data.get()) {  return false; } SkFILEWStream stream(path)return stream.write(data->data(), data->size());}static bool do_document(int w, int h, const char path[], const char text[], const SkPaint& paint) { SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(path)); if (doc.get()) {  SkScalar width = SkIntToScalar(w);  SkScalar height = SkIntToScalar(h);  doDraw(doc->beginPage(width, height, NULL), paint, text);  return true; } return false;}int tool_main(int argc, char** argv) { SkCommandLineFlags::SetUsage(""); SkCommandLineFlags::Parse(argc, argv); SkAutoGraphics ag; SkString path("skhello")SkString text("Hello")if (!FLAGS_outFile.isEmpty()) {  path.set(FLAGS_outFile[0]); } if (!FLAGS_text.isEmpty()) {  text.set(FLAGS_text[0]); } SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(30)); paint.setTextAlign(SkPaint::kCenter_Align); SkScalar width = paint.measureText(text.c_str(), text.size()); SkScalar spacing = paint.getFontSpacing(); int w = SkScalarRoundToInt(width) + 30int h = SkScalarRoundToInt(spacing) + 30static const struct {  bool (*fProc)(int w, int h, const char path[], const char text[],   const SkPaint&);  const char* fSuffix; } gRec[] = {  { do_surface, ".png" },  { do_document, ".pdf" }, }; for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {  SkString file;  file.printf("%s%s", path.c_str(), gRec[i].fSuffix);  if (!gRec[i].fProc(w, h, file.c_str(), text.c_str(), paint)) {   return -1;  } } return 0;}int main(int argc, char* argv[])int flag = tool_main(argc, (char**) argv); if (flag == 0)  cout<<"ok"<<endlelse   cout<<"error"<<endlreturn 0;}

執行此工程,會在此工程目錄下生成 skhello.pdf 和 skhello.png 兩個檔案,檔案內容為Hello


           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述 你好! 這是你第一次使用 **Markdown編輯器** 所展示的歡迎頁。如果你想學習如何使用Markdown編輯器, 可以仔細閱讀這篇文章,瞭解一下Markdown的基本語法知識。

新的改變

我們對Markdown編輯器進行了一些功能拓展與語法支援,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫部落格:

  1. 全新的介面設計 ,將會帶來全新的寫作體驗;
  2. 在創作中心設定你喜愛的程式碼高亮樣式,Markdown 將程式碼片顯示選擇的高亮樣式 進行展示;
  3. 增加了 圖片拖拽 功能,你可以將本地的圖片直接拖拽到編輯區域直接展示;
  4. 全新的 KaTeX數學公式 語法;
  5. 增加了支援甘特圖的mermaid語法1 功能;
  6. 增加了 多螢幕編輯 Markdown文章功能;
  7. 增加了 焦點寫作模式、預覽模式、簡潔寫作模式、左右區域同步滾輪設定 等功能,功能按鈕位於編輯區域與預覽區域中間;
  8. 增加了 檢查列表 功能。

功能快捷鍵

撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
檢查列表:Ctrl/Command + Shift + C
插入程式碼:Ctrl/Command + Shift + K
插入連結:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G

合理的建立標題,有助於目錄的生成

直接輸入1次#,並按下space後,將生成1級標題。
輸入2次#,並按下space後,將生成2級標題。
以此類推,我們支援6級標題。有助於使用TOC語法後生成一個完美的目錄。

如何改變文字的樣式

強調文字 強調文字

加粗文字 加粗文字

標記文字

刪除文字

引用文字

H2O is是液體。

210 運算結果是 1024.

插入連結與圖片

連結: link.

圖片: Alt

帶尺寸的圖片: Alt

當然,我們為了讓使用者更加便捷,我們增加了圖片拖拽功能。

如何插入一段漂亮的程式碼片

部落格設定頁面,選擇一款你喜歡的程式碼片高亮樣式,下面展示同樣高亮的 程式碼片.

// An highlighted block var foo = 'bar'; 

生成一個適合你的列表

  • 專案
    • 專案
      • 專案
  1. 專案1
  2. 專案2
  3. 專案3
  • 計劃任務
  • 完成任務

建立一個表格

一個簡單的表格是這麼建立的:

專案 Value
電腦 $1600
手機 $12
導管 $1

設定內容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文字居中 第二列文字居右 第三列文字居左

SmartyPants

SmartyPants將ASCII標點字元轉換為“智慧”印刷標點HTML實體。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

建立一個自定義列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何建立一個註腳

一個具有註腳的文字。2

註釋也是必不可少的

Markdown將文字轉換為 HTML

KaTeX數學公式

您可以使用渲染LaTeX數學表示式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n 1 ) ! n N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通過尤拉積分

Γ ( z ) = 0 t z 1 e t d t &ThinSpace; . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

你可以找到更多關於的資訊 LaTeX 數學表示式here.

新的甘特圖功能,豐富你的文章

gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section 現有任務
        已完成               :done,    des1, 2014-01-06,2014-01-08
        進行中               :active,  des2, 2014-01-09, 3d
        計劃一               :         des3, after des2, 5d
        計劃二               :         des4, after des3, 5d
  • 關於 甘特圖 語法,參考 這兒,

UML 圖表

可以使用UML圖表進行渲染。 Mermaid. 例如下面產生的一個序列圖::

這將產生一個流程圖。:

  • 關於 Mermaid 語法,參考 這兒,

FLowchart流程圖

我們依舊會支援flowchart的流程圖:

  • 關於 Flowchart流程圖 語法,參考 這兒.

匯出與匯入

匯出

如果你想嘗試使用此編輯器, 你可以在此篇文章任意編輯。當你完成了一篇文章的寫作, 在上方工具欄找到 文章匯出 ,生成一個.md檔案或者.html檔案進行本地儲存。

匯入

如果你想載入一篇你寫過的.md檔案或者.html檔案,在上方工具欄可以選擇匯入功能進行對應副檔名的檔案匯入,
繼續你的創作。


  1. mermaid語法說明 ↩︎

  2. 註腳的解釋 ↩︎