日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

woff字体图元结构剖析,自定义字体的制作与匹配和识别

發布時間:2023/12/14 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 woff字体图元结构剖析,自定义字体的制作与匹配和识别 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前面我在《2萬字硬核剖析網頁自定義字體解析》一文中,講解了通過圖像識別來解析自定義字體,但是圖像識別的缺點在于準確率并不能達到100%,還需要二次修改。

前面將字體的稱為點陣圖,其實根據TrueType字體實際采用的技術,稱為輪廓圖更為合適,所以本文所說的輪廓圖就是上篇的點陣圖。

由于目前幾個大廠的網站的自定義字體的輪廓圖都是那個固定的順序,所以上文只處理了所有字體文件輪廓圖順序都一致的情況,并沒有繼續深挖去處理輪廓圖順序出現隨機的情況。

本文就將針對未來自定義字體的輪廓圖順序出現隨機的情況進行處理。

具體處理思路就是,提取字體的圖元數據,包括控制點位置和標志位,轉成二進制字節進行唯一標識,與現有的已知的字符集進行映射。后續任何Unicode代碼點順序隨機和輪廓圖順序隨機的字體文件,都可以提取圖元數據轉換后進行唯一匹配從而解碼出唯一正確的字符。

不過上述思路還只是處理了輪廓圖順序隨機,其實還可以再變態點以多個基礎字形制作自定義字體取隨機,意味著每個字符的圖元數據都會發生較大變化,上面的匹配方法就會直接失效。此時便只能通過機器學習計算字符間的相似度,從而識別出圖元對應的真實字符。

文章目錄

    • 字體格式類型介紹
    • 如何生成自定義字體
    • woff字體的解析
      • 字體頭表(head表)
      • 字符到圖元索引的映射表(cmap表)
      • 圖元數據(glyf表)
      • 位置索引(loca表)
      • 最大需求表(maxp表)
      • 命名表(name)
      • 水平布局(hmtx)
    • 二進制匹配解析輪廓圖順序隨機的woff字體
    • 圖像識別解析字形隨機的woff字體
    • 總結

字體格式類型介紹

字體格式類型主要有幾個大分類:TrueType、Embedded Open Type 、OpenType、WOFF 、SVG。

TrueType

Windows和Mac系統最常用的字體格式,基于輪廓技術的數學模式來進行定義,比基于矢量的字體更容易處理,保證了屏幕與打印輸出的一致性。同時,這類字體和矢量字體一樣可以隨意縮放、旋轉而不必擔心會出現鋸齒。

EOT – Embedded Open Type (.eot):

微軟開發的嵌入式字體,允許OpenType字體用@font-face嵌入到網頁并下載至瀏覽器渲染,存儲在臨時安裝文件夾下。

OpenType (.otf)

微軟和Adobe共同開發的字體,微軟的IE瀏覽器全部采用這種字體,致力于替代TrueType字體。

WOFF – Web Open Font Format (.woff):

專門為了Web而設計的字體格式標準,實際上是對TrueType/OpenType等字體格式的封裝,每個字體文件中含有字體以及針對字體的元數據(Metadata),字體文件被壓縮,以便于網絡傳輸。

SVG (Scalable Vector Graphics) Fonts (.svg)

使用SVG技術來呈現字體,支持gzip壓縮格式。

在上次從css的@font-face提取出字體URL鏈接時,就包含了eot和woff兩種格式。鑒于woff字體更容易被分析,所以我們上次選擇了只下載woff字體格式,今天這篇文章也一樣。

字體格式轉換工具:

  • https://www.fontsquirrel.com/tools/webfont-generator
  • https://everythingfonts.com/

可以生成自定義字體的網站:

  • https://icomoon.io/app/#/select
  • http://fontello.com

如何生成自定義字體

先生成svg字體,再導入到自定義字體生成網站,再定義字體映射關系,最后導入字體即可。

由于https://everythingfonts.com/對文件較大的字體轉換需要收費,這里我使用https://www.fontsquirrel.com/tools/webfont-generator將系統自帶的arial.ttf字體文件轉換為svg字體:

下載并解壓得到一個arial-webfont.svg文件。

接下來打開https://icomoon.io/app/#/select,選擇需要被自定義的字符:

本例選擇了0-9作為被自定義的字符,然后點擊右下角 Generate Font 按鈕準備設置字符映射:

設置好映射關系后,點擊下載字體。

下載的壓縮包包含多種字體,解壓出其中的icomoon.woff字體文件。

用FontCreator字體設計工具打開后可以看到如下結果:

可以看到與我們前面在網站中自定義的映射一致。

woff字體的解析

首先,我們用python的fontTools庫讀取上次下載的字體文件:

from fontTools.ttLib import TTFontfont = TTFont("tagName.woff")

可以一次性將相關數據保存到本地:

font.saveXML("tagName.xml")

字體文件都包含了一個TableDirectory結構,保存了多張表,每個表保存了不同的信息。

TrueType字體中常見的表有:

英文表名中文表名詳細描述
head字體頭字體的全局信息
cmap字符代碼到圖元的映射把字符代碼映射為圖元索引
glyf圖元數據圖元輪廓定義以及網格調整指令
loca位置表索引把元索引轉換為圖元的位置
maxp最大需求表字體中所需內存分配情況的匯總數據
name命名表版權說明、字體名、字體族名、風格名等等
hmtx水平布局字體水平布局:上高、下高、行間距、最大前進寬度、最小左支撐、最小右支撐

字體頭表(head表)

字體頭表(head表)中包含了TrueType字體的全局信息,在c語言中的結構定義如下:

