日韩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字体图元结构剖析,自定义字体的制作与匹配和识别的全部內容,希望文章能夠幫你解決所遇到的問題。

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

激情综合国产 | 日韩欧美精品在线 | 日韩在线免费小视频 | 欧美日韩视频一区二区三区 | 免费在线观看黄色网 | 91亚洲精品在线 | 亚洲成人一区 | 亚洲国产精选 | 91精品免费看 | 综合久久五月天 | 国产精品久久久久久久久久久久午夜 | 在线观看激情av | 午夜免费在线观看 | 免费影视大全推荐 | 91热这里只有精品 | av在线收看 | 99热精品国产 | 日韩免费在线观看视频 | 免费看一级片 | 亚洲精品视频网址 | 九九免费观看视频 | 在线免费观看一区二区三区 | 日日操操| 中文字幕精品三级久久久 | 东方av在线免费观看 | 成人国产精品av | 国产精品久久久久久吹潮天美传媒 | 天天爱天天插 | 91av在线国产 | 久草在线99| 成人网大片| 欧美日韩99 | 最新影院| 成人免费电影 | 欧美日韩精品在线视频 | www一起操| 狠狠网站 | 高清在线一区 | 欧美精品天堂 | 久久伦理电影 | 日韩欧美精品在线视频 | 伊人国产在线播放 | 婷婷福利影院 | 天天操天天色天天射 | 国产玖玖在线 | 人人干人人模 | 久久综合干| 欧美 激情 国产 91 在线 | 久久久久久高潮国产精品视 | 国产粉嫩在线观看 | 久久色在线播放 | 天天色天天射天天操 | 日韩在线免费视频观看 | 97成人超碰| av在线一二三区 | 久久亚洲人| 福利视频网站 | 欧美黑人xxxx猛性大交 | 日本公妇在线观看 | 国内精品久久久久影院日本资源 | 一色屋精品视频在线观看 | 999国内精品永久免费视频 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 麻豆视频在线免费 | 久久精品91视频 | 天天操福利视频 | 三级视频国产 | 日本高清dvd| 中文在线亚洲 | 午夜久久成人 | 91在线视频精品 | 免费人做人爱www的视 | 久久久精品影视 | 国产成人精品日本亚洲999 | 黄色www| 9999在线| 国产精品毛片久久蜜 | 国产麻豆视频免费观看 | 国产欧美在线一区二区三区 | 色老板在线 | 99精品欧美一区二区三区 | 99一级片 | 国产精品中文字幕av | 国产成人黄色网址 | 91视频com | 欧美乱码精品一区二区 | 六月丁香婷婷久久 | 亚洲综合精品视频 | av免费电影在线 | 欧美少妇的秘密 | 精品在线亚洲视频 | 日韩免费观看视频 | 91在线资源 | 高清在线一区 | 国产视频一区在线播放 | 中文字幕在线网址 | 精品在线观 | 狠狠干天天操 | 麻豆视频免费网站 | 成人一区二区三区在线 | 天天操天天添天天吹 | 免费污片 | 天天色 天天 | 亚洲免费在线播放视频 | 国产日韩视频在线播放 | 一本一道久久a久久综合蜜桃 | 国产精品mv| 中文字幕网站 | 亚洲视频免费在线观看 | 欧美日韩久久一区 | 黄色一级免费网站 | 欧美在线视频不卡 | 日韩网站在线看片你懂的 | www日韩视频 | 日日爱av| 免费三级在线 | 欧美一区二区精品在线 | 99爱视频 | 天天草天天干天天射 | 久久少妇 | 久久亚洲福利视频 | 天天射综合网站 | 麻豆国产在线播放 | 成人国产精品久久久 | 日韩伦理片hd | 欧美精品一区二区三区四区在线 | 日韩理论在线视频 | 久久久久激情视频 | 蜜臀av一区二区 | 在线亚洲精品 | 国产经典三级 | 香蕉视频在线看 | 久久免费视频在线观看 | 91完整版 | 四虎www| 久久超碰99 | 国产在线精品一区二区不卡了 | 亚洲精品视频二区 | 国产视频亚洲精品 | 91麻豆精品国产91久久久更新时间 | 日韩在线视频一区二区三区 | 亚洲高清激情 | 国产黄色在线观看 | 国产不卡精品 | 狠狠艹夜夜干 | 人人视频网站 | 最近中文字幕免费视频 | 欧美精品三级 | 9在线观看免费高清完整 | 日韩av偷拍| 国产精品美女久久久久久免费 | 久草精品视频在线观看 | 久久久久久久久免费视频 | 久久精品国产第一区二区三区 | 国产精品一区二区三区在线看 | 久久超碰免费 | 久久精品99国产精品亚洲最刺激 | 人人爽人人射 | 五月综合色婷婷 | 欧美成年人在线观看 | 国产精品久久在线 | 97精品国产一二三产区 | 91高清免费看 | 国产在线一区二区三区播放 | 中文字幕在线字幕中文 | 日本中文字幕在线一区 | 免费看国产视频 | 国产精品久久久久久久久久久杏吧 | 日本中文字幕网站 | av在线网站免费观看 | 午夜久久久久久久久 | 99热九九这里只有精品10 | 在线观看a视频 | 国产中文字幕视频在线 | 91精品国产九九九久久久亚洲 | 夜夜操狠狠操 | 日韩大片在线免费观看 | 日韩午夜一级片 | 欧美不卡在线 | 91亚洲在线观看 | 国产精品一区二区三区四 | 亚洲激情综合 | 蜜臀久久99精品久久久酒店新书 | 免费黄色网址大全 | 久久99精品波多结衣一区 | 国产99久久久国产 | 免费网址在线播放 | 丁香五月网久久综合 | 日日夜夜天天久久 | 日韩最新理论电影 | 91豆花在线观看 | 欧美a级在线免费观看 | 91片在线观看 | 91av视频在线免费观看 | 最近更新中文字幕 | 欧美另类性 | 国产在线更新 | 欧美成人理伦片 | 在线观av | 81精品国产乱码久久久久久 | 日韩精品在线视频 | 久久久99精品免费观看 | 国产亚洲欧洲 | 在线观看911视频 | 国产一级黄色电影 | 精品国产自在精品国产精野外直播 | 97超碰人人网 | 国产中文字幕在线观看 | 欧美日韩a视频 | 精品久久久免费 | 免费在线观看日韩 | 欧美激情精品久久久久久 | 日韩在线 一区二区 | 国产高清精品在线 | 欧美高清成人 | av在线免费网 | 欧美老女人xx | 激情偷乱人伦小说视频在线观看 | 91成人精品一区在线播放69 | 久草爱视频 | 爱情影院aqdy鲁丝片二区 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 色偷偷男人的天堂av | 9热精品 | 久久久久国产视频 | 精品国内自产拍在线观看视频 | 亚洲欧美视频一区二区三区 | 91av视频免费观看 | av一区二区三区在线 | 成 人 黄 色 视频播放1 | 激情五月综合 | 91九色蝌蚪在线 | 91久久人澡人人添人人爽欧美 | 欧美精品免费在线 | 亚州av成人 | 精品黄色在线观看 | 久久成人午夜 | 精品视频123区在线观看 | 91久久精品日日躁夜夜躁国产 | www.国产高清 | 麻豆视频免费在线观看 | 免费观看9x视频网站在线观看 | 亚洲香蕉在线观看 | 99久久er热在这里只有精品66 | 婷婷久久丁香 | 国内精品久久久久久久久久久 | 蜜臀av在线一区二区三区 | 免费看成人a | 国产超碰97 | a色网站| 日韩在线观看小视频 | 日韩在线视频免费播放 | 亚洲午夜小视频 | 亚洲精品动漫在线 | 在线国产91 | 在线观看网站黄 | 欧美日韩不卡在线 | 天天天色综合 | 丝袜av网站 | 国产精品久久久久av免费 | www.久久久com | 国产精品黄网站在线观看 | 最近中文字幕高清字幕在线视频 | a天堂中文在线 | 成人免费在线播放 | 久久国产经典 | 27xxoo无遮挡动态视频 | 亚洲成aⅴ人片久久青草影院 | 精品在线小视频 | 色婷婷综合久久久 | 五月婷婷在线观看 | 国产一级一片免费播放放 | 国产成人免费网站 | 婷婷性综合 | 亚洲电影图片小说 | 在线电影 一区 | 久久99久久99久久 | 国产一区免费在线 | 国产69精品久久app免费版 | 日本午夜免费福利视频 | 久久99影院 | 一区二区三区在线免费 | 99热.com| 久久国产精品久久精品国产演员表 | 黄色字幕网 | 中文字幕av免费 | 国产在线色视频 | 性色av免费在线观看 | 欧美一二三视频 | 午夜视频免费 | 国产精品一区二区三区在线看 | 免费欧美高清视频 | 91av中文字幕 | 亚洲精品午夜久久久 | 亚洲理论电影 | 精品二区久久 | 欧美日韩国产一区二区在线观看 | 亚洲va在线va天堂va偷拍 | 日韩欧美国产精品 | 欧美午夜寂寞影院 | 99热高清 | 九九在线精品视频 | 精品久久久久久久久久久久久久久久 | 天天干,天天插 | 国产亚洲成av片在线观看 | 综合久久一本 | 九九视频免费观看视频精品 | 久久久www成人免费毛片 | 二区三区在线视频 | 久久精品成人 | 欧美俄罗斯性视频 | 99999精品视频| 久久 精品一区 | 日韩欧美一区二区在线观看 | 日韩免费电影网站 | 久久久久久久久久久福利 | 99欧美精品 | 国产精品免费在线观看视频 | 日韩免费一级a毛片在线播放一级 | 国产精品久久久久久久午夜片 | 免费观看一级一片 | 成人动漫一区二区三区 | 久草在线免费电影 | 国产一线在线 | 国产日韩精品一区二区三区在线 | 免费视频 你懂的 | 日韩 国产| 99精品国产99久久久久久97 | 久久福利影视 | 伊人首页 | 久久精品视频99 | 天天爽天天爽 | 欧美日韩国内在线 | 四虎影视成人永久免费观看亚洲欧美 | 中文字幕资源网 | 国产精品一区二区三区免费视频 | 欧美精品久久久久a | 69精品久久 | 91精品视频免费观看 | 成人一级免费电影 | 国产精品亚| 亚洲国产剧情av | 欧美成年人在线观看 | 狠狠的操狠狠的干 | 97看片| av短片在线 | 日韩不卡高清 | 亚洲国产精品va在线看黑人 | 欧美精品一区二区三区一线天视频 | 国产福利在线免费 | 日日干网址| www.色午夜,com| 97在线影院 | 国产精品尤物 | 粉嫩av一区二区三区免费 | 色婷婷成人网 | 亚洲人人网 | 就要干b| 国产精品第二十页 | 久久久久国产一区二区三区 | 美女黄频在线观看 | 亚洲精品视频第一页 | 国产婷婷精品 | 久久综合九色欧美综合狠狠 | 91在线看片| 99久久精品视频免费 | 日韩欧美一区二区在线 | 一区二区激情 | 在线观看视频97 | 成人资源在线观看 | 日韩爱爱网站 | 亚洲综合一区二区精品导航 | 99精品国产在热久久下载 | 国产精品自在欧美一区 | 欧美人zozo | 日日夜夜狠狠干 | 国产在线一区二区 | 国产精华国产精品 | 色婷婷啪啪免费在线电影观看 | 毛片3| 久久久久99精品成人片三人毛片 | 国产精品国产亚洲精品看不卡15 | 麻豆视频免费入口 | 一区二区不卡 | 亚洲一区免费在线 | 久久久久免费电影 | 欧美在线91 | 少妇搡bbbb搡bbb搡aa | 日韩三区在线 | www五月天com | 久久久久久久久久久久电影 | 亚洲欧美婷婷六月色综合 | 久久久久久国产精品 | 国产资源网站 | 日韩精品中文字幕在线观看 | 久久兔费看a级 | 91午夜精品| 国产99久久九九精品免费 | 丰满少妇在线观看资源站 | 天天综合婷婷 | 91在线小视频 | 97在线视频免费看 | 8x成人在线| 日韩一区二区在线免费观看 | 免费亚洲一区二区 | 婷婷丁香久久五月婷婷 | 一区二区三区四区免费视频 | 五月婷在线播放 | 亚洲精品国产精品久久99热 | free. 性欧美.com | 色综合久久久网 | 欧洲高潮三级做爰 | 日韩高清一区在线 | 国产手机在线播放 | 麻豆视频一区二区 | 成人国产精品av | 国产成人免费观看久久久 | 国产a视频免费观看 | 免费观看福利视频 | 99久久999久久久精玫瑰 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 五月婷婷久久丁香 | 在线视频国产区 | 亚洲免费观看在线视频 | 911av视频 | 在线观看视频你懂的 | 亚洲视频久久 | 国产三级视频在线 | 91在线文字幕 | 在线a亚洲视频播放在线观看 | 婷婷激情在线观看 | 久久一区91 | 一区二区三区在线观看中文字幕 | 九九九电影免费看 | 91精品国产综合久久婷婷香蕉 | 天天碰天天操视频 | 啪啪精品 | 国产麻豆视频 | 欧美日韩精品在线播放 | 麻豆影视在线免费观看 | 久久a久久| 久久美女高清视频 | 欧美一级在线观看视频 | 亚洲成人av电影在线 | 免费在线观看av网站 | 亚洲更新最快 | 国产啊v在线观看 | 婷婷成人综合 | 国产亚洲精品中文字幕 | 天天躁天天操 | 久草在线这里只有精品 | 中文在线a∨在线 | 日韩免费在线观看视频 | 六月婷婷网 | 久久精品国产v日韩v亚洲 | 天天插天天狠天天透 | 青青草国产免费 | 天天射天天做 | 少妇性bbb搡bbb爽爽爽欧美 | av播放在线 | 国产日韩精品一区二区三区 | 久影院| 精品久久福利 | 国产日韩在线看 | 涩五月婷婷 | 人人插人人干 | 一区二区三区免费在线观看 | 精品久久久久久国产偷窥 | 97国产精品久久 | 国产成人在线观看免费 | 天天射天 | 高清不卡一区二区在线 | 国产毛片久久久 | 成人h视频 | 国产午夜精品一区二区三区 | 亚洲欧美乱综合图片区小说区 | 国产视频精品在线 | 欧美成人久久 | 狠狠色丁香婷婷综合久久片 | 国产在线黄 | 亚洲精品视频在线播放 | 国产精品videossex国产高清 | 国产精品资源网 | 中国一级片在线 | www激情网| 久久国产精品免费视频 | 丁香视频全集免费观看 | 美女黄久久 | 激情黄色一级片 | 丁香色婷 | 91av精品 | 国产资源av| 五月天综合网 | 国产一区二区三区 在线 | 色综合中文字幕 | 久草电影网 | 四虎伊人| 午夜精品一二区 | 日本中文不卡 | 九色精品免费永久在线 | 99se视频在线观看 | 婷婷九月丁香 | 国产大陆亚洲精品国产 | 97超碰在线久草超碰在线观看 | 伊人六月 | 久久精品91久久久久久再现 | 欧美va天堂在线电影 | 国产日韩欧美精品在线观看 | 国产亚洲精品久久久久久久久久 | 久久99在线视频 | 亚洲综合色婷婷 | 超碰人人在线观看 | 欧美中文字幕久久 | 午夜精品久久久99热福利 | av亚洲产国偷v产偷v自拍小说 | 国产在线2020 | 亚洲精品动漫久久久久 | 国产精品一区二区三区免费看 | 久久免费国产电影 | 亚洲天堂毛片 | 精品国产成人av | 黄色精品免费 | 欧洲成人av| avav99| av在线亚洲天堂 | 狠狠色丁香九九婷婷综合五月 | 中文 一区二区 | 午夜三级影院 | 一区二区三区视频在线 | 超级碰99 | 懂色av一区二区三区蜜臀 | 99久高清在线观看视频99精品热在线观看视频 | 天天操天天射天天添 | 久久99精品国产99久久 | 精品视频免费播放 | 国产精品欧美日韩在线观看 | av激情五月 | 亚洲精品午夜久久久 | 精品国产一区二区三区久久久蜜月 | 欧美日韩国产在线一区 | 操操日日| 久久久国产精品一区二区三区 | 精品久久久久久久久久岛国gif | 99久久99久久精品国产片 | 一区二区精品在线 | 婷婷综合五月 | 久亚洲| 久久爱www. | 亚洲国产视频直播 | 97超碰中文字幕 | 97国产精品免费 | 99久久99久久| 国产一区二区精品久久 | 在线观看亚洲精品 | 国产v视频 | 久久久久久国产精品免费 | 不卡av在线 | 国产精品日韩在线播放 | 精品国产乱码久久久久久浪潮 | 久久久久久中文字幕 | 91精品在线免费视频 | 青青草国产精品视频 | 精品国产一区二区三区久久久 | 国产精品久久三 | 久久中文网 | 免费在线一区二区 | 中文字幕在线播放一区二区 | 中文亚洲欧美日韩 | 亚洲精品美女视频 | 91秒拍国产福利一区 | 久久久久久久久久久久av | 一区二区电影网 | 91污视频在线观看 | 亚洲美女精品区人人人人 | 九九亚洲精品 | 成人av电影免费观看 | 国产精品国产亚洲精品看不卡15 | 91精品国产91 | 免费视频你懂得 | 日韩中文字幕免费看 | 亚洲黄色在线看 | 美女视频久久久 | 成人av网页| 日韩高清片 | 国产精品一区二区在线观看免费 | 又黄又刺激| 国产在线一区二区三区播放 | 夜夜爽88888免费视频4848 | 精品久久久999 | 国产视频二 | 欧美日韩高清不卡 | 狠狠色丁香婷婷综合最新地址 | 国产亚洲成av人片在线观看桃 | 日韩在线观看一区二区三区 | 99视频久久| 亚洲欧洲成人精品av97 | 91中文字幕在线播放 | 97视频精品| 黄色一二级片 | 在线免费观看黄 | 在线观看免费成人av | 精品av网站| 五月天综合色激情 | 人人舔人人舔 | 日韩精品影视 | 最新国产精品拍自在线播放 | 亚洲精品免费播放 | 日韩免费在线播放 | 五月天激情视频 | 91成人免费在线视频 | 麻豆视频在线免费观看 | 97日日碰人人模人人澡分享吧 | 91xav| 久久久久国| 91精品视频一区二区三区 | 五月婷婷毛片 | 五月开心婷婷 | 国产精品亚洲片夜色在线 | www.com黄色| 久草在线视频国产 | 狠狠色丁香久久婷婷综合_中 | 国产高清在线精品 | 亚洲精品综合在线 | 日本最大色倩网站www | 国产精品免费久久久久 | 在线国产中文字幕 | 国语精品免费视频 | 伊人激情综合 | 久久综合之合合综合久久 | 草久视频在线观看 | 日本丰满少妇免费一区 | 日韩免费在线视频 | 在线免费观看黄网站 | 91视频免费国产 | 日韩精品久久久久久久电影99爱 | 天天爽夜夜爽精品视频婷婷 | 亚洲精品成人在线 | 久久国产精品99国产精 | 一区二区三区播放 | 成人免费xxx在线观看 | 九九久久久久久久久激情 | 久久蜜桃av| 国产精品中文字幕在线观看 | 免费亚洲婷婷 | 在线观看免费福利 | 在线亚洲精品 | 亚洲在线日韩 | 中文字幕永久免费 | 黄色大片国产 | 亚洲成人精品国产 | 9在线观看免费高清完整版 玖玖爱免费视频 | av高清网站在线观看 | 97精品国产97久久久久久春色 | 国产破处视频在线播放 | 超碰在97 | 欧美日韩亚洲在线观看 | 看黄色91| 久久激情影院 | 亚洲人毛片 | 91中文字幕在线观看 | 五月婷婷六月丁香在线观看 | 美女免费视频观看网站 | 色五婷婷 | 色欲综合视频天天天 | 亚洲视频一区二区三区在线观看 | 久久综合婷婷国产二区高清 | 日韩欧美一级二级 | 狠狠做深爱婷婷综合一区 | 美女免费视频一区二区 | 国产你懂的在线 | 午夜影院先 | 91影视成人| 五月婷婷播播 | 激情视频久久 | 久久久精品99 | 亚洲男女精品 | 欧美成人xxxxx | 激情欧美xxxx | 久久久久久久久久久免费视频 | 91成人精品国产刺激国语对白 | 日韩a在线播放 | 国产免费资源 | 国产一区麻豆 | 右手影院亚洲欧美 | 亚洲精品九九 | 精品国产乱码久久久久久久 | 国产精品黄色 | 免费色视频网址 | 中文字幕在线观看资源 | 在线影院中文字幕 | 国产精品久久久久国产a级 激情综合中文娱乐网 | 日韩城人在线 | 久久免费国产视频 | 玖玖在线看| 日韩午夜小视频 | 91欧美视频网站 | 一本—道久久a久久精品蜜桃 | 国产黄色大片 | 国产精品原创在线 | 99精品视频一区 | 国内久久视频 | 成人啪啪18免费游戏链接 | 69国产精品视频免费观看 | 中文永久免费观看 | 国产精品久久久久影视 | 亚洲成年人av | 国产精品 日韩 欧美 | 亚洲精品av中文字幕在线在线 | www最近高清中文国语在线观看 | 91综合视频在线观看 | 天天色天| 成年人黄色在线观看 | 国产一级片观看 | 波多野结依在线观看 | 日韩激情视频在线观看 | 欧美精品一区二区性色 | 97色婷婷成人综合在线观看 | 国产精品2018 | 日本中文字幕在线电影 | 欧美激情视频一区二区三区免费 | 丁香色综合 | 97在线看| 婷婷在线色 | 国产精品视频区 | 国产剧情av在线播放 | 久久久国产毛片 | 日韩在线视频网 | 精品一区二区三区久久久 | 色噜噜日韩精品一区二区三区视频 | 91色九色 | 精品黄色片 | 日日夜夜网| 日韩中文字幕免费视频 | 免费a级黄色毛片 | 亚洲精品ww | 最新国产在线观看 | 在线观看91精品国产网站 | 精品美女视频 | 久久久久电影 | 狠狠躁夜夜躁人人爽视频 | 成人午夜免费剧场 | 国产精品久久久久久久久久99 | 婷婷av网站| 久草亚洲视频 | 国模一区二区三区四区 | 久久在线免费观看视频 | 久久午夜电影 | 精品视频资源站 | 美女黄久久 | 中文字幕在线观看你懂的 | 国产精品爽爽久久久久久蜜臀 | 爱av在线网| 最近2019年日本中文免费字幕 | 欧美日韩国产精品久久 | 中文字幕999 | 久久精品国产免费看久久精品 | 国产二区视频在线观看 | 日韩久久精品一区二区 | 午夜一级免费电影 | 91麻豆国产 | 久久永久免费视频 | 精品一区二区在线播放 | 黄色片免费电影 | 天天爽天天爽 | 超碰免费av| 综合中文字幕 | 午夜精品福利影院 | 在线观看国产亚洲 | 在线黄色av电影 | 国产精品夜夜夜一区二区三区尤 | 成年人在线观看 | 久久国产经典 | 激情丁香在线 | 国产日韩精品一区二区三区在线 | 久久久久国产一区二区三区四区 | 亚洲黄色在线免费观看 | www.av免费观看| 精品国产一区二区三区男人吃奶 | 狠狠色丁香婷婷综合最新地址 | 国产精品一区二区三区在线播放 | 国产一级性生活 | 国产视频18 | 91成人免费在线视频 | 久久热亚洲 | 免费黄色在线 | 国产免费久久 | 美女一二三区 | av免费在线看网站 | 亚洲国产日韩欧美在线 | av电影在线不卡 | 日韩电影在线观看中文字幕 | 天堂av在线| 日日躁夜夜躁aaaaxxxx | 国产一区在线看 | 亚洲综合视频在线 | 久久综合干 | 911久久香蕉国产线看观看 | 最新免费av在线 | 国产成人精品久久二区二区 | 日韩最新理论电影 | a久久免费视频 | 国产一级不卡毛片 | 婷婷天天色 | 日本黄色黄网站 | 欧美精品黑人性xxxx | 99免费在线观看视频 | 西西4444www大胆视频 | 日韩av不卡在线观看 | 欧美一区二视频在线免费观看 | 国产尤物一区二区三区 | 久草在线免费电影 | 国产另类xxxxhd高清 | 97自拍超碰| 婷婷综合五月天 | 国产精品不卡在线播放 | 超碰97人人在线 | 欧美亚洲久久 | av观看久久久| 国产一区二区在线免费视频 | 亚洲a网 | 国产91精品一区二区麻豆亚洲 | 日韩欧美视频一区 | 天海翼一区二区三区免费 | 日韩欧美在线综合网 | 日韩精品久久久久 | 亚洲aⅴ一区二区三区 | 午夜av激情| a级一a一级在线观看 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | 日本在线视频一区二区三区 | 免费黄色在线播放 | 精品国产一区二区三区不卡 | 综合久久2023| 亚洲最新av在线网址 | 欧美精品v国产精品v日韩精品 | 免费看黄在线 | 91手机电影 | 91在线中字 | 日日夜夜人人精品 | 日韩电影中文字幕 | 二区三区精品 | 精品一区二区电影 | 丁香婷婷基地 | 亚洲综合色视频在线观看 | 国产精品福利在线 | 国产亚洲婷婷免费 | 午夜av一区二区三区 | 国产午夜精品久久久久久久久久 | 香蕉网在线观看 | 国产精品欧美精品 | 久久一区二 | 日韩欧美一区二区三区免费观看 | 在线播放一区 | 日韩啪啪小视频 | 久久亚洲免费 | 综合久久五月天 | 9在线观看免费高清完整版在线观看明 | 欧美成人精品欧美一级乱 | 国产精品欧美日韩在线观看 | 免费观看视频的网站 | 激情电影影院 | 亚洲欧美日韩精品久久久 | 九九九毛片 | 99精品视频观看 | 国产黄a三级三级三级三级三级 | 国内精品久久久久久久影视简单 | av爱干| 久久精品专区 | 99c视频高清免费观看 | 伊人黄色网 | 超碰免费在线公开 | 亚洲精品乱码久久久久v最新版 | 五月天伊人 | 丁香激情视频 | 91网页版免费观看 | 精品在线观看一区二区三区 | 九色精品免费永久在线 | 日韩av成人| 精品国产自在精品国产精野外直播 | 久久成人在线视频 | 国产精品一区二区麻豆 | 欧美综合在线视频 | 欧美午夜理伦三级在线观看 | 99综合电影在线视频 | 99精品视频在线观看视频 | 国产在线p | 久草视频精品 | 久久久久久久久艹 | 精品福利国产 | 免费高清男女打扑克视频 | 日韩av影视 | 国产99久久久精品 | 亚洲精品中文字幕在线观看 | 国产精品麻豆一区二区三区 | 狠狠狠狠狠狠狠狠 | 在线观看免费版高清版 | 涩五月婷婷 | 国产91精品久久久久 | 日韩欧美在线中文字幕 | 色偷偷网站视频 | 欧美九九九| av网址在线播放 | 欧美另类交在线观看 | 色综合久久中文字幕综合网 | 91在线中文 | 日本mv大片欧洲mv大片 | 欧洲激情在线 | 国产精品igao视频网入口 | 精品在线观看免费 | 亚洲a网 | 蜜桃麻豆www久久囤产精品 | 一区二区三区国 | 狠狠狠色丁香综合久久天下网 | 国产一级二级视频 | 国产精品久久久久av | 9色在线视频 | 99久久精品国 | 久久亚洲美女 | 免费久久片| 精品麻豆入口免费 | 在线 欧美 日韩 | 成人一区不卡 | 91色偷偷 | 在线观看亚洲国产精品 | 国产视频在线观看一区 | 91麻豆精品久久久久久 | 在线一二三区 | 天天干天天草天天爽 | 狠狠狠色丁香婷婷综合久久88 | 国产亚洲视频在线 | 九九视频一区 | 一区二区三区在线免费播放 | 6080yy午夜一二三区久久 | 久久久久在线观看 | 综合色爱| 亚洲九九九在线观看 | 久久精品99国产精品亚洲最刺激 | 婷婷国产一区二区三区 | 免费试看一区 | 欧美日韩在线视频观看 | 日本中文字幕在线 | 亚州成人av在线 | 夜夜躁日日躁狠狠久久88av | 激情 一区二区 | 久久久国产精品电影 | 亚洲欧美在线综合 | 天天综合狠狠精品 | 丁香久久久 | 日韩三级成人 | 久久天天躁夜夜躁狠狠躁2022 | 激情五月婷婷 | 手机在线日韩视频 | 午夜精品成人一区二区三区 | 国产免费观看高清完整版 | 在线免费视频 你懂得 | www成人av| 亚洲综合激情小说 | 国产区在线看 | av免费试看 | 久久免费黄色大片 | 国产成人一区三区 | 在线观看色网 | 国产免费久久久久 | 久草网首页 | 亚洲综合干 | 久草视频99| 欧美黑吊大战白妞欧美 | av天天澡天天爽天天av | 国产精品99久久免费观看 | 高潮久久久 | 色婷婷狠狠五月综合天色拍 | 成人av资源在线 | 国产日产精品久久久久快鸭 | 一区二区av | 亚洲人成网站精品片在线观看 | 亚洲免费av网站 | 一区久久久 | 欧美日韩精品在线免费观看 | 亚洲欧洲一区二区在线观看 | 最近中文字幕免费视频 | 久久精品视频一 | 黄色网免费| 在线观看视频福利 | 日本天天操| 日韩成人在线一区二区 | 一区二区三区四区五区六区 | 深爱激情久久 | 国产一级大片在线观看 | 亚洲 成人 一区 | 亚洲视频在线视频 | 99久久er热在这里只有精品15 | 国产裸体视频bbbbb | 精久久久久 | 欧美高清视频不卡网 | 在线观看国产v片 | 国产精品久久久久久久久久久久午夜片 | 国产在线a | 国产亚洲va综合人人澡精品 |