滿紙荒唐言:Processing 尋覓文字魅力篇

本文要說的:

  • 滿紙荒唐言
  • 文字學習篇
  • 進階成長錄
  • 字體設計稿
  • 金陵十二釵

滿紙荒唐言

亂鬨哄,你方唱罷我登場,反認他鄉是故鄉;甚荒唐,到頭來都是為他人作嫁衣裳。

「滿紙荒唐言」出自小說《紅樓夢》的開篇。正所謂,「滿紙荒唐言,一把辛酸淚。都雲作者痴,誰解其中味?」雪芹先生於悼紅軒中,披閱十載,增刪五次,纂成目錄,分出章回,又題曰《金陵十二釵》,並題了該詩。

吾近來讀之,甚喜。自以為文章合本意,故以此為引。

古人有雲,「聲不能傳於異地,留於異時,於是乎文字生。文字者,所以為意與聲之跡。」

當然,本文志在體味「脫帽露頂王公前,揮毫落紙如雲煙」的洒脫與超然,而非細究文字的「傳於異地,留於異時」的實用性。

就藝術的眼光看來,文字即無言之詩,無形之舞,無圖之畫,無聲之樂。

這不禁讓我想起了2008年北京奧運會開幕式的場景,國人向全世界展示中華文字藝術的魅力,好不壯觀。

以下,是我用 Processing 製作的一個標題。代碼在線,點擊這裡(Dodge Text - OpenProcessing)。

文字學習篇

於程序而言,其顯示步驟如下:

step 1:Create the font;

至於創建字體,吾有三計——

計之一:利用創建字體工具手動創建字體。

在 Processing 工作窗口的「工具」(Tools)菜單中選擇「創建字體…」(Create Font)命令,在彈出的窗口中選擇字體和字型大小,點擊「確定」(OK)完成創建。生成的 vlw 格式字體被默認放置於 data 文件夾中(若沒有,PDE 會自動創建 data 文件夾)中。(「vlw」是 Processing 特有的字體格式)

計之二:使用用戶系統中的字體。

如何查看用戶系統中有字體呢?調用 PFont.list() 函數:

String[] list=PFont.list();
printArray(list); // 在控制台輸出字體名稱

換而言之,我們可以在自己的電腦系統里安裝好所需的字體,而後在 Processing 直接載入調用。

而美中不足的是,這種方式會導致程序的載入速度變緩,畢竟我們增大了載入難度。同時這也並非所有字體都可以使用,有些可能只適用於一個操作系統。

計之三:使用網上下載的字體。

此計可謂是結合了前二計的綜合法。一為將下載好字體放置於 data 文件夾中(計一),一為在用戶系統上安裝好下載的字體(計二)。

step 2:Declare an object of type PFont;

聲明變數:

// PFont + 變數名
PFont font; // 變數名為 font

step 3:Load the font;

這裡理應有兩種做法:

法之一:當需要將 .vlw 格式的字體載入到 PFont 對象時,我們調用 loadFont() (loadFont() Language (API) Processing 3+) 方法。

舉個栗子:

PFont font;
// 字體必須位於「data」文件夾中才能成功載入
font = loadFont("LetterGothicStd-32.vlw");

法之二:利用 createFont() (createFont() Language (API) Processing 3+) 方法,將「data」文件夾中的 .ttf 或 .otf 文件或計算機上其他位置安裝好的字體,動態地轉換為 Processing 使用的格式。

舉個栗子:

PFont myFont;

void setup() {
size(200, 200);
// 取消以下兩行注釋,以查看可用字體
// String[] fontList = PFont.list();
// printArray(fontList);
myFont = createFont("Georgia", 32);
}

step 4:Specify the font;

此處應有 textFont() (textFont() Language (API) Processing 3+)。

textFont():設置將使用 text() 繪製的當前字體。其可輸入一個或兩個參數,字體變數和字體大小。若輸入不包含字體大小,則字體將顯示為字體的原始載入大小。值得注意的是,如果我們指定的字體大小與載入的字體大小不同,則可能會顯示像素化或質量差的文本。