typedef sturct {Fixed Table;//x00010000 ro version 1.0Fixed fontRevision;//Set by font manufacturer.ULONG checkSumAdjustment;ULONG magicNumer; //Set to 0x5f0f3cf5USHORT flags;USHORT unitsPerEm; //Valid range is from 16 to 16384longDT created; //International date (8-byte field).longDT modified; //International date (8-byte field).FWord xMin; //For all glyph bounding boxes.FWord yMin; //For all glyph bounding boxes.FWord xMax; //For all glyph bounding boxes.FWord xMax; //For all glyph bounding boxes.USHORT macStyle;USHORT lowestRecPPEM; //Smallest readable size in pixels.SHORT fontDirctionHint;SHORT indexToLocFormat; //0 for short offsets ,1 for long.SHORT glyphDataFormat; //0 for current format. }Table_head;

上面各個字段定義基本都能直接在python中讀取,其中日期字段有created和modified,分別表示字體創建時間和字體最后修改時間,使用8個字節記錄從1904年1月1日午夜12:00開始的秒數。

獲取字體的創建時間和字體最后修改時間:

import datetime head = font['head'] base = datetime.datetime(1904, 1, 1, 0, 0, 0) create_time = base+datetime.timedelta(seconds=head.created) modifie_time = base+datetime.timedelta(seconds=head.modified) print(f"創建時間:{create_time},最后修改時間:{modifie_time}") 創建時間:2021-08-02 15:00:30,最后修改時間:2021-08-02 15:00:30

字體是針對一個被稱為em-square的參考網格設計的,字體中的圖元用網格中的坐標表示。em-squrare的大小決定字體的圖元被縮放的方式和質量。字體頭中保存了每個em-square的格數和能 包含所有圖元的邊界框。Em-square的有效值是從16到16384。

讀取每個em-square的格數和圖元邊界框范圍:

print(f"每個em-square的格數:{head.unitsPerEm},邊界框范圍x: {head.xMin} - {head.xMax},y: {head.yMin} - {head.yMax}") 每個em-square的格數:1000,邊界框范圍x: 0 - 1136,y: -112 - 833

字體頭表中的其他信息包括最小可讀像素大小、字體方向、在位置表中圖元索引的格式和圖元數據格式等:

head.lowestRecPPEM, head.fontDirectionHint, head.indexToLocFormat, head.glyphDataFormat (8, 2, 0, 0)

字符到圖元索引的映射表(cmap表)

字符到圖元索引的映射表(cmap表)定義了從不同代碼頁中的字符代碼到圖元索引的映射關系。cmap表包含幾個子表以支持不同的平臺和不同的字符編碼方案。cmap表在c語言中的定義較為復雜,不作展示。

在python中我們可以通過cmap表獲取字符代碼到圖元索引的映射關系:

cmap = font['cmap'] cmap.getBestCmap() {120: 'x',57360: 'unie010',57369: 'unie019',57370: 'unie01a',...63699: 'unif8d3',63718: 'unif8e6',63724: 'unif8ec'}

不過獲取這個關系也并沒有太大的意義,因為我們可以很輕松的進行相互轉換:

"uni"+chr(57360).encode("unicode_escape").decode()[2:]

就可以得到對應的unie010,反過來也可以:

char = 'unie010' ord(("\\u"+char[3:]).encode().decode("unicode_escape"))

即可得到57360。

當然fontTools本身也提供了反向獲取的API:

cmap.buildReversed() {'x': {120},'unie010': {57360},'unie019': {57369},'unie01a': {57370},...'unif8d3': {63699},'unif8e6': {63718},'unif8ec': {63724}}

圖元數據(glyf表)

圖元數據(glyf表)是我們所需要的字體核心信息,以序列形式保存了圖元數據,每個圖元以圖元頭(GlyphHeader)結構開始,在c語言中的定義為:

typedef struct { WORD numberOfContours; //contor number,negative if composite FWord xMin; //Minimum x for coordinate data. FWord yMin; //Minimum y for coordinate data. FWord xMax; //Maximum x for coordinate data. FWord yMax; //Maximum y for coordinate data. }GlyphHeader;

合成圖元由多個簡單圖元或合成圖元組成,簡單圖元的numberOfContours字段保存了當前圖元的輪廓線的數目。而合成圖元的numberOfContours字段為負值,表示需要基于組成該合成圖元的所有簡單圖元的輪廓線的數目計算得到。后四個字段記錄了圖元的邊界框。

簡單圖元的圖元描述信息緊跟在其GlyphHeader結構之后,c語言定義為:

USHORT endPtsOfContours[n]; //n=number of contours USHORT instructionlength; BYTE instruction[i]; //i = instructionlength BYTE flags[]; //variable size BYTE xCoordinates[]; //variable size BYTE yCoordinates[]; //variable size

包括所有輪廓線結束點的索引、圖元指令和一系列的控制點,每個控制點包括包括一個標志和xy軸坐標。

endPtsOfContours數組保存了每一條輪廓線終點的索引,通過該索引可以計算出每條輪廓線中點的數量。比如,endPtsOfContours[0]+1是第一條輪廓線上點的數量,endPtsOfContours[1]-endPtsOfContours[0]是第二條輪廓線上點的數量。

圖元的控制點保存在三個數組中:標志獲得組、x坐標數組和y坐標數組。為了節省存儲空間,圖元中保存的是相對坐標。第一個點的坐標是相對原點(0, 0)記錄的,隨后的點記錄和上一個點的坐標差值。標志數組保存了每個坐標的編碼信息以及其他一些信息。下面是標志中各個位的含義(c語言定義):

typedef enum {G_ONCURVE=0x01, // on curve ,off curveG_REPEAT=0x08, // next byte is flag repeat count G_XMASK=0x12, G_XADDBYTE=0x12, //X is positive byteG_XSUBBYTE=0x12, //X is negative byte G_XSAME=0x10, //X is sameG_XADDINT=0x00, //X is signed word G_YMASK=0x24,G_YADDBYTE=0x24, //Y is positive byte G_YSUBBYTE=0x04, //Y is negative byteG_YSAME=0x20, //Y is sameG_YADDINT=0x00, //Y is signed word };

在輪廓技術的數學模式中,一段三階的Bezier曲線由四個控制點定義:位于曲線上的起始點、兩個不在曲線上(off-curve)的控制點和一個曲線上的結束點。

字體中的圖元輪廓用二階Bezier曲線定義,有三個點:一個曲線上的點,一個曲線外的點和另一個曲線上的點。對于多個連續不在曲線上的點,會隱式加入一些點使其符合二階Bezier曲線曲線的定義。例如,on-off-off-on模式的四個點,會隱式加入一個點使之成為on-off-on-off-on的五個點。

G_ONCURVE位表示控制點是否在曲線上,設置G_REPEAT位表示標志數組的下一字節表示重復次數,當前標志被重復指定的次數。解碼圖元的描述需要兩次掃描起始點,然后再遍歷圖元定義中的每一個點進行轉換。

圖元指令具體細節比較復雜,主要是為了控制圖元輪廓從em-square到柵格網格的縮放過程,通過網格調整技術使縮放后的渲染不失真,而記錄控制值的一張表。

整體來說渲染圖元是一個非常復雜的算法,咱們不再繼續深究。


下面看看fontTools庫能夠讀取到的圖元數據,首先讀取glyf表:

glyf = font["glyf"]

我們以字符0為例進行演示,查看到該字體中數字0對應的代碼點為unif82e。

首先查看圖元頭信息:

glyph = glyf['unif82e'] print(f"輪廓線數目:{glyph.numberOfContours},邊界范圍:({glyph.xMin},{glyph.yMin})-({glyph.xMax},{glyph.yMax})") 輪廓線數目:2,邊界范圍:(0,-14)-(550,729)

前面已經提到,每個點記錄的是和上一個點的坐標差值,所以邊界范圍存在負數很好理解。

獲取每條輪廓線終點的索引:

glyph.endPtsOfContours [12, 25]

可以計算出兩條輪廓線點的數量:

num1 = glyph.endPtsOfContours[0]+1 num2 = glyph.endPtsOfContours[1]-glyph.endPtsOfContours[0] print(f"第一條輪廓線上點的數量為{num1},第二條輪廓線上點的數量為{num2}") 第一條輪廓線上點的數量為13,第二條輪廓線上點的數量為13

對于控制點數據中的標志,python的fontTools庫似乎只能讀取G_ONCURVE標志位,即是否存在于曲線上。

首先查看控制點的坐標coordinates:

glyph.coordinates GlyphCoordinates([(300, 728),(171, 729),(107, 615),(50, 519),(50, 195),(107, 99),(171, -14),(427, -14),(493, 99),(550, 195),(550, 519),(493, 615),(427, 729),(300, 658),(396, 658),(438, 555),(469, 483),(469, 233),(438, 159),(396, 57),(204, 57),(162, 159),(132, 233),(132, 483),(162, 555),(204, 658)])

可以借助numpy計算出偏移后的實際坐標:

coordinates = np.array(glyph.coordinates).cumsum(axis=0) print(coordinates.shape, coordinates.tolist()) (26, 2) [[300, 728], [471, 1457], [578, 2072], [628, 2591], [678, 2786], [785, 2885], [956, 2871], [1383, 2857], [1876, 2956], [2426, 3151], [2976, 3670], [3469, 4285], [3896, 5014], [4196, 5672], [4592, 6330], [5030, 6885], [5499, 7368], [5968, 7601], [6406, 7760], [6802, 7817], [7006, 7874], [7168, 8033], [7300, 8266], [7432, 8749], [7594, 9304], [7798, 9962]]

控制點是否存在于曲線上:

glyph.flags bytearray(b'\x01\x00\x01\x00\x00\x01\x00\x00\x01\x00\x00\x01\x00\x01\x00\x01\x00\x00\x01\x00\x00\x01\x00\x00\x01\x00')

可以用numpy橫向拼接,方便查看:

data = np.c_[coordinates, glyph.flags].astype("int16") print(data) [[ 300 728 1][ 471 1457 0][ 578 2072 1][ 628 2591 0][ 678 2786 0][ 785 2885 1][ 956 2871 0][1383 2857 0][1876 2956 1][2426 3151 0][2976 3670 0][3469 4285 1][3896 5014 0][4196 5672 1][4592 6330 0][5030 6885 1][5499 7368 0][5968 7601 0][6406 7760 1][6802 7817 0][7006 7874 0][7168 8033 1][7300 8266 0][7432 8749 0][7594 9304 1][7798 9962 0]]

對于連續不在曲線上的點都會自動添加隱式的點。

如何將這些控制點數據用最簡化的2進制的形式描述呢?

np.array(glyph.coordinates).astype("int16").tobytes()+glyph.flags b',\x01\xd8\x02\xab\x00\xd9\x02k\x00g\x022\x00\x07\x022\x00\xc3\x00k\x00c\x00\xab\x00\xf2\xff\xab\x01\xf2\xff\xed\x01c\x00&\x02\xc3\x00&\x02\x07\x02\xed\x01g\x02\xab\x01\xd9\x02,\x01\x92\x02\x8c\x01\x92\x02\xb6\x01+\x02\xd5\x01\xe3\x01\xd5\x01\xe9\x00\xb6\x01\x9f\x00\x8c\x019\x00\xcc\x009\x00\xa2\x00\x9f\x00\x84\x00\xe9\x00\x84\x00\xe3\x01\xa2\x00+\x02\xcc\x00\x92\x02\x01\x00\x01\x00\x00\x01\x00\x00\x01\x00\x00\x01\x00\x01\x00\x01\x00\x00\x01\x00\x00\x01\x00\x00\x01\x00'

位置索引(loca表)

前面在讀取glyf表中的圖元數據時就需要讀取loca表的圖元索引的偏移量。

位置索引表中保存了n+1個圖元數據表的索引,其中的n是保存在最大需求表中的圖元數量。最后一個額外的偏移量指向最后一個圖元的偏移量和當前圖元的偏移量間的差值得到的圖元長度。

python中能夠讀取到:

loca = font["loca"] loca.locations array('I', [0, 0, 24, 68, 168, 304, 364, 480, 612, 652, 824, 948, 1040, 1164, 1252, 1432, 1660, 1856, 1944, 2052, 2140, ...... 97488, 97624, 97776, 98036, 98180, 98320, 98480, 98676, 98832, 99020, 99308])

最大需求表(maxp表)

最大需求表的目的是告知字體柵格器(rasterizer)對內存的需求,以便 在出來字體前分配合適大小的內存。下面是maxp表的結構在c語言中的定義:

typedef struct { Fixed Version;//0x00010000 for version 1.0. USHORT numGlypha; //Number of glyphs in the font . USHORT maxPoints; //Max points in noncomposite glyph . RSHORT maxContours; //Max contours in noncomposite glyph. USHORT maxCompositePoints;//Max points in a composite glyph. USHORT maxCompositeContours; //Max contours in a composite glyph. USHORT maxZones;// 1 if not use the twilight zone [Z0],//or 2 if so use Z0;2 in most cases. USHORT max TwilightPoints ;/ Maximum points used in Z0. USHORT maxStorage; //Number of storage area locations. USHORT maxFunctionDefs; //Number of FDEFs. USHORT maxStackElements; //Number of depth. USHORT maxSizeOfInstructions; //Max byte count for glyph inst. USHORT maxComponentElements; //Max number top components refernced. USHORT maxComponentDepth; //Max levels of recursion. }Table_maxp;

numGlyphs字段保存了字體中圖元的總數,這決定了到位置表的圖元索引的數量,可以驗證圖元索引的有效性。maxPoints\maxCountors\maxCompositePoints maxCompositeContours這幾個字段說明了圖元定義的復雜度。

python中的讀取一下:

maxp = font["maxp"] maxp.numGlyphs, maxp.maxPoints, maxp.maxContours, maxp.maxCompositePoints, maxp.maxCompositeContours (603, 134, 11, 0, 0)

命名表(name)

包含版權說明、字體名、字體族名、風格名等,直接通過python查看:

for n in font["name"].names:print(repr(n), n)print(n.platformID, n.nameID, n.string)print("----------------") 1 0 b'\n Created by font-carrier\n ' ---------------- ...... 1 10 b'Generated by svg2ttf from Fontello project.' ---------------- 1 11 b'http://fontello.com' ---------------- 3 0 b'\x00\n\x00 \x00 \x00C\x00r\x00e\x00a\x00t\x00e\x00d\x00 \x00b\x00y\x00 \x00f\x00o\x00n\x00t\x00-\x00c\x00a\x00r\x00r\x00i\x00e\x00r\x00\n\x00 \x00 ' ......

截取了部分結果,可以看到該自定義字體通過fontello.com生成。

水平布局(hmtx)

Python查看字體的水平布局:

for code, width in hmtx.metrics.items():print(code, width) glyph00000 (1136, 0) x (100, 0) uniec3e (600, 0) ... unif82e (600, 0) unie7c5 (1000, 0) ... unif69c (1000, 0)

二進制匹配解析輪廓圖順序隨機的woff字體

有了前面的基礎,現在對于亂序了輪廓圖順序的woff字體,已經變得非常簡單。

我們使用上次下載的address.woff文件作為已知訓練集,然后將shopNum.woff字體文件的輪廓圖,進行一定的亂序處理,看看能否正確的提取出需要的文字。

首先使用FontCreator.exe打開shopNum.woff字體文件,然后修改輪廓圖順序。

最終在我一頓操作后,形成下面的順序:

再將字體導出為random.woff。

那么我們能否通過address.woff文件和已知字符列表作為訓練集,正確匹配出random.woff文件每個Unicode代碼點對應的字符呢?

首先讀取address.woff文件的每個圖元數據轉成二進制后和之前已經識別出來的字符列表建立映射關系:

from fontTools.ttLib import TTFont import numpy as npdef get_glyphBytes(glyph):coordinates = np.array(glyph.coordinates).astype("int16")return coordinates.tobytes()+glyph.flagsfont = TTFont("address.woff") glyf = font["glyf"]chars = ' `1234567890店中美家館小車大市公酒行國品發電金心業商司超生裝園場食有新限天面工服海華水房飾城樂汽香部利子老藝花專東肉菜學福飯人百餐茶務通味所山區門藥銀農龍停尚安廣鑫一容動南具源興鮮記時機烤文康信果陽理鍋寶達地兒衣特產西批坊州牛佳化五米修愛北養賣建材三會雞室紅站德王光名麗油院堂燒江社合星貨型村自科快便日民營和活童明器煙育賓精屋經居莊石順林爾縣手廳銷用好客火雅盛體旅之鞋辣作粉包樓校魚平彩上吧保永萬物教吃設醫正造豐健點湯網慶技斯洗料配匯木緣加麻聯衛川泰色世方寓風幼羊燙來高廠蘭阿貝皮全女拉成云維貿道術運都口博河瑞宏京際路祥青鎮廚培力惠連馬鴻鋼訓影甲助窗布富牌頭四多妝吉苑沙恒隆春干餅氏里二管誠制售嘉長軒雜副清計黃訊太鴨號街交與叉附近層旁對巷棟環省橋湖段鄉廈府鋪內側元購前幢濱處向座下澩鳳港開關景泉塘放昌線灣政步寧解白田町溪十八古雙勝本單同九迎第臺玉錦底后七斜期武嶺松角紀朝峰六振珠局崗洲橫邊濟井辦漢代臨弄團外塔楊鐵浦字年島陵原梅進榮友虹央桂沿事津凱蓮丁秀柳集紫旗張谷的是不了很還個也這我就在以可到錯沒去過感次要比覺看得說常真們但最喜哈么別位能較境非為歡然他挺著價那意種想出員兩推做排實分間甜度起滿給熱完格薦喝等其再幾只現朋候樣直而買于般豆量選奶打每評少算又因情找些份置適什蛋師氣你姐棒試總定啊足級整帶蝦如態且嘗主話強當更板知己無酸讓入啦式笑贊片醬差像提隊走嫩才剛午接重串回晚微周值費性桌拍跟塊調糕' glyphBytes2char = {} for code, char in zip(glyf.glyphOrder, chars):glyph = glyf[code]if not hasattr(glyph, 'coordinates'):continueglyphBytes2char[get_glyphBytes(glyph)] = char

有了映射關系,我們再開始嘗試匹配random.woff文件每個Unicode代碼點對應的字符:

font = TTFont("random.woff") glyf = font["glyf"]code2char = {} for code in glyf.glyphOrder:glyph = glyf[code]if not hasattr(glyph, 'coordinates'):continueglyphBytes = get_glyphBytes(glyph)if glyphBytes not in glyphBytes2char:print("不在資料庫的代碼點:", code)continuecode2char[code] = glyphBytes2char[glyphBytes] code2char

結果:

可以看到每一個代碼點都一一精準的匹配出正確的結果。

可以將上述過程封裝成類,方便以后隨時調用使用:

from fontTools.ttLib import TTFont import numpy as npclass FontMatch:"""用于字體圖元數據匹配的類"""@staticmethoddef get_glyphBytes(glyph):coordinates = np.array(glyph.coordinates).astype("int16")return coordinates.tobytes() + glyph.flagsdef __init__(self, sample_font="sample.woff", chars=None, dest_font=None):"""傳入已知輪廓圖順序的字體文件和真實字符作為訓練集,去匹配目標字體,后面能夠得到該目標字體映射字符對應的真實字符:param sample_font: 已知輪廓圖順序的字體文件:param chars: 該字體文件每個輪廓圖對應的真實字符:param dest_font: 要進行匹配的目標字體,可以后面再調用 load_dest_font 傳入"""sample_font = TTFont(sample_font)glyf = sample_font["glyf"]if chars is None:chars = ' `1234567890店中美家館小車大市公酒行國品發電金心業商司超生裝園場食有新限天面工服海華水房飾城樂汽香部利子老藝花專東肉菜學福飯人百餐茶務通味所山區門藥銀農龍停尚安廣鑫一容動南具源興鮮記時機烤文康信果陽理鍋寶達地兒衣特產西批坊州牛佳化五米修愛北養賣建材三會雞室紅站德王光名麗油院堂燒江社合星貨型村自科快便日民營和活童明器煙育賓精屋經居莊石順林爾縣手廳銷用好客火雅盛體旅之鞋辣作粉包樓校魚平彩上吧保永萬物教吃設醫正造豐健點湯網慶技斯洗料配匯木緣加麻聯衛川泰色世方寓風幼羊燙來高廠蘭阿貝皮全女拉成云維貿道術運都口博河瑞宏京際路祥青鎮廚培力惠連馬鴻鋼訓影甲助窗布富牌頭四多妝吉苑沙恒隆春干餅氏里二管誠制售嘉長軒雜副清計黃訊太鴨號街交與叉附近層旁對巷棟環省橋湖段鄉廈府鋪內側元購前幢濱處向座下澩鳳港開關景泉塘放昌線灣政步寧解白田町溪十八古雙勝本單同九迎第臺玉錦底后七斜期武嶺松角紀朝峰六振珠局崗洲橫邊濟井辦漢代臨弄團外塔楊鐵浦字年島陵原梅進榮友虹央桂沿事津凱蓮丁秀柳集紫旗張谷的是不了很還個也這我就在以可到錯沒去過感次要比覺看得說常真們但最喜哈么別位能較境非為歡然他挺著價那意種想出員兩推做排實分間甜度起滿給熱完格薦喝等其再幾只現朋候樣直而買于般豆量選奶打每評少算又因情找些份置適什蛋師氣你姐棒試總定啊足級整帶蝦如態且嘗主話強當更板知己無酸讓入啦式笑贊片醬差像提隊走嫩才剛午接重串回晚微周值費性桌拍跟塊調糕'glyphBytes2char = {}for code, char in zip(glyf.glyphOrder, chars):glyph = glyf[code]if not hasattr(glyph, 'coordinates'):continueglyphBytes2char[FontMatch.get_glyphBytes(glyph)] = charself.glyphBytes2char = glyphBytes2charsample_font.close()if dest_font is not None:self.load_dest_font(dest_font)def load_dest_font(self, dest_font):"""傳入要進行匹配的目標字體,之前已經傳入的目標字體會被覆蓋"""font = TTFont(dest_font)self.code2name = font.getBestCmap()self.glyf = font["glyf"]def getRealChar(self, char):code = ord(char)if code not in self.code2name:returnname = self.code2name[code]glyphBytes = FontMatch.get_glyphBytes(self.glyf[name])return self.glyphBytes2char.get(glyphBytes)

調用方式:下面的代碼將前面已經下載的任意一個字體文件重命名為sample.woff作為訓練集,random.woff是要處理的目標字體。對于任何給點的映射字符都可以匹配出正確結果:

from FontMatch import FontMatchfont = FontMatch(sample_font="sample.woff", dest_font="random.woff") print(font.getRealChar("\uEE9B")) '4'

對前面我們自行亂序后的自定義字體前面幾個字符批量匹配測試一下:

real_map = {'\uE0A7': '1', '\uEBF3': '2', '\uEE9B': '4', '\uE7E4': '3', '\uF5F8': '店', '\uE7A1': '中', '\uEF49': '7', '\uEEF7': '8', '\uF7E0': '9', '\uE633': '小', '\uE5DE': '車', '\uE67F': '6', '\uF2C3': '美', '\uF012': '家', '\uE0B8': '館', '\uE438': '5'} for char, real in real_map.items():r = font.getRealChar(char)print("真實結果與匹配結果:", real, "|", r) 真實結果與匹配結果: 1 | 1 真實結果與匹配結果: 2 | 2 真實結果與匹配結果: 4 | 4 真實結果與匹配結果: 3 | 3 真實結果與匹配結果: 店 | 店 真實結果與匹配結果: 中 | 中 真實結果與匹配結果: 7 | 7 真實結果與匹配結果: 8 | 8 真實結果與匹配結果: 9 | 9 真實結果與匹配結果: 小 | 小 真實結果與匹配結果: 車 | 車 真實結果與匹配結果: 6 | 6 真實結果與匹配結果: 美 | 美 真實結果與匹配結果: 家 | 家 真實結果與匹配結果: 館 | 館 真實結果與匹配結果: 5 | 5

一樣也是完全正確。

圖像識別解析字形隨機的woff字體

上述代碼解決了輪廓圖順序隨機的問題,但是假如字形也發生隨機怎么破呢?例如用10套基礎字體隨機生成自定義字體。那么之前的獲取到的圖元數據就無法直接匹配。

此時我們需要使用機器學習或深度學習相關的算法,或者能夠完成圖元數據渲染字體圖形的大佬可以直接使用邏輯算法完成。

自己嘗試了一些分類模型發現效果并不比圖像識別算法好,所以最終我們依然還是決定使用一開始采用的圖像識別來解決這個問題,優點是通用性強,但缺點是準確率再也無法達到100%。

前面下載的字體文件定義最常用的601個字符,這里我們也只對這601個字符進行測試。

首先,創建文字識別類:

from ddddocr import DdddOcr, npclass OCR(DdddOcr):def __init__(self):super().__init__()def ocr(self, image):image = np.array(image).astype(np.float32)image = np.expand_dims(image, axis=0) / 255.image = (image - 0.5) / 0.5ort_inputs = {'input1': np.array([image])}ort_outs = self._DdddOcr__ort_session.run(None, ort_inputs)result = []last_item = 0for item in ort_outs[0][0]:if item == 0 or item == last_item:continueresult.append(self._DdddOcr__charset[item])last_item = itemreturn ''.join(result)ocr = OCR()

定義需要被測試的正確字符:

chars = '1234567890店中美家館小車大市公酒行國品發電金心業商司超生裝園場食有新限天面工服海華水房飾城樂汽香部利子老藝花專東肉菜學福飯人百餐茶務通味所山區門藥銀農龍停尚安廣鑫一容動南具源興鮮記時機烤文康信果陽理鍋寶達地兒衣特產西批坊州牛佳化五米修愛北養賣建材三會雞室紅站德王光名麗油院堂燒江社合星貨型村自科快便日民營和活童明器煙育賓精屋經居莊石順林爾縣手廳銷用好客火雅盛體旅之鞋辣作粉包樓校魚平彩上吧保永萬物教吃設醫正造豐健點湯網慶技斯洗料配匯木緣加麻聯衛川泰色世方寓風幼羊燙來高廠蘭阿貝皮全女拉成云維貿道術運都口博河瑞宏京際路祥青鎮廚培力惠連馬鴻鋼訓影甲助窗布富牌頭四多妝吉苑沙恒隆春干餅氏里二管誠制售嘉長軒雜副清計黃訊太鴨號街交與叉附近層旁對巷棟環省橋湖段鄉廈府鋪內側元購前幢濱處向座下澩鳳港開關景泉塘放昌線灣政步寧解白田町溪十八古雙勝本單同九迎第臺玉錦底后七斜期武嶺松角紀朝峰六振珠局崗洲橫邊濟井辦漢代臨弄團外塔楊鐵浦字年島陵原梅進榮友虹央桂沿事津凱蓮丁秀柳集紫旗張谷的是不了很還個也這我就在以可到錯沒去過感次要比覺看得說常真們但最喜哈么別位能較境非為歡然他挺著價那意種想出員兩推做排實分間甜度起滿給熱完格薦喝等其再幾只現朋候樣直而買于般豆量選奶打每評少算又因情找些份置適什蛋師氣你姐棒試總定啊足級整帶蝦如態且嘗主話強當更板知己無酸讓入啦式笑贊片醬差像提隊走嫩才剛午接重串回晚微周值費性桌拍跟塊調糕'

先對系統自帶的微軟雅黑字體進行測試:

from PIL import ImageFont, Image, ImageDrawsize = 64 font = ImageFont.truetype("msyh.ttc", size-24) error = 0 for char in chars:im = Image.new(mode='L', size=(size, size), color=255)draw = ImageDraw.Draw(im=im)w, h = draw.textsize(char, font)o1, o2 = font.getoffset(char)fontx, fonty = (size-w-o1)/2, (size-h-o2)/2draw.text(xy=(fontx, fonty), text=char, fill=0, font=font)result = ocr.ocr(im)[0]if result != char:print("正確結果:", char, ",識別結果:", result)error += 1 print("識別錯誤的字符數量:", error) 正確結果: 二 ,識別結果: 一 正確結果: 澩 ,識別結果: 檗 正確結果: 昌 ,識別結果: 目 正確結果: 町 ,識別結果: 盯 正確結果: 丁 ,識別結果: j 正確結果: 入 ,識別結果: 人 識別錯誤的字符數量: 6

可以看到對該字體601字符的識別只存在6個錯誤,其他都正確。

再對之前下載的自定義字體進行測試:

from fontTools.ttLib import TTFontfont = TTFont("shopNum.woff") name2char = dict(zip(font.getGlyphOrder()[2:], chars))size = 64 imageFont = ImageFont.truetype("shopNum.woff", size-24) error = 0 for code, name in font.getBestCmap().items():if name not in name2char:continuechar = chr(code)real_char = name2char[name]im = Image.new(mode='L', size=(size, size), color=255)draw = ImageDraw.Draw(im=im)w, h = draw.textsize(char, imageFont)o1, o2 = imageFont.getoffset(char)fontx, fonty = (size-w-o1)/2, (size-h-o2)/2draw.text(xy=(fontx, fonty), text=char, fill=0, font=imageFont)result = ocr.ocr(im)[0]if result != real_char:print("正確結果:", real_char, "識別結果:", result)error += 1 print("識別錯誤的字符數量:", error) 正確結果: 町 識別結果: 盯 正確結果: 二 識別結果: 一 正確結果: 澩 識別結果: 嗅 識別錯誤的字符數量: 3

可以看到對該字體601字符的識別只存在3個錯誤,其他都正確。

那么對于任何一個未知的自定義字體,如何通過圖像識別技術知道真實字符是什么呢?

我們改造一下前面的ocr類,封裝一下:

from ddddocr import DdddOcr, np from PIL import ImageFont, Image, ImageDrawclass FontOCR(DdddOcr):def __init__(self, font_name, font_size=40):super().__init__()self.font = ImageFont.truetype(font_name, font_size)self.cache = {}self.im_cache = {}def ocr(self, image):image = np.array(image).astype(np.float32)image = np.expand_dims(image, axis=0) / 255.image = (image - 0.5) / 0.5ort_inputs = {'input1': np.array([image])}ort_outs = self._DdddOcr__ort_session.run(None, ort_inputs)for item in ort_outs[0][0]:if item == 0:continuereturn self._DdddOcr__charset[item]def ocrFontChar(self, char):if char in self.cache:return self.cache[char]im = self.getCharImage(char)return self.cache.setdefault(char, self.ocr(im))def getCharImage(self, char):if char in self.im_cache:return self.im_cache[char]im = Image.new(mode='L', size=(64, 64), color=255)draw = ImageDraw.Draw(im=im)w, h = draw.textsize(char, self.font)o1, o2 = self.font.getoffset(char)fontx, fonty = (64-w-o1)/2, (64-h-o2)/2draw.text(xy=(fontx, fonty), text=char, fill=0, font=self.font)return self.im_cache.setdefault(char, im)

調用方式:

fontocr = FontOCR("shopNum.woff") fontocr.getRealChar("\uF7F2") '讓'

于是可以通過以下代碼可以對自定義字體的全部unicode代碼點識別一遍:

from fontTools.ttLib import TTFontfont_name = "address.woff" fontocr = FontOCR(font_name) font = TTFont(font_name) for name, real_char in zip(font.getGlyphOrder(), chars):if not name.startswith("uni"):continuechar = f"\\u{name[3:]}".encode().decode("unicode_escape")ocr_char = fontocr.ocrFontChar(char)print(name, real_char, ocr_char) uniec3e 1 1 unif3fc 2 2 uniea1f 3 3 unie7f7 4 4 unie258 5 5 unif5aa 6 6 unif48c 7 7 unif088 8 8 unif588 9 9 unif82e 0 0 unie7c5 店 店 unie137 中 中 unie2cb 美 美 unif767 家 家 ...

可以看到這些數據都被正確的解析出來,至此我們就完成了對任意自定義字體的智能解析。

總結

今天,我首先演示了如何生成自定義字體,并對字體的格式結構進行了較為詳細的講解,順便演示如何通過python的fontools庫獲取相應的字體數據。

在上一篇文章中,我們通過二級緩存解決了cssURL和fontURL隨機以及Unicode代碼點順序點隨機的問題,本文進一步考慮針對自定義字體文件內部,輪廓圖甚至基礎字形也隨機怎么處理。

本文針對輪廓圖順序隨機,開發了FontMatch,傳入已知字體的輪廓圖順序,能處理任何針對該字體進行輪廓圖順序隨機的匹配,準確率能達到100%。

但針對字形也可能隨機的情況,中間個人進行了很多基礎研究,寫了很多算法,但最終都還不如圖像識別的效果更好。所以最終我封裝了一個基于圖像識別的OCR處理類,能夠針對任何自定義字體傳入輸入字符識別出相應的結果字符。目前測試的600個高頻字符,準確率達到98%以上,針對未來的不確定性,犧牲這一點準確率個人感覺也很值。

總結

以上是生活随笔為你收集整理的woff字体图元结构剖析,自定义字体的制作与匹配和识别的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

中文伊人 | 国产麻豆精品一区二区 | 国产999精品 | 亚洲激情综合 | 久久久久国产精品www | 97精品免费视频 | av电影在线观看完整版一区二区 | 波多野结衣一区三区 | 国产精品免费视频一区二区 | 国产精品精品视频 | 麻花豆传媒mv在线观看 | 中文字幕精品一区久久久久 | 波多野结衣一区三区 | 99精品一区二区 | 日韩三级一区 | 久久深夜| 国产资源网站 | 97人人看| 亚洲国内精品 | 亚洲精品在线视频网站 | 婷婷av综合| 国产精品18久久久久vr手机版特色 | 91精品国产乱码久久 | 久久精品一区二区三区中文字幕 | 亚洲激色| 婷婷综合影院 | 亚洲资源一区 | 在线观看福利网站 | av在线免费观看不卡 | 亚洲综合在线观看视频 | 国产三级视频在线 | 国产区网址| 成人日韩av | 五月宗合网 | 亚洲91中文字幕无线码三区 | 久久在视频| 热久久免费国产视频 | 在线小视频国产 | 美女免费网视频 | 美女在线黄 | 色国产在线 | 肉色欧美久久久久久久免费看 | 亚洲人人精品 | 成人av免费 | 国产成人精品一区二区 | 中文久草| 激情 亚洲 | 日韩欧美一区二区在线播放 | 欧美肥妇free| 蜜桃av久久久亚洲精品 | 日日操操| 成人性生交大片免费看中文网站 | 久久九九免费视频 | 免费99精品国产自在在线 | 午夜国产福利在线观看 | 精品一二三四在线 | 国产又黄又爽又猛视频日本 | 日韩高清免费电影 | 亚洲国产播放 | 国产成人在线免费观看 | www黄免费| 亚洲成人资源在线观看 | 中文字字幕在线 | 成人在线观看网址 | 国产精品久久久久久久久久久久午夜 | 日韩电影一区二区三区在线观看 | 亚洲一级片在线观看 | 在线成人中文字幕 | 一区二区在线电影 | 久久久久福利视频 | 国产精品免费久久久久影院仙踪林 | 欧美日韩中文在线视频 | 欧美另类成人 | 在线观看免费成人 | 亚洲一级黄色片 | 欧美大片aaa | 五月婷婷伊人网 | 天天操夜操 | 激情五月五月婷婷 | 欧美日韩有码 | 免费观看不卡av | 日韩高清一 | 国产91在线观看 | 亚洲 综合 国产 精品 | 久久有精品 | 99免费观看视频 | 一区在线播放 | 久久五月婷婷丁香 | 亚洲精品一区二区三区新线路 | 国产一区免费看 | 99精品视频一区 | 欧美激情片在线观看 | 在线观看视频黄 | 亚洲最大av | 欧美日韩在线观看一区二区三区 | 久久精品亚洲一区二区三区观看模式 | 国产精品粉嫩 | 99视频在线精品免费观看2 | 国产在线观看免费av | 久久久久久久看片 | 91精品视频在线看 | 亚洲九九影院 | 激情五月视频 | 五月婷色 | 国产一区在线视频播放 | 久久精品亚洲精品国产欧美 | 91成人精品观看 | 九九热99视频 | 国产亚洲精品久久久久动 | 91免费观看视频网站 | 欧美日韩调教 | 久久精品99| 国产69精品久久久久99 | 欧美精品久久久久性色 | 久久久国产影视 | 免费麻豆网站 | 国产精品久久久久永久免费观看 | 麻豆视频观看 | 伊香蕉大综综综合久久啪 | 国产精品18久久久久久不卡孕妇 | 新版资源中文在线观看 | 91在线精品一区二区 | 亚洲欧美视频在线观看 | 国产成人精品999在线观看 | 国产福利一区二区三区视频 | 综合伊人久久 | 人人澡人人添人人爽一区二区 | 国产一级高清 | 日韩在线二区 | 亚洲国产精品视频在线观看 | 中文字幕免 | 高清不卡一区二区三区 | 一本一本久久a久久精品综合 | 中文视频在线播放 | 国产在线精品一区二区 | www.五月天色| 在线观看一区二区精品 | 91成人久久 | 日韩免费一区二区三区 | 国产精品久久久久免费观看 | 天天射综合网站 | 999一区二区三区 | 色五婷婷| 丁香六月伊人 | 美女视频a美女大全免费下载蜜臀 | 免费成人av电影 | 456免费视频| 久章草在线观看 | 成人免费看电影 | 免费看成人 | 免费观看性生交大片3 | 在线一级片 | 玖玖在线播放 | 狠狠色噜噜狠狠狠狠2021天天 | av一级片网站 | www.日韩免费 | 免费在线观看黄 | 亚洲成色777777在线观看影院 | 麻豆视频在线免费看 | 亚洲成人免费在线 | 97国产一区二区 | 亚洲最大成人免费网站 | 亚洲精品久久久久久久不卡四虎 | 在线免费观看黄色av | 97在线视频免费播放 | 偷拍区另类综合在线 | 日韩影视大全 | 韩国av免费观看 | 国产视频综合在线 | 亚洲精品在线播放视频 | 中文字幕免费观看 | 久久在线免费观看视频 | 国产黄色成人 | 欧美激情视频久久 | 中文永久免费观看 | 亚洲人在线7777777精品 | 久久精品99国产精品酒店日本 | 成人免费视频网站 | 免费 在线 中文 日本 | 日韩在线观看影院 | aaawww| 91在线中字 | 黄色一级免费电影 | 人人插人人做 | 在线观看一区 | 日韩精品视频免费专区在线播放 | 国产又粗又硬又爽的视频 | 亚洲国产日韩欧美在线 | 亚洲国产中文字幕在线观看 | 国产小视频在线播放 | 久久久久久久久久影视 | 91亚洲永久精品 | av电影中文 | 成人av在线看 | 欧美日韩啪啪 | 成人免费看电影 | 最近高清中文字幕 | 婷婷精品国产一区二区三区日韩 | 懂色av一区二区三区蜜臀 | 久久人人爽人人片av | 一二区电影 | 欧美激情精品 | 亚洲精品小视频在线观看 | 国产特黄色片 | 成人在线一区二区 | 日韩欧美精品一区二区三区经典 | 五月婷婷综合激情 | 久久色在线观看 | 国产成人精品日本亚洲999 | 亚洲精品乱码久久久久久按摩 | 日韩一二三 | 中文字幕有码在线 | 日韩中文字幕免费在线播放 | 久草网视频在线观看 | 国产电影一区二区三区四区 | 深爱激情综合 | 国产综合精品久久 | 国产精品高清在线 | 久久开心激情 | 91亚洲精品国偷拍自产在线观看 | 亚洲人成人在线 | av中文在线观看 | 免费人成在线观看网站 | 91九色在线播放 | 亚洲视频在线播放 | 国产专区视频在线观看 | 国际精品久久 | 中文不卡视频在线 | 综合伊人av | 久久免费观看少妇a级毛片 久久久久成人免费 | 最新av中文字幕 | 日韩r级在线 | av一区二区三区在线 | 欧美国产视频在线 | 国产精品黄网站在线观看 | 999精品在线| 顶级bbw搡bbbb搡bbbb | 日本激情视频中文字幕 | 99婷婷| 国产精品一区二区三区在线看 | 日韩高清免费在线 | 日韩一二三区不卡 | 夜夜高潮夜夜爽国产伦精品 | 粉嫩高清一区二区三区 | 国产精品视频区 | 久久综合影院 | 国产第一页精品 | 亚洲黄色在线免费观看 | 欧美日韩视频 | 国内精品久久久久久中文字幕 | 亚洲精品影视在线观看 | 亚洲精品乱码久久久久久写真 | 99热精品国产一区二区在线观看 | 97超碰色| 日韩字幕 | 在线观看日韩 | 婷婷色中文字幕 | 欧美日韩国产页 | 黄色com| 日韩精品视频免费在线观看 | 日韩在线视频免费播放 | 伊人婷婷综合 | 日韩视频免费 | 又爽又黄在线观看 | 中文字幕国产一区 | 深爱激情综合网 | 日韩免费看片 | 中文字幕高清有码 | 国产精品99精品 | 婷婷久月| 粉嫩av一区二区三区免费 | 亚洲 欧美 变态 国产 另类 | 色99在线 | 免费欧美高清视频 | 在线看日韩av| 国产精品专区在线 | 国产高清免费av | 欧美精彩视频 | 2019国产精品| 高清色免费 | 国产超碰在线 | 在线观看你懂的网站 | 91插插插免费视频 | 国产精品久久久视频 | 午夜免费电影院 | 狠狠色免费| 国产高清免费观看 | 免费在线观看黄色网 | 欧美日韩国产色综合一二三四 | 2021国产在线视频 | 在线观看视频你懂得 | 91精品国产91久久久久 | 欧美人人爱 | 福利久久久 | av天天干 | 久久久久久久久爱 | 亚洲欧美日韩一二三区 | 在线观看色网 | 国产一级精品绿帽视频 | 性色视频在线 | 成人国产电影在线观看 | 国模视频一区二区三区 | 亚洲最大激情中文字幕 | 日韩大片免费在线观看 | 精品久久久久久久久久久久久久久久 | 亚洲一级理论片 | 日本久久久亚洲精品 | 日韩在线视频网 | 国产群p视频 | 91在线观看欧美日韩 | 久久精品久久久久 | 日韩综合色 | 精品一区免费 | 九色视频自拍 | 在线午夜av | 999视频网站 | 久久久国产影院 | 日本精油按摩3 | 九九免费在线观看 | 久久成人精品电影 | 91在线视频在线观看 | 日韩丝袜在线观看 | 久久99深爱久久99精品 | 91精品国自产在线观看 | 色视频在线看 | 五月激情婷婷丁香 | 日本精品视频一区二区 | 啪嗒啪嗒免费观看完整版 | 欧美日韩在线精品 | 国产一级免费片 | 精品视频网站 | 三上悠亚一区二区在线观看 | 国产超碰97 | 免费观看国产精品视频 | 日韩一区二区三区高清免费看看 | 精品久久久久国产免费第一页 | 四虎伊人| 91精品在线免费观看 | 日韩av免费一区二区 | 伊人伊成久久人综合网站 | 又黄又刺激 | 日韩在线小视频 | 黄色网www| 视频一区久久 | 久久久久亚洲精品中文字幕 | 天堂在线一区二区 | 肉色欧美久久久久久久免费看 | 激情婷婷综合网 | 免费视频xnxx com| 免费观看成人 | 午夜国产福利在线 | 国产最新网站 | 成人9ⅰ免费影视网站 | 97网在线观看 | 日韩三级中文字幕 | 中文字幕精品www乱入免费视频 | 国产一区久久久 | 色干干 | 97在线超碰| 手机看片99 | 久久er99热精品一区二区 | www.av中文字幕.com | 成年人免费在线观看网站 | 精品国产乱码一区二 | 国产丝袜一区二区三区 | 国产精品专区一 | 久久精品3| 日本久久免费电影 | 欧美日韩国产xxx | 成人国产精品av | 伊人欧美| 天天射网 | 99久久精品国产一区二区成人 | 狠狠搞,com| 午夜美女网站 | 日韩经典一区二区三区 | 91亚色免费视频 | 超碰免费av | 黄在线| 久久8精品| 狠狠狠色丁香综合久久天下网 | 98涩涩国产露脸精品国产网 | 国产综合在线观看视频 | 午夜精品久久久久久久99 | 一区二区三区福利 | 亚洲电影图片小说 | 最近最新中文字幕视频 | 亚洲视频电影在线 | 国产精品国产三级国产不产一地 | 国产精品成人自产拍在线观看 | 天堂av在线中文在线 | 亚洲成人在线免费 | 久久五月婷婷丁香社区 | 国产精品av久久久久久无 | 精品视频在线免费 | 91成人在线观看高潮 | 又紧又大又爽精品一区二区 | 午夜精品久久久久久久久久 | 国产精品成人a免费观看 | 91九色蝌蚪视频在线 | 91色视频| 男女全黄一级一级高潮免费看 | 国产午夜三级一二三区 | 久久久久久久久久毛片 | 免费观看视频黄 | 在线观看视频国产 | 欧美一区二区三区在线看 | 97电院网手机版 | 国产69久久精品成人看 | 亚洲天天综合网 | 九九热精品国产 | 日韩在线视频观看 | 久久精品1区| 久久久精品亚洲 | 久久久www免费电影网 | 成年人免费观看在线视频 | 中文av在线免费观看 | 99在线观看视频网站 | 手机在线观看国产精品 | 在线看黄网站 | 97精品免费视频 | 人人插人人搞 | 久久乐九色婷婷综合色狠狠182 | 91av视频导航 | 久久国产热 | 中文字幕在线观看第一页 | 午夜免费福利视频 | 亚洲成人午夜在线 | 成人免费网站在线观看 | 久草免费新视频 | 亚洲视频免费在线观看 | 日日夜夜网 | 97热在线观看 | 中文字幕视频一区二区 | 亚洲人人av | 超碰免费97 | 99久久er热在这里只有精品66 | 国产精品igao视频网入口 | 97色婷婷人人爽人人 | 日本精品视频在线观看 | 国产精品久久久久久久久久尿 | 97超碰资源 | 五月婷婷爱 | 欧美激情操 | 日韩精品免费专区 | 久久激情视频免费观看 | 日本黄色大片免费 | 黄网在线免费观看 | 欧美成人h版 | 视频成人 | 国产人免费人成免费视频 | av品善网 | 欧美色久 | 国产电影一区二区三区四区 | 超碰在线资源 | 国产一区免费 | 天天干,天天射,天天操,天天摸 | 亚洲成a人片综合在线 | 在线黄色国产电影 | 国产69精品久久99不卡的观看体验 | 国产成人一级电影 | 黄色av免费看 | 91九色精品国产 | 成人黄色大片在线免费观看 | 亚洲视频在线观看免费 | 国产特级毛片aaaaaa毛片 | 色噜噜在线观看视频 | 五月天最新网址 | 成人禁用看黄a在线 | 成年人三级网站 | 中文字幕精品久久 | 激情六月婷婷久久 | 96看片| 国产精品99久久久久久有的能看 | 国产中的精品av小宝探花 | 国产亚洲精品久久久久久大师 | 国产视频在线免费观看 | 中文字幕在线观看完整版电影 | 色悠悠久久综合 | 亚洲性xxxx| 国产99久久久国产精品 | 人人舔人人 | 四川bbb搡bbb爽爽视频 | 欧美精品久久久久久久久免 | 国产一级做a爱片久久毛片a | 日本爱爱免费 | 国产精品情侣视频 | 国产高清无线码2021 | 精品一区二区三区香蕉蜜桃 | 欧美一级久久 | 中文字幕一区二区在线观看 | 成人一区二区三区在线 | 欧美污在线观看 | 亚洲艳情| 日黄网站| 久久久亚洲麻豆日韩精品一区三区 | 四虎影视8848aamm| 国产视频精品久久 | 国产精品人成电影在线观看 | 五月婷婷开心 | 在线看污网站 | 日日爱影视 | 日本中文字幕在线看 | 亚洲成人资源在线 | 午夜色站| 亚洲最新视频在线播放 | 久久精品影片 | 亚洲va欧洲va国产va不卡 | 97精品国产91久久久久久久 | 在线看国产日韩 | 婷婷色 亚洲 | 久久伊人八月婷婷综合激情 | 久久精品视频免费观看 | 高潮久久久久久久久 | 又黄又刺激的网站 | 深爱激情av | 麻豆小视频在线观看 | 国产成人精品午夜在线播放 | 91精品视频网站 | 99在线看 | 成人黄色在线 | 中午字幕在线观看 | 免费黄色特级片 | av不卡在线看 | 五月婷婷深开心 | 狠狠搞,com | 伊人在线视频 | 麻豆超碰 | 久久精品5| 久久综合之合合综合久久 | 国产精品一码二码三码在线 | av线上免费看 | 在线免费高清一区二区三区 | 91传媒视频在线观看 | 黄色小网站在线观看 | 五月香视频在线观看 | 综合网在线视频 | 天天插天天 | 精品成人国产 | 国产录像在线观看 | 五月激情在线 | 狠狠色丁香婷婷综合久久片 | 国产成人精品久久亚洲高清不卡 | 亚洲午夜激情网 | 综合久久精品 | 丁香激情五月 | 在线观看黄色小视频 | 丁香激情视频 | 久草在线最新视频 | 西西444www大胆高清视频 | 波多在线视频 | 国产精品久久久久永久免费看 | 玖玖在线精品 | 久草视频中文在线 | 国产精品黄色av | 国产精品久久久久久高潮 | 午夜美女视频 | 成人av av在线 | 婷婷综合亚洲 | av一区二区三区在线播放 | 国产精品免费观看久久 | 国产精品乱码久久久 | 久久久午夜影院 | 天天干天天怕 | 亚洲欧美日韩精品久久奇米一区 | 国产不卡在线 | 日韩在线观看你懂得 | 久久99影院 | 国产精品不卡在线观看 | 国产第一页在线观看 | 国产一级二级三级在线观看 | 999久久国产 | 欧美日韩在线观看视频 | 麻豆国产精品一区二区三区 | 中字幕视频在线永久在线观看免费 | 国产精品资源在线 | 日韩av影视在线观看 | www夜夜操com| 成人免费xyz网站 | 在线91精品 | 91av综合 | 日韩av成人在线 | 日韩国产精品毛片 | 精品国产一区二区三区久久久久久 | 青青草国产在线 | 精品国产乱码久久久久久天美 | 人人爱人人添 | 久久综合九色综合97_ 久久久 | 麻豆影视网 | 在线天堂视频 | 亚洲精品乱码久久久久久蜜桃91 | 精品国产一区二区三区男人吃奶 | 久久字幕精品一区 | 国产精品色婷婷视频 | 久久有精品 | 91九色免费视频 | 黄污视频网站大全 | 国产高清精| 国产亚洲精品无 | 一区电影 | 日韩视频免费 | 人人草在线观看 | 国产成人精品一区二 | 国产精品美女在线 | 国产精品一区二区无线 | 亚洲精品视频二区 | 久久久国产一区二区三区四区小说 | 日韩丝袜在线观看 | 天天干天天操天天拍 | 国产精品久久精品国产 | 亚洲精品成人av在线 | 日日干夜夜爱 | 久久午夜免费观看 | 一区二区三区在线影院 | 国产精品成人aaaaa网站 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 超碰久热| 四虎免费在线观看 | 成人播放器 | 一本色道久久综合亚洲二区三区 | 久久av一区二区三区亚洲 | 国产在线观看免 | 麻花天美星空视频 | 一级黄色片在线免费观看 | 国产一级片免费视频 | 亚洲 欧洲 国产 精品 | 五月天色婷婷丁香 | 欧美在线视频一区二区三区 | 国产精品一区在线观看你懂的 | 国产精品白浆视频 | 国产日产精品一区二区三区四区 | 亚洲精品国偷拍自产在线观看蜜桃 | 天天干天天摸 | 国产视频2 | 欧美日韩不卡在线观看 | 在线激情影院一区 | 日日干天天插 | 国产成人av一区二区三区在线观看 | 一区二区三区日韩精品 | 天堂网一区 | 激情欧美一区二区免费视频 | 国产免费又爽又刺激在线观看 | 成年人在线观看网站 | 狠狠色综合网站久久久久久久 | 久久久亚洲影院 | 国产精品久久毛片 | 久久高视频 | 夜夜干天天操 | 毛片区| 久久久精品国产免费观看同学 | 亚洲 精品在线视频 | 亚洲免费资源 | 中文字幕日本电影 | 精品国产99国产精品 | 久久九九精品 | 中文字幕一区二 | 欧美成人精品欧美一级乱黄 | 国产精品视频永久免费播放 | 久久久精品久久 | 超碰97.com| 日韩,精品电影 | 最近更新好看的中文字幕 | 肉色欧美久久久久久久免费看 | 天天干天天干天天干天天干天天干天天干 | 玖玖精品在线 | av中文字幕日韩 | 成年一级片 | 一区二区三区日韩在线观看 | 欧洲视频一区 | 久久久久久久久久久久电影 | 久久精品视频在线观看免费 | 久草视频视频在线播放 | 91视频在线免费观看 | 日韩免费电影一区二区 | 很污的网站 | 免费观看视频的网站 | 久久综合久色欧美综合狠狠 | 97国产视频 | 在线色亚洲| 粉嫩一区二区三区粉嫩91 | 午夜12点 | 福利一区在线 | 91精品在线视频观看 | 黄色小说在线观看视频 | 九九视频免费在线观看 | 黄色精品久久 | 国产精品美女久久久久久网站 | 中文字幕一区二区三区视频 | 日韩免费av网址 | 色噜噜日韩精品一区二区三区视频 | 久草影视在线观看 | 99热这里只有精品在线观看 | 黄色av电影免费观看 | 麻豆91在线看 | 成人在线视频论坛 | 亚洲成人免费在线观看 | 国产成人精品日本亚洲999 | www.天天色 | 亚洲成人精品国产 | 91pony九色丨交换 | 成人免费观看网址 | 成人av资源网站 | 成人免费观看视频大全 | 国产精品尤物视频 | 在线观看视频一区二区三区 | 久草视频在 | 欧美久久久久久久久中文字幕 | 日韩精品视频一二三 | 色婷五月天 | 亚洲精品系列 | 美女视频黄频 | 久久怡红院 | 五月天高清欧美mv | 久久免费播放 | 一区二区三区电影在线播 | 免费精品国产va自在自线 | 国产精品美女久久久久久久网站 | 激情av资源| 久久视频在线免费观看 | 久爱综合 | 免费在线观看av | 黄色网www | 久久中文字幕视频 | 在线精品亚洲一区二区 | 狠狠色狠狠色合久久伊人 | 欧美性黑人| 97av超碰| 最近更新好看的中文字幕 | 久久免费黄色大片 | 国产.精品.日韩.另类.中文.在线.播放 | 精品视频亚洲 | 国产日本亚洲高清 | 国产精品自产拍在线观看中文 | 在线免费黄色毛片 | 国模视频一区二区三区 | 亚洲成年人免费网站 | 久日精品 | 日韩aⅴ视频 | 国产亚洲日本 | 99精品热视频 | 人人dvd| 日韩综合视频在线观看 | 午夜精品久久一牛影视 | 久久不射影院 | 91精品视频观看 | 久久国产精品影视 | 日韩中文字幕国产精品 | 色在线视频 | 亚洲精品字幕在线观看 | 欧美精彩视频在线观看 | 国产一区高清在线 | 国产精品系列在线播放 | 一区二区三区中文字幕在线观看 | 欧美成人黄色片 | 福利一区视频 | 日韩精品免费在线播放 | 国产在线a不卡 | 日韩在线视频线视频免费网站 | 99c视频高清免费观看 | 91久久国产精品 | 国产亚洲精品无 | 亚洲专区在线播放 | av色一区 | 一级黄色片在线免费看 | 精品福利视频在线 | 日韩av电影中文字幕 | 久久久美女 | 激情视频免费在线 | 黄色一集片 | 欧美性色xo影院 | 国产五月| 亚洲 欧美 综合 在线 精品 | 国产糖心vlog在线观看 | www.夜夜爽 | 在线观看黄色的网站 | 在线免费黄色片 | japanesexxxhd奶水 91在线精品一区二区 | 天天爱天天干天天爽 | 91在线看网站 | 天天操天天插 | 18岁免费看片| 婷婷激情网站 | 69国产精品视频 | 久久久在线免费观看 | 中文字幕在线国产精品 | 天天看天天操 | 91在线观看视频网站 | 久久久亚洲麻豆日韩精品一区三区 | 精品视频成人 | 国产欧美久久久精品影院 | 国产精品久久久久久久久费观看 | 午夜久久电影网 | 在线香蕉视频 | 国产91精品看黄网站在线观看动漫 | 最新国产在线视频 | 久久久久久久久久久精 | 精品在线小视频 | 蜜桃视频成人在线观看 | 婷婷久久丁香 | 美女免费黄视频网站 | 国产黄在线 | 日韩在线电影观看 | 亚洲成人黄色在线观看 | 日本乱视频 | 国产99久久久国产精品免费看 | 久久久久久久久久久精 | 色综合www | 毛片a级片| av在线短片 | 亚洲在线不卡 | 97视频人人免费看 | 激情在线网| 欧美一级性生活 | 国产精品 国内视频 | 天天人人 | a黄色片在线观看 | 国产视频在线观看免费 | 日韩精品免费一区二区在线观看 | 久草免费资源 | www九九热 | 91精品一区二区三区蜜桃 | 国产一级黄色免费看 | 黄色毛片网站在线观看 | 黄色免费av | 久久久久久国产精品亚洲78 | 久久国内精品99久久6app | 国产成人区 | 精品国产免费久久 | 亚洲视频播放 | 日韩av免费一区 | 婷婷在线看 | 日本视频不卡 | 中文在线免费看视频 | 国产视频精品视频 | 久久精品一区二区三区国产主播 | 热久久国产精品 | 免费看一级特黄a大片 | 日韩视频在线不卡 | www.久久91 | 中文字幕中文字幕在线一区 | 国产精品免费久久 | 97精品国产97久久久久久 | 久久人人爽人人爽人人片 | 午夜美女视频 | 91网址在线观看 | 国产99亚洲 | 香蕉影院在线 | 婷婷六月综合亚洲 | 久久免费视频这里只有精品 | 亚洲精品在线免费看 | 综合激情| 99久久精品免费看国产免费软件 | 亚洲精品av中文字幕在线在线 | 国产一区二区三区免费观看视频 | 夜夜躁天天躁很躁波 | 99热.com| 久久夜夜操 | 精品二区久久 | 国产一级片网站 | 日韩免费视频一区二区 | 国产一区影院 | 在线看片日韩 | 欧美性天天 | 在线免费视频一区 | 国产尤物视频在线 | 午夜手机电影 | 免费在线观看av网站 | 国产黄网在线 | 国产精品淫| 国产一级片久久 | 国产精品免费观看国产网曝瓜 | 久草免费看 | www黄色软件 | 6080yy午夜一二三区久久 | 久操视频在线免费看 | 亚洲人人网 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 97超碰人人在线 | 亚洲天堂网在线播放 | 国产精品美女毛片真酒店 | 免费看片日韩 | 中文字幕乱码亚洲精品一区 | 国产一区国产精品 | 国产黄色在线观看 | 视频在线亚洲 | 999成人| 久久婷婷五月综合色丁香 | 在线网址你懂得 | 中文字幕乱在线伦视频中文字幕乱码在线 | av高清在线观看 | 国产精品18毛片一区二区 | 国产精品久久久久久久久久东京 | 九色视频网 | 久久久麻豆精品一区二区 | 91精品国自产在线观看欧美 | 日日夜夜精品免费 | 国产成人黄色av | 久久综合九色综合久久久精品综合 | 天天射夜夜爽 | 久久久精品久久日韩一区综合 | 国产精彩在线视频 | 国产亚洲字幕 | 亚洲精品玖玖玖av在线看 | 91精品国产九九九久久久亚洲 | av九九九 | 在线国产日本 | 国产精品久久久久久久99 | 99国产在线观看 | 成年人av在线播放 | 久久av影院 | 国产在线观看 | 就要干b | 日日干夜夜骑 | 在线观看成人一级片 | 久免费视频 | 五月天婷婷在线观看视频 | 91精品久久久久久粉嫩 | 黄色av网站在线免费观看 | 久草在线资源网 | 国产午夜在线观看视频 | 日本天天色| 一区中文字幕在线观看 | 天天在线免费视频 | 久久精品视频日本 | 国产精选视频 | 日本丶国产丶欧美色综合 | 91视频午夜| 亚洲综合在线五月天 | 日韩三级.com | 日韩av成人在线观看 | 国产一级片网站 | 国产精品成人a免费观看 | 久久久人人人 | 亚洲天堂自拍视频 | 久久国产欧美日韩 | 国产精品久久久久永久免费 | 色视频一区 | 激情婷婷六月 | 国产精品日韩欧美 | 国产美女网 | 精品av在线播放 | 天天干天天干天天操 | 成年人电影毛片 | 久久综合在线 | 最新中文字幕在线播放 | 国产精品美女久久久久久久久久久 | 日日夜夜狠狠操 | 天天爽人人爽夜夜爽 | 久久激情视频 久久 | 丁香一区二区 | 国产免费亚洲高清 | 亚洲成av人片 | 欧美aaa一级 | 免费在线观看午夜视频 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 久久情爱 | 国产亚洲91| 成人a级免费视频 | 久久久久久久毛片 | 久久免费的视频 | 97精品国产97久久久久久久久久久久 | 国内精品亚洲 | 激情综合网五月婷婷 | 中文字幕日韩高清 | 日韩在线视频免费观看 | 国产精品久久久久久电影 | www.狠狠插.com | 亚洲五月激情 | av黄色av | 婷婷夜夜| 综合色亚洲 | 国产视频二 | 少妇资源站 | 看污网站 | 激情大尺度视频 | 久久这里只有精品1 | 久久精品影视 | 丁香六月久久综合狠狠色 | 免费看黄色毛片 | 中文字幕av有码 | 色婷婷狠狠五月综合天色拍 | 欧美午夜久久 | 日韩欧美视频在线免费观看 | 一区二区视频在线看 | 亚洲视频在线播放 | 色综合久久久久综合 | 亚洲成av人片在线观看无 | 91精品日韩 | 天天拍天天操 | 字幕网资源站中文字幕 | 亚洲天堂色婷婷 | 欧洲一区二区三区精品 | 国产手机av在线 | av电影在线不卡 | 久久免费影院 | 国产资源在线免费观看 | 激情综合六月 | 国产录像在线观看 |