舉個栗子:

textFont(f,36);

step 5:Specify a color;

上色工序,你可能需要:

fill(rgb)
fill(rgb, alpha)
fill(gray)
fill(gray, alpha)
fill(v1, v2, v3)
fill(v1, v2, v3, alpha)

step 6:Display text。

顯示文本咯!詳細請查閱 text() (text() Language (API) Processing 3+)。

舉個栗子:

text("word", 10, 90);

進階成長錄

厚地高天,堪嘆古今情不盡;痴男怨女,可憐風月債難償。

欲取文台幻境,且需步步為營。

在下文中,愚笨的筆者舉了一個小小的的栗子,以期讀者能夠領悟如何由淺入深、循序漸進地增長自身功力,成為絕世大俠。

小栗子的結構:

栗子皮:文字跳動

【明】袁宏道言:一林過雨蘆花白,半壁疏雲栗子黃。

代碼在線,點擊這裡 (Text Art V1.0 - OpenProcessing)。

栗子殼: 天外飛仙

無名氏言:毛刺隨身霧裡狂,針球栗子郁山鄉。

代碼在線,點擊這裡 (Text Art V1.1 - OpenProcessing)。

栗子肉: 落絮來書

京津傳言:堆盤栗子炒深黃,客到長談索酒嘗。寒火三更燈半灺,門前高喊「灌香糖」。

代碼在線,點擊這裡 (Text Art V1.2 - OpenProcessing)。

栗子味: 還是得自己嘗!

【元】王哲曰:栗子甘甜美芋頭。

……

字體設計稿

關於創意字體設計,這裡有兩個可謂實用的庫(NextText 已在 Processing 3 中棄用了,此處且不再提及):

Ⅰ:Geomerative (Geomerative),By Ricard Marxer

Introduction:

Geomerative (ricardmarxer.com/geomer) 擴展了 2D 幾何操作,以促進生成幾何。其包括了 TrueType 字體和 SVG 解釋器。

Ⅱ:Fontastic (A Processing library to create font files),By Andreas Koller

Introduction:

Fontastic (A Processing library to create font files) 用於創建 TTF 和 WOFF 格式的字體文件。

所以,你該用誰呢?以筆者的理解,前者如雕刻刀,後者若鑿石斧。Geomerative 追求創意,Fontastic 旨在簡易。

當然,我也收集到了一些使用 Geomerative 創建的字體:

金陵十二釵

可嘆的是,這裡並不談論《石頭記》裡面那些薄命女子,而是以87版《紅樓夢》十二釵的美艷劇照為本,編寫出一個以文字繪製肖像的創意小程序——「Twelve Beauties of Jinling」。

金陵城中美人圖 https://www.zhihu.com/video/1043525785520451584

該程序我已在 OpenProcessing 上傳,獲取之 (Twelve Beauties of Jinling - OpenProcessing),然而其運行效果尚不理想,但倘若讀者利用 Processing 運行,它確實沒有問題。這可能是網站的 Bug,目前我也沒找到較好的解決辦法。

因此,我在 CSDN 上補發了一份完整的源代碼+資源,點擊這裡 (download.csdn.net/downl)。

以下,為其完整的源代碼:

/**
* Twelve_Beauties_of_Jinling
*
* By Hewes 18/11/6
* https://blog.csdn.net/Hewes
* Controls:
* MousePress - 切換美人圖
*
**/

//String[] imgNames = {"黛玉.jpg", "寶釵.jpg", "元春.jpg",
// "探春.jpg", "湘雲.jpg", "妙玉.jpg", "熙鳳.jpg", "惜春.jpg",
// "迎春.jpg", "巧姐.jpg", "李紈.jpg", "可卿.jpg"};
String[] imgNames = {"黛玉:欠淚的淚已盡.jpg", "寶釵:富貴的金銀散盡.jpg",
"元春:欲知命短問前生.jpg", "探春:分離聚合皆前定.jpg", "湘云:為官的家業凋零.jpg",
"妙玉:無情的分明報應.jpg", "熙鳳:痴迷的枉送了性命.jpg", "惜春:看破的遁入空門.jpg",
"迎春:欠命的命已還.jpg", "巧姐:有恩的死裡逃生.jpg", "李紈:老來富貴也真僥倖.jpg",
"可卿:冤冤相報豈非輕.jpg"};
PImage img, bg;
int imgIndex = 0, index=0;
String[] lines;
PFont font1, font2;
char[] chars;
String displayText;
float cx, cy, r, degree;
float minWeight = 2, maxWeight = 6, currWeight;
float spacing = maxWeight; // 字元間隔
float goldenRatio = (sqrt(5) + 1 ) / 2;
int iter = 0;

void setup() {
size(900, 900);
frameRate(30);
font1 = createFont("楷體", 10);
font2 = createFont("隸書", 80);
bg=loadImage("bg.jpg");
bg.resize(width, height);
textAlign(CENTER, CENTER);
lines=loadStrings("十二釵判詞.txt"); // 讀取並創建其各行的 String 數組
nextImage(); // 下一張肖像
}

void draw() {
pushMatrix();
translate(width/2-120, height/2);
if (cx>= 0 && 1.1*cx<= img.width && cy >= 0 && 1.1*cy<= img.height ) {
for (int i = 30; i > 0; --i) {
index = index % displayText.length(); // 遍歷文本
degree = (iter * goldenRatio) * 360; // 字元的角度
r = sqrt(iter++) * spacing;
// 計算字元的位置
calcCharPos(img.width/2, img.height/2, r, (degree % 360));
color pix = img.get((int)cx, (int)cy);
currWeight = map(brightness(pix), 255, 0, minWeight, maxWeight);
textSize(currWeight*2);
fill(pix);
text(chars[index], 1.3*(cx-img.width/2), 1.3*(cy-img.height/2));
index++;
}
}
popMatrix();
}

// 計算文字的位置
void calcCharPos(float x, float y, float radius, float angle) {
cx = x + cos(radians(angle))*(radius/2);
cy = y + sin(radians(angle))*(radius/2);
}

// 下一張肖像
void nextImage() {
background(bg);
textFont(font1);
img = loadImage(imgNames[imgIndex]);
img.resize(520, 520);
img.loadPixels(); // 將當前顯示窗口的快照載入到 pixels[] 數組中
displayText=loadText(lines[imgIndex]); // 文本更新載入
// 顯示美人名
textFont(font2);
fill(0, 80);
text(chars[0], 750, 350);
text(chars[1], 750, 550);
textFont(font1);
// 循環圖片索引
imgIndex += 1;
if (imgIndex >=imgNames.length) {
imgIndex = 0;
}
index = 0;
iter = 0;
cx = 0;
cy = 0;
}

// 載入字元,需輸入其索引
String loadText(String inText) {
String allText=join(lines, " ");
chars=new char[inText.length()];
int i=0;
int charPos = 0;
if (imgIndex==0) {
charPos=1;
}
char currChar; // 當前字元
// 遍歷片段內字元,保存到 displayText 中
while (charPos < inText.length()) {
currChar = inText.charAt(charPos);
charPos++;
chars[i]=currChar;
i++;
}
//println(new String(chars));
return new String(chars); // 返回將顯示的判詞
}

void mousePressed() {
nextImage(); // 下一張肖像
}

```
【**歡迎關注**】
***Hewes 的知乎專欄***:https://zhuanlan.zhihu.com/c_123529691
***Hewes 的 CSDN 博客***:https://blog.csdn.net

Last……

歡迎關注

Hewes 的知乎專欄:Hewes的編程藝術

Hewes 的 CSDN 博客:【Hewes的博客】十五好劍術,遍干諸侯。三十成文章,歷抵卿相。 - CSDN博客

推薦閱讀:

TAG:文字 | Processing(編程語言) | 紅樓夢十二釵 |